Completed
Push — master ( fb3e81...9a96e3 )
by Oskar
04:01
created

CCachePool::initCache()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 19
ccs 13
cts 13
cp 1
rs 9.4285
cc 2
eloc 11
nc 2
nop 0
crap 2
1
<?php
2
3
namespace Anax\Cache;
4
5
/**
6
 *
7
 */
8
class CCachePool implements \Psr\Cache\CacheItemPoolInterface
9
{
10
    /**
11
     * An array with all cache items,
12
     * @var \Psr\Cache\CacheItemInterface[]
13
     */
14
    private $cacheItems;
15
16
    /**
17
     * An array of items to be saved later
18
     * @var \Psr\Cache\CacheItemInterface[]
19
     */
20
    private $defferedItems;
21
22
    /**
23
     * The path to the cache items
24
     * @var string
25
     */
26
    static public $path;
27
28
    /**
29
     * Inits one array with the cached items and one with the deffered
30
     *
31
     */
32 12
    public function __construct()
33
    {
34
        //$this->cacheItems    = isset($_SESSION['cacheItems']) ? $_SESSION['cacheItems'] : [];
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
35 12
        $this->defferedItems = [];
36
37 12
        $this->path = self::getPath();
38
39
        // Creates a writable cache folder on the server
40 11
        if (!is_dir($this->path)) {
41 2
            mkdir($this->path, 0777, true);
42 1
        }
43
44 9
        $this->cacheItems = array();
45 9
        $this->initCache();
46 7
    }
47
48
    /**
49
     * Used to fill the array with existing cache items
50
     *
51
     * @return void
52
     */
53 9
    private function initCache()
54
    {
55
        // Init the cacheitems
56 9
        $files = glob($this->path . '/*.val');
57 8
        $expirations = glob($this->path . '/*.meta');
58
59 7
        sort($files);
60 7
        sort($expirations);
61
62 7
        $count = COUNT($files);
63
64 7
        for ($i = 0; $i < $count; $i++) {
65 4
            $key = basename($files[$i]);
66 4
            $key = preg_replace('/\\.[^.\\s]{3,4}$/', '', $key);
67
68 4
            $expiration = unserialize(file_get_contents($expirations[$i]));
69 4
            $this->cacheItems[] = new \Anax\Cache\CCacheFile($key, null, $expiration);
70 4
        }
71 7
    }
72
73
    /**
74
     * Returns the path where the cache items are stored
75
     * @return string The path
76
     */
77 12
    public static function getPath()
78
    {
79 12
        return  __DIR__ . "/../../cacheitems/";
80
    }
81
82
    /**
83
     * Returns a Cache Item representing the specified key.
84
     *
85
     * This method must always return a CacheItemInterface object, even in case of
86
     * a cache miss. It MUST NOT return null.
87
     *
88
     * @param string $key
89
     *   The key for which to return the corresponding Cache Item.
90
     *
91
     * @throws InvalidArgumentException
92
     *   If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException
93
     *   MUST be thrown.
94
     *
95
     * @return \Psr\Cache\CacheItemInterface
96
     *   The corresponding Cache Item.
97
     */
98 5
    public function getItem($key)
99
    {
100
        // Checks if the key is valid
101 5
        $this->checkKey($key);
102
103
        // Iterate all items to find the right match
104 5
        foreach ($this->cacheItems as $cacheItem) {
105 4
            if ($cacheItem->getKey() == $key) {
106
                return $cacheItem;
107
            }
108 5
        }
109
110
        // If the item was not found in the current array, a new item is created and added to the array
111 5
        $item = new \Anax\Cache\CCacheFile($key);
112 5
        $this->cacheItems[] = $item;
113
114 5
        return $item;
115
    }
116
117
    /**
118
     * Generates a key from a string.
119
     *
120
     * @param string $str
121
     *   The value to convert to a key-string, must be unique
122
     *
123
     * @return string
124
     *   A generated key-string
125
     */
126
    public function generateKey($str)
127
    {
128
        $strEncoded = base64_encode($str);
129
        return 'ch_' . md5($strEncoded);
130
    }
131
132
    /**
133
     * Checks if a key string is valid, invalid values are {}()/\@:
134
     *
135
     * @param string $key
136
     * A string to ckeck, invalid values are {}()/\@:
137
     *
138
     * @throws InvalidArgumentException
139
     * If $key are not a legal value
140
     *
141
     * @return void
142
     */
143 7
    public function checkKey($key)
144
    {
145
        // The characters that are not legal/is invalid
146 7
        $invalidValues = "/[\/\{\}\(\)\@\:\.\\\]/";
147
148
        // Checks for matches in the key
149 7
        if (preg_match_all($invalidValues, $key, $matches)) {
150 1
            throw new \Anax\Cache\InvalidKeyException($matches);
151
        }
152 6
    }
153
154
    /**
155
     * Returns a traversable set of cache items.
156
     *
157
     * @param array $keys
158
     * An indexed array of keys of items to retrieve.
159
     * @throws InvalidArgumentException
160
     *   If any of the keys in $keys are not a legal value a \Psr\Cache\InvalidArgumentException
161
     *   MUST be thrown.
162
     *
163
     * @return array|\Traversable
164
     *   A traversable collection of Cache Items keyed by the cache keys of
165
     *   each item. A Cache item will be returned for each key, even if that
166
     *   key is not found. However, if no keys are specified then an empty
167
     *   traversable MUST be returned instead.
168
     */
169
    public function getItems(array $keys = array())
170
    {
171
        // Validating the keys
172
        foreach ($keys as $key) {
173
            $this->checkKey($key);
174
        }
175
176
        // Iterates all keys and gets the associated item
177
        $items = array();
178
        $nKeys = count($keys);
179
        for ($i=0; $i < $nKeys; $i++) {
180
            $items[(string) $keys[$i]] = $this->getItem($keys[$i]);
181
        }
182
183
        return $items;
184
    }
185
186
    /**
187
     * Confirms if the cache contains specified cache item.
188
     *
189
     * Note: This method MAY avoid retrieving the cached value for performance reasons.
190
     * This could result in a race condition with CacheItemInterface::get(). To avoid
191
     * such situation use CacheItemInterface::isHit() instead.
192
     *
193
     * @param string $key
194
     *    The key for which to check existence.
195
     *
196
     * @throws InvalidArgumentException
197
     *   If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException
198
     *   MUST be thrown.
199
     *
200
     * @return bool
201
     *  True if item exists in the cache, false otherwise.
202
     */
203
    public function hasItem($key)
204
    {
205
        //Validates the key
206
        $this->checkKey($key);
207
208
        // is_file
209
210
        foreach ($this->cacheItems as $cacheItem) {
211
            if ($cacheItem->getKey() == $key) {
212
                return true;
213
            }
214
        }
215
        return false;
216
    }
217
218
    /**
219
     * Deletes all items in the pool.
220
     *
221
     * @return bool
222
     *   True if the pool was successfully cleared. False if there was an error.
223
     */
224
    public function clear()
225
    {
226
        $this->cacheItems = array();
227
        $this->defferedItems = array();
228
229
        $files = glob($this->path . '/*');
230
231
        if (!array_map('unlink', $files)) {
232
            return false;
233
        }
234
235
        return true;
236
    }
237
238
    /**
239
     * Removes the item from the pool.
240
     *
241
     * @param string $key
242
     *   The key for which to delete
243
     *
244
     * @throws InvalidArgumentException
245
     *   If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException
246
     *   MUST be thrown.
247
     *
248
     * @return bool
249
     *   True if the item was successfully removed. False if there was an error.
250
     */
251 1
    public function deleteItem($key)
252
    {
253
        //Checks if the key is valid
254 1
        $this->checkKey($key);
255
256 1
        foreach ($this->cacheItems as $cacheItem) {
257
            if ($key == $cacheItem->getKey()) {
258
                $file = $cacheItem->filename($cacheItem->getKey());
259
                if (is_file($file)) {
260
                    unlink($file);
261
                    unset($cacheItem);
262
                } else {
263
                    return false;
264
                }
265
                return true;
266
            }
267 1
        }
268 1
        return false;
269
    }
270
271
    /**
272
     * Removes multiple items from the pool.
273
     *
274
     * @param array $keys
275
     *   An array of keys that should be removed from the pool.
276
277
     * @throws InvalidArgumentException
278
     *   If any of the keys in $keys are not a legal value a \Psr\Cache\InvalidArgumentException
279
     *   MUST be thrown.
280
     *
281
     * @return bool
282
     *   True if the items were successfully removed. False if there was an error.
283
     */
284 1
    public function deleteItems(array $keys)
285
    {
286
        //Checks if the keys are valid
287 1
        foreach ($keys as $key) {
288 1
            $this->checkKey($key);
289 1
        }
290
291 1
        foreach ($keys as $key) {
292 1
            if (!$this->deleteItem($key)) {
293 1
                return false;
294
            }
295
        }
296
        return true;
297
    }
298
299
    /**
300
     * Persists a cache item immediately.
301
     *
302
     * @param \Psr\Cache\CacheItemInterface $item
303
     *   The cache item to save.
304
     *
305
     * @return bool
306
     *   True if the item was successfully persisted. False if there was an error.
307
     */
308 2
    public function save(\Psr\Cache\CacheItemInterface $item)
309
    {
310
        // Gets the filename
311 2
        $file = $item->filename($item->getKey());
312
313
        // Checks if the file write failes and serializes the value
314 2
        if (!file_put_contents($file, serialize($item->getValue()))) {
315
            return false;
316
        }
317
318 2
        $file = $item->filename($item->getKey(), 'expiration');
319
320
        // Checks if the file write failes and serializes the value
321 2
        if (!file_put_contents($file, serialize($item->expiration))) {
0 ignored issues
show
Bug introduced by
Accessing expiration on the interface Psr\Cache\CacheItemInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
322
            return false;
323
        }
324
325 2
        return true;
326
    }
327
328
    /**
329
     * Sets a cache item to be persisted later.
330
     *
331
     * @param \Psr\Cache\CacheItemInterface $item
332
     *   The cache item to save.
333
     *
334
     * @return bool
335
     *   False if the item could not be queued or if a commit was attempted and failed. True otherwise.
336
     */
337 1
    public function saveDeferred(\Psr\Cache\CacheItemInterface $item)
338
    {
339
        // Checks if the item is already saved as deffered
340 1
        foreach ($this->defferedItems as $defferedItem) {
341 1
            if ($defferedItem->getKey() == $item->getKey()) {
342 1
                return false;
343
            }
344 1
        }
345
346
        // Adds the item to the array of deffered items and returns true if it was successfull
347 1
        if (array_push($this->defferedItems, $item)) {
348 1
            return true;
349
        }
350
351
        return false;
352
    }
353
354
    /**
355
     * Persists any deferred cache items.
356
     *
357
     * @return bool
358
     *   True if all not-yet-saved items were successfully saved or there were none. False otherwise.
359
     */
360 1
    public function commit()
361
    {
362
        // Saves all items in $defferedItems
363 1
        foreach ($this->defferedItems as $item) {
364 1
            if (!$this->save($item)) {
365
                return false;
366
            }
367 1
        }
368
369
        // Resets the deffered array
370 1
        $this->defferedItems = array();
371 1
        return true;
372
    }
373
}
374