Completed
Push — master ( fef623...fb3e81 )
by Oskar
05:08
created

CCachePool::checkKey()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 14
ccs 7
cts 7
cp 1
rs 9.4286
cc 3
eloc 7
nc 3
nop 1
crap 3
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
     * Inits one array with the cached items and one with the deffered
24
     *
25
     */
26 13
    public function __construct()
0 ignored issues
show
Coding Style introduced by
__construct uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

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

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
335
    {
336 1
        if ($value) {
337 1
            $_SESSION['cacheItems']    = $this->cacheItems;
338 1
            $_SESSION['defferedItems'] = $this->defferedItems;
339 1
        }
340 1
    }
341
342
    /**
343
     * Clears the current session
344
     *
345
     * @return void
346
     */
347 2
    public function clearSession()
0 ignored issues
show
Coding Style introduced by
clearSession uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
348
    {
349 2
        if (isset($_SESSION['cacheItems'])) {
350 1
            unset($_SESSION['cacheItems']);
351 1
        }
352 2
        if (isset($_SESSION['defferedItems'])) {
353 1
            unset($_SESSION['defferedItems']);
354 1
        }
355 2
    }
356
}
357