-
Notifications
You must be signed in to change notification settings - Fork 26
Expand file tree
/
Copy pathBaseHandler.php
More file actions
185 lines (164 loc) · 4.97 KB
/
BaseHandler.php
File metadata and controls
185 lines (164 loc) · 4.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
<?php
declare(strict_types=1);
namespace CodeIgniter\Settings\Handlers;
use RuntimeException;
abstract class BaseHandler
{
/**
* Checks whether this handler has a value set.
*/
abstract public function has(string $class, string $property, ?string $context = null): bool;
/**
* Returns a single value from the handler, if stored.
*
* @return mixed
*/
abstract public function get(string $class, string $property, ?string $context = null);
/**
* If the Handler supports saving values, it
* MUST override this method to provide that functionality.
* Not all Handlers will support writing values.
* Must throw RuntimeException for any failures.
*
* @param mixed $value
*
* @throws RuntimeException
*/
public function set(string $class, string $property, $value = null, ?string $context = null): void
{
throw new RuntimeException('Set method not implemented for current Settings handler.');
}
/**
* If the Handler supports forgetting values, it
* MUST override this method to provide that functionality.
* Not all Handlers will support writing values.
* Must throw RuntimeException for any failures.
*
* @throws RuntimeException
*/
public function forget(string $class, string $property, ?string $context = null): void
{
throw new RuntimeException('Forget method not implemented for current Settings handler.');
}
/**
* All handlers MUST support flushing all values.
*
* @throws RuntimeException
*/
public function flush(): void
{
throw new RuntimeException('Flush method not implemented for current Settings handler.');
}
/**
* All handlers that support deferWrites MUST support this method.
*
* @throws RuntimeException
*/
public function persistPendingProperties(): void
{
throw new RuntimeException('PersistPendingProperties method not implemented for current Settings handler.');
}
/**
* Takes care of converting some item types so they can be safely
* stored and re-hydrated into the config files.
*
* @param mixed $value
*
* @return mixed|string
*/
protected function prepareValue($value)
{
if (is_bool($value)) {
return (int) $value;
}
if (is_array($value) || is_object($value)) {
return serialize($value);
}
return $value;
}
/**
* Handles some special case conversions that
* data might have been saved as, such as booleans
* and serialized data.
*
* @param mixed $value
*
* @return bool|mixed
*/
protected function parseValue($value, string $type)
{
// Serialized?
if ($this->isSerialized($value)) {
$value = unserialize($value);
}
settype($value, $type);
return $value;
}
/**
* Checks to see if an object is serialized and correctly formatted.
*
* Taken from Wordpress core functions.
*
* @param mixed $data
* @param bool $strict Whether to be strict about the end of the string.
*/
protected function isSerialized($data, $strict = true): bool
{
// If it isn't a string, it isn't serialized.
if (! is_string($data)) {
return false;
}
$data = trim($data);
if ('N;' === $data) {
return true;
}
if (strlen($data) < 4) {
return false;
}
if (':' !== $data[1]) {
return false;
}
if ($strict) {
$lastc = substr($data, -1);
if (';' !== $lastc && '}' !== $lastc) {
return false;
}
} else {
$semicolon = strpos($data, ';');
$brace = strpos($data, '}');
// Either ; or } must exist.
if (false === $semicolon && false === $brace) {
return false;
}
// But neither must be in the first X characters.
if (false !== $semicolon && $semicolon < 3) {
return false;
}
if (false !== $brace && $brace < 4) {
return false;
}
}
$token = $data[0];
switch ($token) {
case 's':
if ($strict) {
if ('"' !== substr($data, -2, 1)) {
return false;
}
} elseif (! str_contains($data, '"')) {
return false;
}
// Or else fall through.
// no break
case 'a':
case 'O':
return (bool) preg_match("/^{$token}:[0-9]+:/s", $data);
case 'b':
case 'i':
case 'd':
$end = $strict ? '$' : '';
return (bool) preg_match("/^{$token}:[0-9.E+-]+;{$end}/", $data);
}
return false;
}
}