Passed
Push — master ( d1842b...7cb61a )
by Matteo
02:41
created

Cache::getString()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 23
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 5.009

Importance

Changes 0
Metric Value
cc 5
eloc 14
nc 5
nop 3
dl 0
loc 23
ccs 13
cts 14
cp 0.9286
crap 5.009
rs 8.5906
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Cacheasy;
5
6
use Cacheasy\NotCachedException;
7
use Cacheasy\MissingProviderException;
8
use Cacheasy\StringProvider;
9
use Cacheasy\JsonProvider;
10
11
class Cache
12
{
13
    /**
14
     * The path where to save the cached things
15
     */
16
    private $path;
17
    // Length of time to cache a file (in seconds)
18
    public $ttl;
19
20 10
    public function __construct(string $path = null, int $ttl = 3600 * 24 * 1)
21
    {
22 10
        $this->path = rtrim($path ?? getenv("CACHE_PATH"), "/");
23 10
        $this->ttl = $ttl ?? getenv("CACHE_TTL");
24 10
    }
25
26
    /**
27
     * This methods tries to hit the cache and if the content is not present
28
     * or expired caches it for future usage
29
     *
30
     * @param   string  $label  The key of the resource to cache
31
     * @param   StringProvider  $provider   The provider for the actual content
32
     * @param   bool    $forceFresh     A bool indicating whether or not to force a fresh call
33
     *
34
     * @throws  MissingProviderException    Thrown when a provider needs to be called but null is passed.
35
     *
36
     * @return  string   The fetched and/or cached data
37
     */
38 5
    public function getString(string $label, StringProvider $provider = null, bool $forceFresh = false) : string
39
    {
40 5
        if ($forceFresh) {
41
            // skipping everything, the user requested fresh data
42
            // he wants to wait, we better cache the fresh data
43 1
            if (!$provider) {
44
                throw new MissingProviderException($label);
45
            }
46 1
            $data = $provider->get();
47 1
            $this->cacheString($label, $data);
48 1
            return $data;
49
        }
50
        // let's check if we've got something cached already...
51
        try {
52 5
            return $this->hitString($label);
53 4
        } catch (NotCachedException $e) {
54
            // Oooopsss... we ain't got anything, let's get the fresh data (and cache them)
55 4
            if (!$provider) {
56 1
                throw new MissingProviderException($label);
57
            }
58 3
            $data = $provider->get();
59 3
            $this->cacheString($label, $data);
60 3
            return $data;
61
        }
62
    }
63
64
    /**
65
     * This methods tries to hit the cache and if the content is not present
66
     * or expired caches it for future usage
67
     *
68
     * @param   string  $label  The key of the resource to cache
69
     * @param   JsonProvider  $provider   The provider for the actual content
70
     * @param   bool    $forceFresh     A bool indicating whether or not to force a fresh call
71
     *
72
     * @throws  MissingProviderException    Thrown when a provider needs to be called but null is passed.
73
     *
74
     * @return  array   The fetched and/or cached data
75
     */
76 1
    public function getJson(string $label, JsonProvider $provider = null, bool $forceFresh = false) : array
77
    {
78 1
        if ($forceFresh) {
79
            // skipping everything, the user requested fresh data
80
            // he wants to wait, we better cache the fresh data
81
            if (!$provider) {
82
                throw new MissingProviderException($label);
83
            }
84
            $data = $provider->get();
85
            $this->cacheJson($label, $data);
86
            return $data;
87
        }
88
        // let's check if we've got something cached already...
89
        try {
90 1
            return json_decode($this->hitString($label), true);
91
        } catch (NotCachedException $e) {
92
            // Oooopsss... we ain't got anything, let's get the fresh data (and cache them)
93
            if (!$provider) {
94
                throw new MissingProviderException($label);
95
            }
96
            $data = $provider->get();
97
            $this->cacheJson($label, $data);
98
            return $data;
99
        }
100
    }
101
    
102
    /**
103
     * Actually writes the content to a file
104
     *
105
     * @param   string  $label  The key of the resource to cache
106
     * @param   string  $data   The actual content of the resource to cache
107
     */
108 4
    public function cacheString(string $label, string $data) : void
109
    {
110 4
        $filename = $this->path . "/" . md5($label);
111 4
        if (file_exists($filename) && is_file($filename)) {
112 2
            unlink($filename);
113
        }
114 4
        file_put_contents($filename, $data);
115 4
    }
116
117
    /**
118
     * Actually writes the json content to a file
119
     *
120
     * @param   string  $label  The key of the resource to cache
121
     * @param   array  $data   The actual content of the resource to cache
122
     */
123 1
    public function cacheJson(string $label, array $data) : void
124
    {
125 1
        $this->cacheString($label, json_encode($data));
126 1
    }
127
    
128
    /**
129
     * Tries to check if the content is cached
130
     *
131
     * @param   string  $label  The key of the cached resource
132
     *
133
     * @throws  NotCachedExeption   If the requested resource is not cached.
134
     *
135
     * @return  string  The content of the cached resource
136
     */
137 6
    public function hitString(string $label) : string
138
    {
139 6
        if ($this->isCached($label)) {
140 3
            $filename = $this->path . "/" . md5($label);
141 3
            return file_get_contents($filename);
142
        } else {
143 5
            throw new NotCachedException($label);
144
        }
145
    }
146
147
    /**
148
     * Tries to check if the content is cached
149
     *
150
     * @param   string  $label  The key of the cached resource
151
     *
152
     * @throws  NotCachedExeption   If the requested resource is not cached.
153
     *
154
     * @return  array  The content of the cached resource
155
     */
156
    public function hitJson(string $label) : array
157
    {
158
        return json_decode($this->hitString($label), true);
159
    }
160
    
161
    /**
162
     * Checks if the content is cached or not
163
     *
164
     * @param   string  $label  The key of the element to cache
165
     *
166
     * @return  bool    Whether the $label resource is cached
167
     */
168 9
    public function isCached(string $label) : bool
169
    {
170 9
        $filename = $this->path . "/" . md5($label);
171 9
        if (file_exists($filename) && (filemtime($filename) + $this->ttl >= time())) {
172 5
            return true;
173
        }
174 8
        return false;
175
    }
176
177
    /**
178
     * Invalidates an entry by deleting the corresponding file
179
     *
180
     * @param   string  $label  The key of the element to invalidate
181
     *
182
     * @throws  NotCachedException  Thrown when the resource $label is not cached.
183
     */
184 2
    public function invalidate(string $label) : void
185
    {
186 2
        if (!$this->isCached($label)) {
187 1
            throw new NotCachedException($label);
188
        }
189 1
        $filename = $this->path . "/" . md5($label);
190 1
        if (file_exists($filename)) {
191 1
            unlink($filename);
192
        }
193 1
    }
194
195
    /**
196
     * Invalidates all the cache entries by deleting the corresponding files
197
     */
198 1
    public function invalidateAll() : void
199
    {
200 1
        $files = glob($this->path . "/*"); // get all file names
201 1
        foreach ($files as $file) { // iterate files
202 1
            if (is_file($file)) {
203 1
                unlink($file); // delete file
204
            }
205
        }
206 1
    }
207
}
208