Completed
Push — master ( ee941a...979257 )
by Dan
12:15 queued 05:20
created

FileStorage   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 171
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 97.67%

Importance

Changes 0
Metric Value
wmc 17
lcom 1
cbo 1
dl 0
loc 171
ccs 42
cts 43
cp 0.9767
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 4
A set() 0 14 2
A _createCacheItem() 0 13 2
A has() 0 20 3
A get() 0 13 2
A delete() 0 4 1
A clear() 0 13 3
1
<?php
2
/**
3
 * Src/Cache/Storage/FileStorage.php
4
 *
5
 * @package     Ds\Cache\Storage
6
 * @subpackage  Cache
7
 * @author      Dan Smith <[email protected]>
8
 * @version     v.1 (20/03/2017)
9
 * @copyright   Copyright (c) 2017, Dan Smith
10
 */
11
namespace Ds\Cache\Storage;
12
13
use \DateInterval;
14
15
/**
16
 * Class NullStorage
17
 *
18
 * @package Ds\Cache
19
 */
20
class FileStorage extends AbstractStorage
21
{
22
    /**
23
     * @var string
24
     */
25
    private $fs;
26
27
    /**
28
     * @var string
29
     */
30
    private $ext = 'cache';
31
32
    /**
33
     * File Storage constructor.
34
     *
35
     * @param string $file
36
     * @param DateInterval $ttl
37
     * @throws \Exception
38
     */
39 7
    public function __construct($file, DateInterval $ttl)
40
    {
41 7
        if (!is_string($file)){
42 1
            throw new \Exception('Directory must be a valid string');
43
        }
44
45 7
        $this->fs = $file;
46
47 7
        if(!@mkdir($this->fs, 0755) && !is_dir($this->fs)){
48
            throw new \Exception('unable to create directory');
49
        }
50
51 7
        parent::__construct($ttl);
52 7
    }
53
54
    /**
55
     * Persists data in the cache, uniquely referenced by a key with an optional expiration TTL time.
56
     *
57
     * @param \string   $key   The key of the item to store.
58
     * @param mixed    $value The value of the item to store, must be serializable.
59
     * @param null|\int $ttl   Optional. The TTL value of this item. If no value is sent and
60
     *                                     the driver supports TTL then the library may set a default value
61
     *                                     for it or let the driver take care of that.
62
     *
63
     * @return bool True on success and false on failure.
64
     */
65 4
    public function set($key, $value, $ttl = null)
66
    {
67 4
        $ttl = time() + $this->getTtlTimestamp($ttl);
68
69 4
        $cacheItem = $this->_createCacheItem($key, $value, $ttl);
70
71 4
        \file_put_contents($cacheItem['file'],$cacheItem['data']);
72
73 4
        if (!file_exists($cacheItem['file'])){
74
            return false;
75
        }
76
77 4
        return true;
78
    }
79
80
    /**
81
     * Create cache item.
82
     *
83
     * @param string $key
84
     * @param $value
85
     * @param int $ttl
86
     * @return array
87
     * @throws \Exception
88
     */
89 4
    private function _createCacheItem($key, $value, $ttl){
90
91 4
        if (!is_string($key)){
92
            throw new \Exception('$key must be a valid string');
93
        }
94
95 4
        $filename = implode('.',[$key,$this->ext]);
96
97
        return [
98 4
            'file' => $this->fs . DIRECTORY_SEPARATOR . $filename,
99 4
            'data' => json_encode([$ttl, $value])
100
        ];
101
    }
102
103
    /**
104
     * Determines whether an item is present in the cache.
105
     *
106
     * NOTE: It is recommended that has() is only to be used for cache warming type purposes
107
     * and not to be used within your live applications operations for get/set, as this method
108
     * is subject to a race condition where your has() will return true and immediately after,
109
     * another script can remove it making the state of your app out of date.
110
     *
111
     * @param string $key The cache item key.
112
     *
113
     * @return bool
114
     */
115 4
    public function has($key){
116
117 4
       $cacheFile = implode('.',[$key,$this->ext]);
118 4
       $cacheLocation = $this->fs . DIRECTORY_SEPARATOR . $cacheFile;
119
120 4
       if (!file_exists($cacheLocation)){
121 1
           return false;
122
       }
123
124 3
       $data = \file_get_contents($cacheLocation);
125 3
       $cacheData = json_decode($data, TRUE);
126
127
       //cache has expired
128 3
       if ($cacheData[0] < time() ){
129 1
           \unlink($cacheLocation);
130 1
           return false;
131
       }
132
133 2
       return true;
134
    }
135
136
    /**
137
     * Fetches a value from the cache.
138
     *
139
     * @param string $key     The unique key of this item in the cache.
140
     *
141
     * @return mixed The value of the item from the cache, or $default in case of cache miss.
142
     *
143
     */
144 1
    public function get($key){
145
146 1
        $cacheFile = implode('.',[$key,$this->ext]);
147 1
        $cacheLocation = $this->fs . DIRECTORY_SEPARATOR . $cacheFile;
148
149 1
        if ($this->has($key)){
150 1
            $data = \file_get_contents($cacheLocation);
151 1
            $cacheData = json_decode($data, TRUE);
152 1
            return $cacheData[1];
153
        }
154
155
        return null;
156
    }
157
158
159
160
    /**
161
     * Delete an item from the cache by its unique key.
162
     *
163
     * @param string $key The unique cache key of the item to delete.
164
     *
165
     * @return bool True if the item was successfully removed. False if there was an error.
166
     */
167
    public function delete($key)
168
    {
169
        return true;
170
    }
171
172
    /**
173
     * Wipes clean the entire cache's keys.
174
     *
175
     * @return bool True on success and false on failure.
176
     */
177 1
    public function clear(){
178 1
        if (is_dir( $this->fs )){
179 1
            array_map('unlink', glob("$this->fs/*.*"));
180
        }
181
182 1
        $data = glob("$this->fs/*.*");
183
184 1
        if (!empty($data)){
185
            return false;
186
        }
187
188 1
        return true;
189
    }
190
}
191