Passed
Push — master ( 159f4a...679316 )
by
unknown
02:11
created

LogDecorator::get()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 9
c 1
b 0
f 0
dl 0
loc 14
ccs 10
cts 10
cp 1
rs 9.9666
cc 2
nc 2
nop 2
crap 2
1
<?php
2
3
namespace Vectorface\Cache;
4
5
use Psr\Log\LoggerInterface;
6
7
/**
8
 * Decorates (Wraps) a Cache implementation with logging
9
 *
10
 * Note:
11
 *   This logs an estimated serialized object size. Cache serialization may
12
 *   use a different serialization mechanism, so the size should be used to
13
 *   give an idea of actual cached size rather than an exact value.
14
 */
15
class LogDecorator implements Cache
16
{
17
    /**
18
     * The wrapped cache class
19
     * @var Cache
20
     */
21
    private $cache;
22
23
    /**
24
     * The logger instance to which operations will be logged
25
     *
26
     * @var LoggerInterface
27
     */
28
    private $log;
29
30
    /**
31
     * The log level, which corresponds to a PSR-3 log level function call
32
     *
33
     * @var string
34
     */
35
    private $level;
36
37
    /**
38
     * @param Cache $cache
39
     * @param LoggerInterface $log
40
     * @param string $level
41
     */
42 4
    public function __construct(Cache $cache, LoggerInterface $log = null, $level = 'debug')
43
    {
44 4
        $levels = ['emergency', 'alert', 'critical', 'error', 'warning', 'notice', 'info', 'debug'];
45 4
        if (!in_array($level, $levels)) {
46 1
            throw new \InvalidArgumentException("Incompatible log level: $level");
47
        }
48
49 3
        $this->cache = $cache;
50 3
        $this->log = $log;
51 3
        $this->level = $level;
52 3
    }
53
54
    /**
55
     * @inheritDoc
56
     */
57 2
    public function get($key, $default = null)
58
    {
59 2
        $result = $this->cache->get($key);
60 2
        if ($result === null) {
61 2
            $this->log(sprintf("get %s MISS", $key));
62 2
            return $default;
63
        }
64
65 1
        $this->log(sprintf(
66 1
            "get %s HIT size=%d",
67 1
            $key,
68 1
            $this->getSize($result)
69
        ));
70 1
        return $result;
71
    }
72
73
    /**
74
     * @inheritDoc
75
     */
76 3
    public function set($key, $value, $ttl = false)
77
    {
78 3
        $result = $this->cache->set($key, $value, $ttl);
79 3
        $this->log(sprintf(
80 3
            "set %s %s ttl=%s, type=%s, size=%d",
81 3
            $key,
82 3
            $result ? 'SUCCESS' : 'FAILURE',
83 3
            is_numeric($ttl) ? $ttl : "false",
84 3
            gettype($value),
85 3
            $this->getSize($value)
86
        ));
87 3
        return $result;
88
    }
89
90
    /**
91
     * @inheritDoc
92
     */
93 2
    public function delete($key)
94
    {
95 2
        $result = $this->cache->delete($key);
96 2
        $this->log(sprintf(
97 2
            "delete %s %s",
98 2
            $key,
99 2
            $result ? 'SUCCESS' : 'FAILURE'
100
        ));
101 2
        return $result;
102
    }
103
104
    /**
105
     * @inheritDoc
106
     */
107 2
    public function flush()
108
    {
109 2
        $result = $this->cache->flush();
110 2
        $this->log(sprintf("flush %s", $result ? 'SUCCESS' : 'FAILURE'));
111 2
        return $result;
112
    }
113
114
    /**
115
     * @inheritDoc
116
     */
117 2
    public function clean()
118
    {
119 2
        $result = $this->cache->clean();
120 2
        $this->log(sprintf("clean %s", $result ? 'SUCCESS' : 'FAILURE'));
121 2
        return $result;
122
    }
123
124
    /**
125
     * @inheritDoc
126
     */
127 1
    public function clear()
128
    {
129 1
        return $this->flush();
130
    }
131
132
    /**
133
     * @inheritDoc
134
     */
135 1
    public function getMultiple($keys, $default = null)
136
    {
137 1
        $values = $this->cache->getMultiple($keys, $default);
138 1
        $this->log(sprintf(
139 1
            "getMultiple [%s] count=%s",
140 1
            implode(', ', $keys),
141 1
            is_array($values) ? count($values) : ('[' . gettype($values) . ']')
142
        ));
143 1
        return $values;
144
    }
145
146
    /**
147
     * @inheritDoc
148
     */
149 1
    public function setMultiple($values, $ttl = null)
150
    {
151 1
        $result = $this->cache->setMultiple($values, $ttl);
152 1
        $this->log(sprintf(
153 1
            "setMultiple [%s] %s ttl=%s",
154 1
            implode(', ', array_keys($values)),
155 1
            $result ? 'SUCCESS' : 'FAILURE',
156 1
            is_numeric($ttl) ? $ttl : "null"
157
        ));
158 1
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result returns the type Traversable|array which is incompatible with the return type mandated by Psr\SimpleCache\CacheInterface::setMultiple() of boolean.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
159
    }
160
161
    /**
162
     * @inheritDoc
163
     */
164 1
    public function deleteMultiple($keys)
165
    {
166 1
        $result = $this->cache->deleteMultiple($keys);
167 1
        $this->log(sprintf(
168 1
            "deleteMultiple [%s] %s",
169 1
            implode(', ', $keys),
170 1
            $result ? 'SUCCESS' : 'FAILURE'
171
        ));
172 1
        return $result;
173
    }
174
175
    /**
176
     * @inheritDoc
177
     */
178 1
    public function has($key)
179
    {
180 1
        $result = $this->cache->has($key);
181 1
        $this->log(sprintf(
182 1
            "has %s %s",
183 1
            $key,
184 1
            $result ? 'true' : 'false'
185
        ));
186 1
        return $result;
187
    }
188
189
    /**
190
     * Log a message to the configured logger
191
     *
192
     * @param $message
193
     */
194 3
    private function log(string $message)
195
    {
196 3
        if (!$this->log) {
197 1
            return;
198
        }
199
200 2
        ([$this->log, $this->level])($message);
201 2
    }
202
203
    /**
204
     * Get a reasonable estimation for the serialized size of a cacheable value
205
     *
206
     * @param mixed $val The cacheable value
207
     * @return int An estimate of the cached size of the value
208
     */
209 3
    private function getSize($val)
210
    {
211 3
        return strlen(is_scalar($val) ? (string)$val : serialize($val));
212
    }
213
}
214