Completed
Push — master ( 26da3a...b9da65 )
by Marco
03:37
created

ApcCache   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 287
Duplicated Lines 16.38 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 78.26%

Importance

Changes 3
Bugs 1 Features 0
Metric Value
wmc 32
c 3
b 1
f 0
lcom 1
cbo 2
dl 47
loc 287
ccs 72
cts 92
cp 0.7826
rs 9.6

9 Methods

Rating   Name   Duplication   Size   Complexity  
B get() 0 37 5
B delete() 9 31 5
A flush() 0 9 2
A setNamespaceKey() 9 9 2
A getNamespaceKey() 0 5 1
A getApcStatus() 0 5 3
A __construct() 23 23 3
B set() 0 56 8
B status() 6 32 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php namespace Comodojo\Cache;
2
3
use \Comodojo\Cache\CacheObject\CacheObject;
4
use \Comodojo\Exception\CacheException;
5
use \Exception;
6
7
/**
8
 * Apc cache class
9
 * 
10
 * @package     Comodojo Spare Parts
11
 * @author      Marco Giovinazzi <[email protected]>
12
 * @license     MIT
13
 *
14
 * LICENSE:
15
 * 
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
25
class ApcCache extends CacheObject {
26
27
    /**
28
     * Class constructor
29
     *
30
     * @throws \Comodojo\Exception\CacheException
31
     */
32 51 View Code Duplication
    public function __construct(\Monolog\Logger $logger = null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
33
34
        try {
35
            
36 51
            parent::__construct($logger);
37
            
38
        }
39
        
40 51
        catch (CacheException $ce) {
41
            
42
            throw $ce;
43
            
44
        }
45
46 51
        if ( self::getApcStatus() === false ) {
47
48 17
            $this->raiseError("Apc extension not available, disabling cache administratively");
49
50 17
            $this->disable();
51
52 17
        }
53
54 51
    }
55
56
    /**
57
     * Set cache element
58
     *
59
     * This method will throw only logical exceptions.
60
     * In case of failures, it will return a boolean false.
61
     *
62
     * @param   string  $name    Name for cache element
63
     * @param   mixed   $data    Data to cache
64
     * @param   int     $ttl     Time to live
65
     *
66
     * @return  bool
67
     * @throws \Comodojo\Exception\CacheException
68
     */
69 12
    public function set($name, $data, $ttl = null) {
70
71 12
        if ( empty($name) ) throw new CacheException("Name of object cannot be empty");
72
73 12
        if ( is_null($data) ) throw new CacheException("Object content cannot be null");
74
75
        // simply return false if cache is disabled
76 12
        if ( !$this->isEnabled() ) return false;
77
78
        // reset error state, just in case
79 8
        $this->resetErrorState();
80
81
        try {
82
            
83 8
            $this->setTtl($ttl);
84
85 8
            $namespace = $this->getNamespaceKey();
86
87 8
            if ( $namespace === false ) $namespace = $this->setNamespaceKey();
88
89
            // if namespace is still false, raise an error and exit gracefully
90 8
            if ( $namespace === false ) {
91
92
                $this->raiseError("Error writing cache (APC), exiting gracefully");
93
94
                $this->setErrorState();
95
96
                $return = false;
97
98
            } else {
99
100 8
                $shadowName = $namespace."-".md5($name);
101
            
102 8
                $shadowTtl = $this->ttl;
103
104 8
                $return = apc_store($shadowName, $data, $shadowTtl);
105
106 8
                if ( $return === false ) {
107
108
                    $this->raiseError("Error writing cache (APC), exiting gracefully");
109
110
                    $this->setErrorState();
111
112
                }
113
114
            }
115
116 8
        } catch (CacheException $ce) {
117
            
118
            throw $ce;
119
120
        }
121
122 8
        return $return;
123
124
    }
125
126
    /**
127
     * Get cache element
128
     *
129
     * This method will throw only logical exceptions.
130
     * In case of failures, it will return a null value.
131
     * In case of cache not found, it will return a null value.
132
     *
133
     * @param   string  $name    Name for cache element
134
     *
135
     * @return  mixed
136
     * @throws \Comodojo\Exception\CacheException
137
     */
138 12
    public function get($name) {
139
140 12
        if ( empty($name) ) throw new CacheException("Name of object cannot be empty");
141
142 12
        if ( !$this->isEnabled() ) return null;
143
144 10
        $this->resetErrorState();
145
146 10
        $namespace = $this->getNamespaceKey();
147
148 10
        if ( $namespace === false ) {
149
150 6
            $return = null;
151
152 6
        } else {
153
154 6
            $shadowName = $namespace."-".md5($name);
155
156 6
            $success = null;
157
158 6
            $return = apc_fetch($shadowName, $success);
159
160 6
            if ( $success === false ) {
161
162
                $this->raiseError("Error reading cache (APC), exiting gracefully");
163
164
                $this->setErrorState();
165
166
                $return = null;
167
168
            }
169
170
        }
171
172 10
        return $return;
173
174
    }
175
176
    /**
177
     * Delete cache object (or entire namespace if $name is null)
178
     *
179
     * This method will throw only logical exceptions.
180
     * In case of failures, it will return a boolean false.
181
     *
182
     * @param   string  $name    Name for cache element
183
     *
184
     * @return  bool
185
     * @throws \Comodojo\Exception\CacheException
186
     */
187 3
    public function delete($name = null) {
188
189 3
        if ( !$this->isEnabled() ) return false;
190
191 2
        $this->resetErrorState();
192
193 2
        $namespace = $this->getNamespaceKey();
194
195 2
        if ( $namespace === false ) return true;
196
197 2 View Code Duplication
        if ( empty($name) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
198
199
            $delete = apc_delete($this->getNamespace());
200
201
        } else {
202
203 2
            $delete = apc_delete($namespace."-".md5($name));
204
205
        }
206
207 2
        if ( $delete === false ) {
208
209
            $this->raiseError("Error deleting cache (APC), exiting gracefully");
210
211
            $this->setErrorState();
212
213
        }
214
215 2
        return $delete;
216
217
    }
218
219
    /**
220
     * Clean cache objects in all namespaces
221
     *
222
     * This method will throw only logical exceptions.
223
     *
224
     * @return  bool
225
     */
226 3
    public function flush() {
227
228 3
        if ( !$this->isEnabled() ) return false;
229
230 2
        $result = apc_clear_cache("user");
231
232 2
        return $result;
233
234
    }
235
236
    /**
237
     * Get cache status
238
     *
239
     * @return  array
240
     */
241 3
    public function status() {
242
243 3 View Code Duplication
        if ( !$this->isEnabled() ) return array(
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
244 1
            "provider"  => "apc",
245 1
            "enabled"   => false,
246 1
            "objects"   => null,
247 1
            "options"   => array()
248 1
        );
249
250 2
        $stats = apc_cache_info("user", true);
251
252 2
        if ( isset($stats["num_entries"]) ) {
253
254 2
            $objects = $stats["num_entries"];
255
256 2
        } else {
257
258
            // some APC extensions do not return the "num_entries", so let's try to calculate it
259
            $stats_2 = apc_cache_info("user");
260
261
            $objects = sizeof($stats_2["cache_list"]);
262
263
        }
264
265
        return array(
266 2
            "provider"  => "apc",
267 2
            "enabled"   => $this->isEnabled(),
268 2
            "objects"   => intval($objects),
269
            "options"   => $stats
270 2
        );
271
272
    }
273
274
    /**
275
     * Set namespace key
276
     *
277
     * @return  mixed
278
     */
279 4 View Code Duplication
    private function setNamespaceKey() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
280
281 4
        $uId = self::getUniqueId();
282
283 4
        $return = apc_store($this->getNamespace(), $uId, 0);
284
285 4
        return $return === false ? false : $uId;
286
287
    }
288
289
    /**
290
     * Get namespace key
291
     *
292
     * @return  string
293
     */
294 16
    private function getNamespaceKey() {
295
296 16
        return apc_fetch($this->getNamespace());
297
298
    }
299
300
    /**
301
     * Check APC availability
302
     *
303
     * @return  bool
304
     */
305 51
    private static function getApcStatus() {
306
307 51
        return ((extension_loaded('apc') || extension_loaded('apc')) && ini_get('apc.enabled'));
308
309
    }
310
311
}
312