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

codeigniter4 / settings / 20033287059

08 Dec 2025 03:25PM UTC coverage: 81.911%. First build
20033287059

Pull #157

github

web-flow
Merge e972c1655 into 7fb10c218
Pull Request #157: Implement a getAll function

0 of 29 new or added lines in 3 files covered. (0.0%)

403 of 492 relevant lines covered (81.91%)

13.34 hits per line

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

69.01
/src/Handlers/ArrayHandler.php
1
<?php
2

3
namespace CodeIgniter\Settings\Handlers;
4

5
use CodeIgniter\Events\Events;
6

7
/**
8
 * Array Settings Handler
9
 *
10
 * Uses local storage to handle non-persistent
11
 * Settings requests. Useful mostly for testing
12
 * or extension by true persistent handlers.
13
 */
14
class ArrayHandler extends BaseHandler
15
{
16
    /**
17
     * Storage for general settings.
18
     * Format: ['class' => ['property' => ['value', 'type']]]
19
     *
20
     * @var array<string, array<string, array{mixed, string}>>
21
     */
22
    private array $general = [];
23

24
    /**
25
     * Storage for context settings.
26
     * Format: ['context' => ['class' => ['property' => ['value', 'type']]]]
27
     *
28
     * @var array<string, array<string, array<string, array{mixed, string}>>>
29
     */
30
    private array $contexts = [];
31

32
    /**
33
     * Whether to defer writes until the end of request.
34
     * Used by handlers that support deferred writes.
35
     */
36
    protected bool $deferWrites = false;
37

38
    /**
39
     * Array of properties that have been modified but not persisted.
40
     * Used by handlers that support deferred writes.
41
     * Format: ['key' => ['class' => ..., 'property' => ..., 'value' => ..., 'context' => ..., 'delete' => ...]]
42
     *
43
     * @var array<string, array{class: string, property: string, value: mixed, context: string|null, delete: bool}>
44
     */
45
    protected array $pendingProperties = [];
46

47
    public function has(string $class, string $property, ?string $context = null): bool
48
    {
49
        return $this->hasStored($class, $property, $context);
9✔
50
    }
51

52
    public function get(string $class, string $property, ?string $context = null)
53
    {
54
        return $this->getStored($class, $property, $context);
7✔
55
    }
56

57
    public function getAll(?string $class, ?string $context = null)
58
    {
NEW
59
        return $this->getAllStored($class, $context);
×
60
    }
61

62
    public function set(string $class, string $property, $value = null, ?string $context = null)
63
    {
64
        $this->setStored($class, $property, $value, $context);
7✔
65
    }
66

67
    public function forget(string $class, string $property, ?string $context = null)
68
    {
69
        $this->forgetStored($class, $property, $context);
1✔
70
    }
71

72
    public function flush()
73
    {
74
        $this->general  = [];
9✔
75
        $this->contexts = [];
9✔
76
    }
77

78
    /**
79
     * Checks whether this value is in storage.
80
     */
81
    protected function hasStored(string $class, string $property, ?string $context): bool
82
    {
83
        if ($context === null) {
51✔
84
            return isset($this->general[$class]) && array_key_exists($property, $this->general[$class]);
49✔
85
        }
86

87
        return isset($this->contexts[$context][$class]) && array_key_exists($property, $this->contexts[$context][$class]);
10✔
88
    }
89

90
    /**
91
     * Retrieves a value from storage.
92
     *
93
     * @return mixed
94
     */
95
    protected function getStored(string $class, string $property, ?string $context)
96
    {
97
        if (! $this->has($class, $property, $context)) {
35✔
98
            return null;
×
99
        }
100

101
        return $context === null
35✔
102
            ? $this->parseValue(...$this->general[$class][$property])
34✔
103
            : $this->parseValue(...$this->contexts[$context][$class][$property]);
35✔
104
    }
105

106
    /**
107
     * Retrieves all values from storage.
108
     *
109
     * @return mixed|null
110
     */
111
    protected function getAllStored(?string $class, ?string $context)
112
    {
NEW
113
        $properties = null;
×
114

NEW
115
        if ($context === null) {
×
NEW
116
            if ($class === null) {
×
NEW
117
                $properties = $this->general;
×
NEW
118
            } elseif (isset($this->general[$class])) {
×
NEW
119
                $properties = $this->general[$class];
×
120
            }
NEW
121
        } elseif (isset($this->contexts[$context])) {
×
NEW
122
            if ($class === null) {
×
NEW
123
                $properties = $this->contexts[$context];
×
NEW
124
            } elseif (isset($this->contexts[$context][$class])) {
×
NEW
125
                $properties = $this->contexts[$context][$class];
×
126
            }
127
        }
128

NEW
129
        if($properties === null)
×
NEW
130
            return null;
×
131

NEW
132
       if($class === null) {
×
NEW
133
            foreach($properties as &$c) {
×
NEW
134
                foreach($c as &$p) {
×
NEW
135
                    $p = $this->parseValue(...$p);
×
136
                }
137
            }
138
        } else {
NEW
139
            foreach($properties as &$p) {
×
NEW
140
                $p = $this->parseValue(...$p);
×
141
            }
142
        }
143

NEW
144
        return $properties;
×
145
    }
146

147
    /**
148
     * Adds values to storage.
149
     *
150
     * @param mixed $value
151
     */
152
    protected function setStored(string $class, string $property, $value, ?string $context): void
153
    {
154
        $type  = gettype($value);
55✔
155
        $value = $this->prepareValue($value);
55✔
156

157
        if ($context === null) {
55✔
158
            $this->general[$class][$property] = [
52✔
159
                $value,
52✔
160
                $type,
52✔
161
            ];
52✔
162
        } else {
163
            $this->contexts[$context][$class][$property] = [
9✔
164
                $value,
9✔
165
                $type,
9✔
166
            ];
9✔
167
        }
168
    }
169

170
    /**
171
     * Deletes an item from storage.
172
     */
173
    protected function forgetStored(string $class, string $property, ?string $context): void
174
    {
175
        if ($context === null) {
9✔
176
            unset($this->general[$class][$property]);
8✔
177
        } else {
178
            unset($this->contexts[$context][$class][$property]);
1✔
179
        }
180
    }
181

182
    /**
183
     * Marks a property as pending (needs to be persisted).
184
     * Used by handlers that support deferred writes.
185
     *
186
     * @param mixed $value
187
     */
188
    protected function markPending(string $class, string $property, $value, ?string $context, bool $isDelete = false): void
189
    {
190
        $key                           = $class . '::' . $property . ($context === null ? '' : '::' . $context);
8✔
191
        $this->pendingProperties[$key] = [
8✔
192
            'class'    => $class,
8✔
193
            'property' => $property,
8✔
194
            'value'    => $value,
8✔
195
            'context'  => $context,
8✔
196
            'delete'   => $isDelete,
8✔
197
        ];
8✔
198
    }
199

200
    /**
201
     * Groups pending properties by class+context combination.
202
     * Useful for handlers that need to persist changes on a per-class basis.
203
     * Format: ['key' => ['class' => ..., 'context' => ..., 'changes' => [...]]]
204
     *
205
     * @return array<string, array{class: string, context: string|null, changes: list<array{class: string, property: string, value: mixed, context: string|null, delete: bool}>}>
206
     */
207
    protected function getPendingPropertiesGrouped(): array
208
    {
209
        $grouped = [];
3✔
210

211
        foreach ($this->pendingProperties as $info) {
3✔
212
            $key = $info['class'] . ($info['context'] === null ? '' : '::' . $info['context']);
3✔
213

214
            if (! isset($grouped[$key])) {
3✔
215
                $grouped[$key] = [
3✔
216
                    'class'   => $info['class'],
3✔
217
                    'context' => $info['context'],
3✔
218
                    'changes' => [],
3✔
219
                ];
3✔
220
            }
221

222
            $grouped[$key]['changes'][] = $info;
3✔
223
        }
224

225
        return $grouped;
3✔
226
    }
227

228
    /**
229
     * Sets up deferred writes for handlers that support it.
230
     *
231
     * @param bool $enabled Whether deferred writes should be enabled
232
     */
233
    protected function setupDeferredWrites(bool $enabled): void
234
    {
235
        $this->deferWrites = $enabled;
54✔
236

237
        if ($this->deferWrites) {
54✔
238
            Events::on('post_system', [$this, 'persistPendingProperties']);
8✔
239
        }
240
    }
241
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc