Skip to content

Commit ad5af97

Browse files
committed
Update settings to automatically convert/hydrate the value types for better conversions. Fixes #2
1 parent c19a90b commit ad5af97

File tree

4 files changed

+289
-255
lines changed

4 files changed

+289
-255
lines changed

src/Database/Migrations/2021-07-04-041948_CreateSettingsTable.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ public function up()
2323
'type' => 'text',
2424
'null' => true,
2525
],
26+
'type' => [
27+
'type' => 'varchar',
28+
'constraint' => 31,
29+
'default' => 'string',
30+
],
2631
'created_at' => [
2732
'type' => 'datetime',
2833
'null' => false,

src/Handlers/BaseHandler.php

Lines changed: 145 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -4,151 +4,157 @@
44

55
abstract class BaseHandler
66
{
7-
/**
8-
* Returns a single value from the handler, if stored.
9-
*
10-
* @param string $class
11-
* @param string $key
12-
*
13-
* @return mixed
14-
*/
15-
abstract public function get(string $class, string $key);
7+
/**
8+
* Returns a single value from the handler, if stored.
9+
*
10+
* @param string $class
11+
* @param string $key
12+
*
13+
* @return mixed
14+
*/
15+
abstract public function get(string $class, string $key);
1616

17-
/**
18-
* If the Handler supports saving values, it
19-
* MUST override this method to provide that functionality.
20-
* Not all Handlers will support writing values.
21-
*
22-
* @param string $key
23-
* @param null $value
24-
*
25-
* @return mixed
26-
*/
27-
public function set(string $class, string $key, $value = null)
28-
{
29-
throw new \RuntimeException('Set method not implemented for current Settings handler.');
30-
}
17+
/**
18+
* If the Handler supports saving values, it
19+
* MUST override this method to provide that functionality.
20+
* Not all Handlers will support writing values.
21+
*
22+
* @param string $key
23+
* @param null $value
24+
*
25+
* @return mixed
26+
*/
27+
public function set(string $class, string $key, $value = null)
28+
{
29+
throw new \RuntimeException('Set method not implemented for current Settings handler.');
30+
}
3131

32-
/**
33-
* Takes care of converting some item types so they can be safely
34-
* stored and re-hydrated into the config files.
35-
*
36-
* @param $value
37-
*
38-
* @return string|mixed
39-
*/
40-
protected function prepareValue($value)
41-
{
42-
if ($value === true) {
43-
return ':true';
44-
}
32+
/**
33+
* Takes care of converting some item types so they can be safely
34+
* stored and re-hydrated into the config files.
35+
*
36+
* @param $value
37+
*
38+
* @return string|mixed
39+
*/
40+
protected function prepareValue($value)
41+
{
42+
if (is_bool($value))
43+
{
44+
return (int)$value;
45+
}
4546

46-
if ($value === false) {
47-
return ':false';
48-
}
47+
if (is_array($value) || is_object($value))
48+
{
49+
return serialize($value);
50+
}
4951

50-
if (is_array($value) || is_object($value)) {
51-
return serialize($value);
52-
}
52+
return $value;
53+
}
5354

54-
return $value;
55-
}
55+
/**
56+
* Handles some special case conversions that
57+
* data might have been saved as, such as booleans
58+
* and serialized data.
59+
*
60+
* @param $value
61+
*
62+
* @return boolean|mixed
63+
*/
64+
protected function parseValue($value, string $type)
65+
{
66+
// Serialized?
67+
if ($this->isSerialized($value))
68+
{
69+
$value = unserialize($value);
70+
}
5671

57-
/**
58-
* Handles some special case conversions that
59-
* data might have been saved as, such as booleans
60-
* and serialized data.
61-
*
62-
* @param $value
63-
*
64-
* @return bool|mixed
65-
*/
66-
protected function parseValue($value)
67-
{
68-
// :true -> boolean
69-
if ($value === ':true') {
70-
return true;
71-
}
72+
settype($value, $type);
7273

73-
// :false -> boolean
74-
if ($value === ':false') {
75-
return false;
76-
}
74+
return $value;
75+
}
7776

78-
// Serialized?
79-
if ($this->isSerialized($value)) {
80-
return unserialize($value);
81-
}
82-
83-
return $value;
84-
}
85-
86-
/**
87-
* Checks to see if an object is serialized and correctly formatted.
88-
*
89-
* Taken from Wordpress core functions.
90-
*
91-
* @param $data
92-
* @param bool $strict Whether to be strict about the end of the string.
93-
*
94-
* @return bool
95-
*/
96-
protected function isSerialized($data, $strict = true): bool
97-
{
98-
// If it isn't a string, it isn't serialized.
99-
if (! is_string($data)) {
100-
return false;
101-
}
102-
$data = trim($data);
103-
if ('N;' === $data) {
104-
return true;
105-
}
106-
if (strlen($data) < 4) {
107-
return false;
108-
}
109-
if (':' !== $data[1]) {
110-
return false;
111-
}
112-
if ($strict) {
113-
$lastc = substr($data, -1);
114-
if (';' !== $lastc && '}' !== $lastc) {
115-
return false;
116-
}
117-
} else {
118-
$semicolon = strpos($data, ';');
119-
$brace = strpos($data, '}');
120-
// Either ; or } must exist.
121-
if (false === $semicolon && false === $brace) {
122-
return false;
123-
}
124-
// But neither must be in the first X characters.
125-
if (false !== $semicolon && $semicolon < 3) {
126-
return false;
127-
}
128-
if (false !== $brace && $brace < 4) {
129-
return false;
130-
}
131-
}
132-
$token = $data[0];
133-
switch ($token) {
134-
case 's':
135-
if ($strict) {
136-
if ('"' !== substr($data, -2, 1)) {
137-
return false;
138-
}
139-
} elseif (false === strpos($data, '"')) {
140-
return false;
141-
}
142-
// Or else fall through.
143-
case 'a':
144-
case 'O':
145-
return (bool) preg_match("/^{$token}:[0-9]+:/s", $data);
146-
case 'b':
147-
case 'i':
148-
case 'd':
149-
$end = $strict ? '$' : '';
150-
return (bool) preg_match("/^{$token}:[0-9.E+-]+;$end/", $data);
151-
}
152-
return false;
153-
}
77+
/**
78+
* Checks to see if an object is serialized and correctly formatted.
79+
*
80+
* Taken from Wordpress core functions.
81+
*
82+
* @param $data
83+
* @param boolean $strict Whether to be strict about the end of the string.
84+
*
85+
* @return boolean
86+
*/
87+
protected function isSerialized($data, $strict = true): bool
88+
{
89+
// If it isn't a string, it isn't serialized.
90+
if (! is_string($data))
91+
{
92+
return false;
93+
}
94+
$data = trim($data);
95+
if ('N;' === $data)
96+
{
97+
return true;
98+
}
99+
if (strlen($data) < 4)
100+
{
101+
return false;
102+
}
103+
if (':' !== $data[1])
104+
{
105+
return false;
106+
}
107+
if ($strict)
108+
{
109+
$lastc = substr($data, -1);
110+
if (';' !== $lastc && '}' !== $lastc)
111+
{
112+
return false;
113+
}
114+
}
115+
else
116+
{
117+
$semicolon = strpos($data, ';');
118+
$brace = strpos($data, '}');
119+
// Either ; or } must exist.
120+
if (false === $semicolon && false === $brace)
121+
{
122+
return false;
123+
}
124+
// But neither must be in the first X characters.
125+
if (false !== $semicolon && $semicolon < 3)
126+
{
127+
return false;
128+
}
129+
if (false !== $brace && $brace < 4)
130+
{
131+
return false;
132+
}
133+
}
134+
$token = $data[0];
135+
switch ($token) {
136+
case 's':
137+
if ($strict)
138+
{
139+
if ('"' !== substr($data, -2, 1))
140+
{
141+
return false;
142+
}
143+
}
144+
elseif (false === strpos($data, '"'))
145+
{
146+
return false;
147+
}
148+
// Or else fall through.
149+
case 'a':
150+
case 'O':
151+
return (bool) preg_match("/^{$token}:[0-9]+:/s", $data);
152+
case 'b':
153+
case 'i':
154+
case 'd':
155+
$end = $strict ? '$' : '';
156+
return (bool) preg_match("/^{$token}:[0-9.E+-]+;$end/", $data);
157+
}
158+
return false;
159+
}
154160
}

0 commit comments

Comments
 (0)