Passed
Push — master ( f4169b...5ce74f )
by Loban
02:35
created

Settings::buildKey()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 4

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 4
eloc 6
nc 4
nop 1
dl 0
loc 10
ccs 3
cts 3
cp 1
crap 4
rs 10
c 2
b 0
f 0
1
<?php
2
/**
3
 * @link https://github.com/lav45/yii2-settings
4
 * @copyright Copyright (c) 2016 LAV45
5
 * @author Alexey Loban <[email protected]>
6
 * @license http://opensource.org/licenses/BSD-3-Clause
7
 */
8
9
namespace lav45\settings;
10
11
use lav45\settings\behaviors\CacheBehavior;
12
use lav45\settings\behaviors\QuickAccessBehavior;
13
use lav45\settings\events\DecodeEvent;
14
use lav45\settings\events\DeleteEvent;
15
use lav45\settings\events\GetEvent;
16
use lav45\settings\events\SetEvent;
17
use lav45\settings\storage\DbStorage;
18
use lav45\settings\storage\StorageInterface;
19
use yii\base\Component;
20
use yii\di\Instance;
21
use yii\helpers\StringHelper;
22
23
/**
24
 * Class Settings
25
 * @package lav45\settings
26
 * @mixin CacheBehavior
27
 * @mixin QuickAccessBehavior
28
 */
29
class Settings extends Component implements \ArrayAccess
30
{
31
    public const EVENT_BEFORE_GET = 'beforeGetValue';
32
    public const EVENT_AFTER_GET = 'afterGetValue';
33
    public const EVENT_AFTER_DECODE_VALUE = 'afterDecodeValue';
34
    public const EVENT_BEFORE_SET = 'beforeSetValue';
35
    public const EVENT_AFTER_SET = 'afterSetValue';
36
    public const EVENT_BEFORE_DELETE = 'beforeDeleteValue';
37
    public const EVENT_AFTER_DELETE = 'afterDeleteValue';
38
39
    /**
40
     * @var string
41
     */
42
    public $keyPrefix;
43
    /**
44
     * @var bool
45
     */
46
    public $buildKey = true;
47
    /**
48
     * @var array|boolean
49
     */
50
    public $serializer;
51
    /**
52
     * @var StorageInterface|string|array
53
     */
54
    public $storage = DbStorage::class;
55 22
56
    /**
57 22
     * @inheritdoc
58 22
     */
59 22
    public function init()
60
    {
61
        parent::init();
62
        $this->storage = Instance::ensure($this->storage, StorageInterface::class);
63
    }
64
65 24
    /**
66
     * @param string|array $key
67 24
     * @return string
68 24
     */
69 20
    public function buildKey($key)
70
    {
71 4
        if ($this->buildKey === true) {
72
            if (is_string($key)) {
73
                $key = StringHelper::byteLength($key) <= 32 ? $key : md5($key);
74 24
            } else {
75
                $key = md5(json_encode($key, JSON_THROW_ON_ERROR));
76
            }
77
        }
78
        return $this->keyPrefix . $key;
0 ignored issues
show
Bug introduced by
Are you sure $key of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

78
        return $this->keyPrefix . /** @scrutinizer ignore-type */ $key;
Loading history...
79
    }
80
81 22
    /**
82
     * @param mixed $value
83 22
     * @return string
84 20
     */
85
    public function encode($value)
86 12
    {
87 1
        if ($this->serializer === null) {
88
            return serialize($value);
89 11
        }
90
        if ($this->serializer !== false) {
91
            return call_user_func($this->serializer[0], $value);
92
        }
93
        return $value;
94
    }
95
96 22
    /**
97
     * @param string $value
98 22
     * @return mixed
99 20
     */
100
    public function decode($value)
101 10
    {
102 1
        if ($this->serializer === null) {
103
            return @unserialize($value, ['allowed_classes' => true]);
104 9
        }
105
        if ($this->serializer !== false) {
106
            return call_user_func($this->serializer[1], $value);
107
        }
108
        return $value;
109
    }
110
111
    /**
112 23
     * @param string|array $key
113
     * @param null $default
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $default is correct as it would always require null to be passed?
Loading history...
114 23
     * @return mixed
115 23
     */
116 23
    public function get($key, $default = null)
117 22
    {
118 22
        $key = $this->buildKey($key);
119
        $value = $this->beforeGetValue($key);
120 23
        if ($value === null) {
0 ignored issues
show
introduced by
The condition $value === null is always false.
Loading history...
121 10
            $value = $this->storage->getValue($key);
122
            $value = $this->afterGetValue($key, $value);
123
        }
124 22
        if ($value === false) {
0 ignored issues
show
introduced by
The condition $value === false is always false.
Loading history...
125 22
            return $default;
126
        }
127 22
128
        $value = $this->decode($value);
129
        return $this->afterDecodeValue($key, $value, $default);
130
    }
131
132
    /**
133
     * @param string|array $key
134
     * @param mixed $value
135 22
     * @return boolean
136
     */
137 22
    public function set($key, $value)
138
    {
139 22
        $value = $this->beforeSetValue($key, $value);
140 22
141 22
        $key = $this->buildKey($key);
142
        $value = $this->encode($value);
143 22
        $result = $this->storage->setValue($key, $value);
144
145 22
        $this->afterSetValue($key, $value);
146
147
        return $result;
148
    }
149
150
    /**
151
     * @param string $key
152 3
     * @return boolean
153
     */
154 3
    public function delete($key)
155
    {
156 3
        $this->beforeDeleteValue($key);
157 3
158
        $key = $this->buildKey($key);
159 3
        $result = $this->storage->deleteValue($key);
160
161 3
        $this->afterDeleteValue($key);
162
163
        return $result;
164
    }
165
166
    /**
167
     * @param string $key
168 23
     * @return string
169
     */
170 23
    protected function beforeGetValue(&$key)
171 23
    {
172 23
        $event = new GetEvent();
173 23
        $event->key = &$key;
174
        $this->trigger(self::EVENT_BEFORE_GET, $event);
175
        return $event->value;
176
    }
177
178
    /**
179
     * @param string $key
180
     * @param string $value
181 22
     * @return string
182
     */
183 22
    protected function afterGetValue($key, $value)
184 22
    {
185 22
        $event = new GetEvent();
186 22
        $event->key = $key;
187 22
        $event->value = $value;
188
        $this->trigger(self::EVENT_AFTER_GET, $event);
189
        return $event->value;
190
    }
191
192
    /**
193
     * @param string|array $key
194
     * @param mixed $value
195
     * @param mixed $default
196 22
     * @return mixed
197
     */
198 22
    protected function afterDecodeValue($key, $value, $default)
199 22
    {
200 22
        $event = new DecodeEvent();
201 22
        $event->key = $key;
202 22
        $event->value = $value;
203 22
        $event->default = $default;
204
        $this->trigger(self::EVENT_AFTER_DECODE_VALUE, $event);
205
        return $event->value;
206
    }
207
208
    /**
209
     * @param string|array $key
210
     * @param mixed $value
211 22
     * @return mixed
212
     */
213 22
    protected function beforeSetValue($key, $value)
214 22
    {
215 22
        $event = new SetEvent();
216 22
        $event->key = $key;
217 22
        $event->value = $value;
218
        $this->trigger(self::EVENT_BEFORE_SET, $event);
219
        return $event->value;
220
    }
221
222
    /**
223
     * @param string $key
224 22
     * @param string $value
225
     */
226 22
    protected function afterSetValue($key, $value)
227 22
    {
228 22
        $event = new SetEvent();
229 22
        $event->key = $key;
230 22
        $event->value = $value;
231
        $this->trigger(self::EVENT_AFTER_SET, $event);
232
    }
233
234
    /**
235 3
     * @param string $key
236
     */
237 3
    protected function beforeDeleteValue($key)
238 3
    {
239 3
        $event = new DeleteEvent();
240 3
        $event->key = $key;
241
        $this->trigger(self::EVENT_BEFORE_DELETE, $event);
242
    }
243
244
    /**
245 3
     * @param string $key
246
     */
247 3
    protected function afterDeleteValue($key)
248 3
    {
249 3
        $event = new DeleteEvent();
250 3
        $event->key = $key;
251
        $this->trigger(self::EVENT_AFTER_DELETE, $event);
252
    }
253
254
    /**
255
     * @inheritDoc
256 1
     */
257
    public function offsetExists($offset): bool
258 1
    {
259
        return $this->get($offset) !== null;
260
    }
261
262
    /**
263
     * @inheritDoc
264
     */
265 2
    #[\ReturnTypeWillChange]
266
    public function offsetGet($offset)
267 2
    {
268
        return $this->get($offset);
269
    }
270
271
    /**
272
     * @inheritDoc
273
     */
274 1
    public function offsetSet($offset, $value): void
275
    {
276 1
        $this->set($offset, $value);
277 1
    }
278
279
    /**
280
     * @inheritDoc
281
     */
282 1
    public function offsetUnset($offset): void
283
    {
284 1
        $this->delete($offset);
285
    }
286
}