• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

codeigniter4 / settings / 19026940269

03 Nov 2025 07:23AM UTC coverage: 87.041% (+1.4%) from 85.634%
19026940269

push

github

web-flow
feat: deferred writes (#154)

117 of 126 new or added lines in 4 files covered. (92.86%)

403 of 463 relevant lines covered (87.04%)

28.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

50.0
/src/Handlers/BaseHandler.php
1
<?php
2

3
namespace CodeIgniter\Settings\Handlers;
4

5
use RuntimeException;
6

7
abstract class BaseHandler
8
{
9
    /**
10
     * Checks whether this handler has a value set.
11
     */
12
    abstract public function has(string $class, string $property, ?string $context = null): bool;
13

14
    /**
15
     * Returns a single value from the handler, if stored.
16
     *
17
     * @return mixed
18
     */
19
    abstract public function get(string $class, string $property, ?string $context = null);
20

21
    /**
22
     * If the Handler supports saving values, it
23
     * MUST override this method to provide that functionality.
24
     * Not all Handlers will support writing values.
25
     * Must throw RuntimeException for any failures.
26
     *
27
     * @param mixed $value
28
     *
29
     * @return void
30
     *
31
     * @throws RuntimeException
32
     */
33
    public function set(string $class, string $property, $value = null, ?string $context = null)
34
    {
35
        throw new RuntimeException('Set method not implemented for current Settings handler.');
×
36
    }
37

38
    /**
39
     * If the Handler supports forgetting values, it
40
     * MUST override this method to provide that functionality.
41
     * Not all Handlers will support writing values.
42
     * Must throw RuntimeException for any failures.
43
     *
44
     * @return void
45
     *
46
     * @throws RuntimeException
47
     */
48
    public function forget(string $class, string $property, ?string $context = null)
49
    {
50
        throw new RuntimeException('Forget method not implemented for current Settings handler.');
×
51
    }
52

53
    /**
54
     * All handlers MUST support flushing all values.
55
     *
56
     * @return void
57
     *
58
     * @throws RuntimeException
59
     */
60
    public function flush()
61
    {
62
        throw new RuntimeException('Flush method not implemented for current Settings handler.');
×
63
    }
64

65
    /**
66
     * All handlers that support deferWrites MUST support this method.
67
     *
68
     * @return void
69
     *
70
     * @throws RuntimeException
71
     */
72
    public function persistPendingProperties()
73
    {
NEW
74
        throw new RuntimeException('PersistPendingProperties method not implemented for current Settings handler.');
×
75
    }
76

77
    /**
78
     * Takes care of converting some item types so they can be safely
79
     * stored and re-hydrated into the config files.
80
     *
81
     * @param mixed $value
82
     *
83
     * @return mixed|string
84
     */
85
    protected function prepareValue($value)
86
    {
87
        if (is_bool($value)) {
110✔
88
            return (int) $value;
12✔
89
        }
90

91
        if (is_array($value) || is_object($value)) {
100✔
92
            return serialize($value);
8✔
93
        }
94

95
        return $value;
92✔
96
    }
97

98
    /**
99
     * Handles some special case conversions that
100
     * data might have been saved as, such as booleans
101
     * and serialized data.
102
     *
103
     * @param mixed $value
104
     *
105
     * @return bool|mixed
106
     */
107
    protected function parseValue($value, string $type)
108
    {
109
        // Serialized?
110
        if ($this->isSerialized($value)) {
82✔
111
            $value = unserialize($value);
8✔
112
        }
113

114
        settype($value, $type);
82✔
115

116
        return $value;
82✔
117
    }
118

119
    /**
120
     * Checks to see if an object is serialized and correctly formatted.
121
     *
122
     * Taken from Wordpress core functions.
123
     *
124
     * @param mixed $data
125
     * @param bool  $strict Whether to be strict about the end of the string.
126
     */
127
    protected function isSerialized($data, $strict = true): bool
128
    {
129
        // If it isn't a string, it isn't serialized.
130
        if (! is_string($data)) {
82✔
131
            return false;
22✔
132
        }
133
        $data = trim($data);
60✔
134
        if ('N;' === $data) {
60✔
135
            return true;
×
136
        }
137
        if (strlen($data) < 4) {
60✔
138
            return false;
24✔
139
        }
140
        if (':' !== $data[1]) {
38✔
141
            return false;
30✔
142
        }
143
        if ($strict) {
8✔
144
            $lastc = substr($data, -1);
8✔
145
            if (';' !== $lastc && '}' !== $lastc) {
8✔
146
                return false;
×
147
            }
148
        } else {
149
            $semicolon = strpos($data, ';');
×
150
            $brace     = strpos($data, '}');
×
151
            // Either ; or } must exist.
152
            if (false === $semicolon && false === $brace) {
×
153
                return false;
×
154
            }
155
            // But neither must be in the first X characters.
156
            if (false !== $semicolon && $semicolon < 3) {
×
157
                return false;
×
158
            }
159
            if (false !== $brace && $brace < 4) {
×
160
                return false;
×
161
            }
162
        }
163
        $token = $data[0];
8✔
164

165
        switch ($token) {
166
            case 's':
8✔
167
                if ($strict) {
×
168
                    if ('"' !== substr($data, -2, 1)) {
×
169
                        return false;
×
170
                    }
171
                } elseif (! str_contains($data, '"')) {
×
172
                    return false;
×
173
                }
174

175
                // Or else fall through.
176
                // no break
177
            case 'a':
8✔
178
            case 'O':
4✔
179
                return (bool) preg_match("/^{$token}:[0-9]+:/s", $data);
8✔
180

181
            case 'b':
×
182
            case 'i':
×
183
            case 'd':
×
184
                $end = $strict ? '$' : '';
×
185

186
                return (bool) preg_match("/^{$token}:[0-9.E+-]+;{$end}/", $data);
×
187
        }
188

189
        return false;
×
190
    }
191
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc