Apc::clear()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
namespace FMUP\Cache\Driver;
3
4
use FMUP\Cache\CacheInterface;
5
use FMUP\Cache\Exception;
6
7
/**
8
 * Class Apc
9
 * This driver needs APC installed on server to work properly
10
 * @package FMUP\Cache\Driver
11
 */
12
class Apc implements CacheInterface
13
{
14
    /**
15
     * @var array
16
     */
17
    private $settings = array();
18
    private $isAvailable = null;
19
20
    const SETTING_CACHE_TYPE = 'SETTING_CACHE_TYPE';
21
    const SETTING_CACHE_TTL = 'SETTING_CACHE_TTL';
22
    const SETTING_CACHE_PREFIX = 'SETTING_CACHE_PREFIX';
23
24
    const CACHE_TTL_DEFAULT = 0;
25
26
    const CACHE_TYPE_USER = 'user';
27
    const CACHE_TYPE_FILE_HITS = 'filehits';
28
    const CACHE_TYPE_OP_CODE = 'opcode';
29
30
    /**
31
     * constructor of File
32
     * @param array $settings
33
     */
34 22
    public function __construct($settings = array())
35
    {
36 22
        $this->setSettings($settings);
37 22
    }
38
39
    /**
40
     * Can define settings of the component
41
     * @param array $settings
42
     * @return $this
43
     */
44 22
    public function setSettings($settings = array())
45
    {
46 22
        $this->settings = $settings;
47 22
        return $this;
48
    }
49
50
    /**
51
     * Get defined value for specified cache key
52
     * @param string $key
53
     * @return mixed
54
     * @throws Exception
55
     */
56 3
    public function get($key)
57
    {
58 3
        if (!$this->isAvailable()) {
59 1
            throw new Exception('APC is not available');
60
        }
61 2
        $key = $this->getCacheKey($key);
62 2
        $success = null;
63 2
        $return = $this->apcFetch($key, $success);
64 2
        if (false === $success) {
65 1
            throw new Exception('Unable to get ' . $key . ' from APC');
66
        }
67 1
        return $return;
68
    }
69
70
    /**
71
     * @param string $key
72
     * @param bool &$success
73
     * @return mixed
74
     * @codeCoverageIgnore
75
     */
76
    protected function apcFetch($key, &$success)
77
    {
78
        return apc_fetch($key, $success);
79
    }
80
81
    /**
82
     * Check whether key exists or not
83
     * @param string $key
84
     * @return bool
85
     * @throws Exception
86
     */
87 2
    public function has($key)
88
    {
89 2
        if (!$this->isAvailable()) {
90 1
            throw new Exception('APC is not available');
91
        }
92 1
        $key = $this->getCacheKey($key);
93 1
        return (bool)$this->apcExists($key);
94
    }
95
96
    /**
97
     * @param string $key
98
     * @return bool|\string[]
99
     * @codeCoverageIgnore
100
     */
101
    protected function apcExists($key)
102
    {
103
        return apc_exists($key);
104
    }
105
106
    /**
107
     * Delete a specified key in cache
108
     * @param string $key
109
     * @return $this
110
     * @throws Exception
111
     */
112 5
    public function remove($key)
113
    {
114 5
        if (!$this->isAvailable()) {
115 1
            throw new Exception('APC is not available');
116
        }
117 4
        $key = $this->getCacheKey($key);
118 4
        if ($this->getCacheType() == self::CACHE_TYPE_OP_CODE) {
119 2
            $success = $this->apcDeleteFile($key);
120
        } else {
121 2
            $success = $this->apcDelete($key);
122
        }
123 4
        if (!$success) {
124 2
            throw new Exception('Unable to delete key from cache APC');
125
        }
126 2
        return $this;
127
    }
128
129
    /**
130
     * @param string $key
131
     * @return bool|\string[]
132
     * @codeCoverageIgnore
133
     */
134
    protected function apcDelete($key)
135
    {
136
        return apc_delete($key);
137
    }
138
139
    /**
140
     * @param string $key
141
     * @return bool|\string[]
142
     * @codeCoverageIgnore
143
     */
144
    protected function apcDeleteFile($key)
145
    {
146
        return apc_delete_file($key);
147
    }
148
149
    /**
150
     * Define a value in cache for a specified name
151
     * @param string $key
152
     * @param mixed $value
153
     * @return $this
154
     * @throws Exception
155
     */
156 3
    public function set($key, $value)
157
    {
158 3
        if (!$this->isAvailable()) {
159 1
            throw new Exception('APC is not available');
160
        }
161 2
        $key = $this->getCacheKey($key);
162 2
        $ttl = $this->getSetting(self::SETTING_CACHE_TTL)
163 1
            ? (int)$this->getSetting(self::SETTING_CACHE_TTL)
164 2
            : self::CACHE_TTL_DEFAULT;
165 2
        if (!$this->apcStore($key, $value, $ttl) && !$this->apcAdd($key, $value, $ttl)) {
166 1
            throw new Exception('Unable to set key into cache APC');
167
        }
168 1
        return $this;
169
    }
170
171
    /**
172
     * @param string $key
173
     * @param mixed $value
174
     * @param int $ttl
175
     * @return bool
176
     * @codeCoverageIgnore
177
     */
178
    protected function apcAdd($key, $value, $ttl = 0)
179
    {
180
        return apc_add($key, $value, $ttl);
181
    }
182
183
    /**
184
     * @param string|array $key
185
     * @param mixed $value
186
     * @param int $ttl
187
     * @return array|bool
188
     * @codeCoverageIgnore
189
     */
190
    protected function apcStore($key, $value, $ttl = 0)
191
    {
192
        return apc_store($key, $value, $ttl);
193
    }
194
195
    /**
196
     * Clear specified cache type
197
     * @return bool
198
     * @throws Exception
199
     */
200 3
    public function clear()
201
    {
202 3
        if (!$this->isAvailable()) {
203 1
            throw new Exception('APC is not available');
204
        }
205 2
        return $this->apcClearCache($this->getCacheType());
206
    }
207
208
    /**
209
     * @param string $cacheType
210
     * @return bool
211
     * @codeCoverageIgnore
212
     */
213
    protected function apcClearCache($cacheType = '')
214
    {
215
        return apc_clear_cache($cacheType);
216
    }
217
218
    /**
219
     * Get information for specified cache type
220
     * @param bool $limited (default false) If limited is TRUE, the return value will exclude the individual list
221
     *                                      of cache entries.
222
     *                                      This is useful when trying to optimize calls for statistics gathering.
223
     * @return array|bool
224
     * @throws Exception
225
     */
226 3
    public function info($limited = false)
227
    {
228 3
        if (!$this->isAvailable()) {
229 1
            throw new Exception('APC is not available');
230
        }
231 2
        return $this->apcCacheInfo($this->getCacheType(), (bool)$limited);
232
    }
233
234
    /**
235
     * @param string $cacheType
236
     * @param bool|false $limited
237
     * @return array|bool
238
     * @codeCoverageIgnore
239
     */
240
    protected function apcCacheInfo($cacheType, $limited = false)
241
    {
242
        return apc_cache_info($cacheType, (bool)$limited);
243
    }
244
245
    /**
246
     * Define a setting
247
     * @param string $name
248
     * @param mixed $value
249
     * @return $this
250
     */
251 3
    public function setSetting($name, $value)
252
    {
253 3
        $this->settings[$name] = $value;
254 3
        return $this;
255
    }
256
257
    /**
258
     * Retrieve a defined setting
259
     * @param string $name
260
     * @return mixed
261
     */
262 13
    public function getSetting($name)
263
    {
264 13
        return isset($this->settings[$name]) ? $this->settings[$name] : null;
265
    }
266
267
    /**
268
     * Get defined cache type
269
     * @return string
270
     */
271 8
    private function getCacheType()
272
    {
273 8
        $type = $this->getSetting(self::SETTING_CACHE_TYPE);
274 8
        if (!$type) {
275 5
            return self::CACHE_TYPE_OP_CODE;
276
        }
277 3
        return $type;
278
    }
279
280
    /**
281
     * Check whether apc is available
282
     * @return bool
283
     */
284 1
    public function isAvailable()
285
    {
286 1
        if (is_null($this->isAvailable)) {
287 1
            $iniValue = ini_get('apc.enabled');
288 1
            $iniEnabled = ($iniValue == 1 || strtolower($iniValue) == 'on');
289 1
            $this->isAvailable = function_exists('apc_clear_cache') && $iniEnabled;
290
        }
291 1
        return $this->isAvailable;
292
    }
293
294
    /**
295
     * Get cache key with prefix
296
     * @param string $key
297
     * @return string
298
     */
299 8
    protected function getCacheKey($key)
300
    {
301 8
        $prefix = (string)$this->getSetting(self::SETTING_CACHE_PREFIX);
302 8
        return $prefix . $key;
303
    }
304
}
305