Completed
Push — master ( ecfeff...c95134 )
by
unknown
01:46
created

LogDecorator::increment()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 9
c 0
b 0
f 0
dl 0
loc 13
ccs 10
cts 10
cp 1
rs 9.9666
cc 3
nc 1
nop 2
crap 3
1
<?php
2
3
namespace Vectorface\Cache;
4
5
use InvalidArgumentException;
6
use Psr\Log\LoggerInterface;
7
use Vectorface\Cache\Exception\CacheException;
8
9
/**
10
 * Decorates (Wraps) a Cache implementation with logging
11
 *
12
 * Note:
13
 *   This logs an estimated serialized object size. Cache serialization may
14
 *   use a different serialization mechanism, so the size should be used to
15
 *   give an idea of actual cached size rather than an exact value.
16
 */
17
class LogDecorator implements Cache, AtomicCounter
18
{
19
    /**
20
     * The wrapped cache class
21
     * @var Cache|AtomicCounter
22
     */
23
    private $cache;
24
25
    /**
26
     * The logger instance to which operations will be logged
27
     *
28
     * @var LoggerInterface
29
     */
30
    private $log;
31
32
    /**
33
     * The log level, which corresponds to a PSR-3 log level function call
34
     *
35
     * @var string
36
     */
37
    private $level;
38
39
    /**
40
     * @param Cache|AtomicCounter $cache
41
     * @param LoggerInterface $log
42
     * @param string $level
43
     */
44 4
    public function __construct(Cache $cache, LoggerInterface $log = null, $level = 'debug')
45
    {
46 4
        $levels = ['emergency', 'alert', 'critical', 'error', 'warning', 'notice', 'info', 'debug'];
47 4
        if (!in_array($level, $levels)) {
48 1
            throw new InvalidArgumentException("Incompatible log level: $level");
49
        }
50
51 3
        $this->cache = $cache;
52 3
        $this->log = $log;
53 3
        $this->level = $level;
54 3
    }
55
56
    /**
57
     * @inheritDoc
58
     * @throws CacheException
59
     */
60 2
    public function get($key, $default = null)
61
    {
62 2
        $this->throwIfNotInstanceof(Cache::class);
63
64 2
        $result = $this->cache->get($key);
0 ignored issues
show
Bug introduced by
The method get() does not exist on Vectorface\Cache\AtomicCounter. Since it exists in all sub-types, consider adding an abstract or default implementation to Vectorface\Cache\AtomicCounter. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

64
        /** @scrutinizer ignore-call */ 
65
        $result = $this->cache->get($key);
Loading history...
65 2
        if ($result === null) {
66 2
            $this->log(sprintf("get %s MISS", $key));
67 2
            return $default;
68
        }
69
70 1
        $this->log(sprintf(
71 1
            "get %s HIT size=%d",
72 1
            $key,
73 1
            $this->getSize($result)
74
        ));
75 1
        return $result;
76
    }
77
78
    /**
79
     * @inheritDoc
80
     */
81 3
    public function set($key, $value, $ttl = false)
82
    {
83 3
        $this->throwIfNotInstanceof(Cache::class);
84
85 3
        $result = $this->cache->set($key, $value, $ttl);
0 ignored issues
show
Bug introduced by
The method set() does not exist on Vectorface\Cache\AtomicCounter. Since it exists in all sub-types, consider adding an abstract or default implementation to Vectorface\Cache\AtomicCounter. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

85
        /** @scrutinizer ignore-call */ 
86
        $result = $this->cache->set($key, $value, $ttl);
Loading history...
86 3
        $this->log(sprintf(
87 3
            "set %s %s ttl=%s, type=%s, size=%d",
88 3
            $key,
89 3
            $result ? 'SUCCESS' : 'FAILURE',
90 3
            is_numeric($ttl) ? $ttl : "false",
91 3
            gettype($value),
92 3
            $this->getSize($value)
93
        ));
94 3
        return $result;
95
    }
96
97
    /**
98
     * @inheritDoc
99
     * @throws CacheException
100
     */
101 2
    public function delete($key)
102
    {
103 2
        $this->throwIfNotInstanceof(Cache::class);
104
105 2
        $result = $this->cache->delete($key);
0 ignored issues
show
Bug introduced by
The method delete() does not exist on Vectorface\Cache\AtomicCounter. Since it exists in all sub-types, consider adding an abstract or default implementation to Vectorface\Cache\AtomicCounter. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

105
        /** @scrutinizer ignore-call */ 
106
        $result = $this->cache->delete($key);
Loading history...
106 2
        $this->log(sprintf(
107 2
            "delete %s %s",
108 2
            $key,
109 2
            $result ? 'SUCCESS' : 'FAILURE'
110
        ));
111 2
        return $result;
112
    }
113
114
    /**
115
     * @inheritDoc
116
     * @throws CacheException
117
     */
118 2
    public function flush()
119
    {
120 2
        $this->throwIfNotInstanceof(Cache::class);
121
122 2
        $result = $this->cache->flush();
0 ignored issues
show
Bug introduced by
The method flush() does not exist on Vectorface\Cache\AtomicCounter. Since it exists in all sub-types, consider adding an abstract or default implementation to Vectorface\Cache\AtomicCounter. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

122
        /** @scrutinizer ignore-call */ 
123
        $result = $this->cache->flush();
Loading history...
123 2
        $this->log(sprintf("flush %s", $result ? 'SUCCESS' : 'FAILURE'));
124 2
        return $result;
125
    }
126
127
    /**
128
     * @inheritDoc
129
     * @throws CacheException
130
     */
131 2
    public function clean()
132
    {
133 2
        $this->throwIfNotInstanceof(Cache::class);
134
135 2
        $result = $this->cache->clean();
0 ignored issues
show
Bug introduced by
The method clean() does not exist on Vectorface\Cache\AtomicCounter. Since it exists in all sub-types, consider adding an abstract or default implementation to Vectorface\Cache\AtomicCounter. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

135
        /** @scrutinizer ignore-call */ 
136
        $result = $this->cache->clean();
Loading history...
136 2
        $this->log(sprintf("clean %s", $result ? 'SUCCESS' : 'FAILURE'));
137 2
        return $result;
138
    }
139
140
    /**
141
     * @inheritDoc
142
     * @throws CacheException
143
     */
144 1
    public function clear()
145
    {
146 1
        $this->throwIfNotInstanceof(Cache::class);
147
148 1
        return $this->flush();
149
    }
150
151
    /**
152
     * @inheritDoc
153
     * @throws CacheException
154
     */
155 1
    public function getMultiple($keys, $default = null)
156
    {
157 1
        $this->throwIfNotInstanceof(Cache::class);
158
159 1
        $values = $this->cache->getMultiple($keys, $default);
0 ignored issues
show
Bug introduced by
The method getMultiple() does not exist on Vectorface\Cache\AtomicCounter. Since it exists in all sub-types, consider adding an abstract or default implementation to Vectorface\Cache\AtomicCounter. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

159
        /** @scrutinizer ignore-call */ 
160
        $values = $this->cache->getMultiple($keys, $default);
Loading history...
160 1
        $this->log(sprintf(
161 1
            "getMultiple [%s] count=%s",
162 1
            implode(', ', $keys),
163 1
            is_array($values) ? count($values) : ('[' . gettype($values) . ']')
164
        ));
165 1
        return $values;
166
    }
167
168
    /**
169
     * @inheritDoc
170
     */
171 1
    public function setMultiple($values, $ttl = null)
172
    {
173 1
        $this->throwIfNotInstanceof(Cache::class);
174
175 1
        $result = $this->cache->setMultiple($values, $ttl);
0 ignored issues
show
Bug introduced by
The method setMultiple() does not exist on Vectorface\Cache\AtomicCounter. Since it exists in all sub-types, consider adding an abstract or default implementation to Vectorface\Cache\AtomicCounter. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

175
        /** @scrutinizer ignore-call */ 
176
        $result = $this->cache->setMultiple($values, $ttl);
Loading history...
176 1
        $this->log(sprintf(
177 1
            "setMultiple [%s] %s ttl=%s",
178 1
            implode(', ', array_keys($values)),
179 1
            $result ? 'SUCCESS' : 'FAILURE',
180 1
            is_numeric($ttl) ? $ttl : "null"
181
        ));
182 1
        return $result;
183
    }
184
185
    /**
186
     * @inheritDoc
187
     * @throws CacheException
188
     */
189 1
    public function deleteMultiple($keys)
190
    {
191 1
        $this->throwIfNotInstanceof(Cache::class);
192
193 1
        $result = $this->cache->deleteMultiple($keys);
0 ignored issues
show
Bug introduced by
The method deleteMultiple() does not exist on Vectorface\Cache\AtomicCounter. Since it exists in all sub-types, consider adding an abstract or default implementation to Vectorface\Cache\AtomicCounter. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

193
        /** @scrutinizer ignore-call */ 
194
        $result = $this->cache->deleteMultiple($keys);
Loading history...
194 1
        $this->log(sprintf(
195 1
            "deleteMultiple [%s] %s",
196 1
            implode(', ', $keys),
197 1
            $result ? 'SUCCESS' : 'FAILURE'
198
        ));
199 1
        return $result;
200
    }
201
202
    /**
203
     * @inheritDoc
204
     * @throws CacheException
205
     */
206 1
    public function has($key)
207
    {
208 1
        $this->throwIfNotInstanceof(Cache::class);
209
210 1
        $result = $this->cache->has($key);
0 ignored issues
show
Bug introduced by
The method has() does not exist on Vectorface\Cache\AtomicCounter. Since it exists in all sub-types, consider adding an abstract or default implementation to Vectorface\Cache\AtomicCounter. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

210
        /** @scrutinizer ignore-call */ 
211
        $result = $this->cache->has($key);
Loading history...
211 1
        $this->log(sprintf(
212 1
            "has %s %s",
213 1
            $key,
214 1
            $result ? 'true' : 'false'
215
        ));
216 1
        return $result;
217
    }
218
219
    /**
220
     * @inheritDoc
221
     * @throws CacheException
222
     */
223 2
    public function increment($key, $step = 1)
224
    {
225 2
        $this->throwIfNotInstanceof(AtomicCounter::class);
226
227 2
        $result = $this->cache->increment($key, $step);
0 ignored issues
show
Bug introduced by
The method increment() does not exist on Vectorface\Cache\Cache. It seems like you code against a sub-type of said class. However, the method does not exist in Vectorface\Cache\TempFileCache or Vectorface\Cache\TieredCache. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

227
        /** @scrutinizer ignore-call */ 
228
        $result = $this->cache->increment($key, $step);
Loading history...
228 2
        $this->log(sprintf(
229 2
            "increment %s by %d %s, value=%d",
230 2
            $key,
231 2
            $step,
232 2
            ($result !== false ? 'SUCCESS' : 'FAILURE'),
233 2
            ($result !== false ? $result : 0)
234
        ));
235 2
        return $result;
236
    }
237
238
    /**
239
     * @inheritDoc
240
     * @throws CacheException
241
     */
242 2
    public function decrement($key, $step = 1)
243
    {
244 2
        $this->throwIfNotInstanceof(AtomicCounter::class);
245
246 2
        $result = $this->cache->decrement($key, $step);
0 ignored issues
show
Bug introduced by
The method decrement() does not exist on Vectorface\Cache\Cache. It seems like you code against a sub-type of said class. However, the method does not exist in Vectorface\Cache\TempFileCache or Vectorface\Cache\TieredCache. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

246
        /** @scrutinizer ignore-call */ 
247
        $result = $this->cache->decrement($key, $step);
Loading history...
247 2
        $this->log(sprintf(
248 2
            "decrement %s by %d %s, value=%d",
249 2
            $key,
250 2
            $step,
251 2
            ($result !== false ? 'SUCCESS' : 'FAILURE'),
252 2
            ($result !== false ? $result : 0)
253
        ));
254 2
        return $result;
255
    }
256
257
    /**
258
     * Log a message to the configured logger
259
     *
260
     * @param $message
261
     */
262 3
    private function log(string $message)
263
    {
264 3
        if (!$this->log) {
265 1
            return;
266
        }
267
268 2
        ([$this->log, $this->level])($message);
269 2
    }
270
271
    /**
272
     * Guards against calls on a decorated instance that does not support the underlying method
273
     *
274
     * @param string $class
275
     * @throws CacheException
276
     */
277 3
    private function throwIfNotInstanceof($class)
278
    {
279 3
        if (! $this->cache instanceof $class) {
280
            throw new CacheException("This decorated instance does not implement $class");
281
        }
282 3
    }
283
284
    /**
285
     * Get a reasonable estimation for the serialized size of a cacheable value
286
     *
287
     * @param mixed $val The cacheable value
288
     * @return int An estimate of the cached size of the value
289
     */
290 3
    private function getSize($val)
291
    {
292 3
        return strlen(is_scalar($val) ? (string)$val : serialize($val));
293
    }
294
}
295