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

codeigniter4 / CodeIgniter4 / 8586246081

07 Apr 2024 04:43AM UTC coverage: 86.602% (+1.0%) from 85.607%
8586246081

push

github

web-flow
Merge pull request #8720 from codeigniter4/4.5

Merge 4.5 into develop

2273 of 2603 new or added lines in 188 files covered. (87.32%)

53 existing lines in 18 files now uncovered.

19947 of 23033 relevant lines covered (86.6%)

189.35 hits per line

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

95.45
/system/Config/BaseConfig.php
1
<?php
2

3
/**
4
 * This file is part of CodeIgniter 4 framework.
5
 *
6
 * (c) CodeIgniter Foundation <admin@codeigniter.com>
7
 *
8
 * For the full copyright and license information, please view
9
 * the LICENSE file that was distributed with this source code.
10
 */
11

12
namespace CodeIgniter\Config;
13

14
use Config\Encryption;
15
use Config\Modules;
16
use ReflectionClass;
17
use ReflectionException;
18
use RuntimeException;
19

20
/**
21
 * Class BaseConfig
22
 *
23
 * Not intended to be used on its own, this class will attempt to
24
 * automatically populate the child class' properties with values
25
 * from the environment.
26
 *
27
 * These can be set within the .env file.
28
 *
29
 * @phpstan-consistent-constructor
30
 * @see \CodeIgniter\Config\BaseConfigTest
31
 */
32
class BaseConfig
33
{
34
    /**
35
     * An optional array of classes that will act as Registrars
36
     * for rapidly setting config class properties.
37
     *
38
     * @var array
39
     */
40
    public static $registrars = [];
41

42
    /**
43
     * Whether to override properties by Env vars and Registrars.
44
     */
45
    public static bool $override = true;
46

47
    /**
48
     * Has module discovery happened yet?
49
     *
50
     * @var bool
51
     */
52
    protected static $didDiscovery = false;
53

54
    /**
55
     * The modules configuration.
56
     *
57
     * @var Modules|null
58
     */
59
    protected static $moduleConfig;
60

61
    public static function __set_state(array $array)
62
    {
63
        static::$override = false;
2✔
64
        $obj              = new static();
2✔
65
        static::$override = true;
2✔
66

67
        $properties = array_keys(get_object_vars($obj));
2✔
68

69
        foreach ($properties as $property) {
2✔
70
            $obj->{$property} = $array[$property];
2✔
71
        }
72

73
        return $obj;
2✔
74
    }
75

76
    /**
77
     * @internal For testing purposes only.
78
     * @testTag
79
     */
80
    public static function setModules(Modules $modules): void
81
    {
82
        static::$moduleConfig = $modules;
1✔
83
    }
84

85
    /**
86
     * @internal For testing purposes only.
87
     * @testTag
88
     */
89
    public static function reset(): void
90
    {
91
        static::$registrars   = [];
18✔
92
        static::$override     = true;
18✔
93
        static::$didDiscovery = false;
18✔
94
        static::$moduleConfig = null;
18✔
95
    }
96

97
    /**
98
     * Will attempt to get environment variables with names
99
     * that match the properties of the child class.
100
     *
101
     * The "shortPrefix" is the lowercase-only config class name.
102
     */
103
    public function __construct()
104
    {
105
        static::$moduleConfig ??= new Modules();
6,398✔
106

107
        if (! static::$override) {
6,398✔
108
            return;
2✔
109
        }
110

111
        $this->registerProperties();
6,398✔
112

113
        $properties  = array_keys(get_object_vars($this));
6,398✔
114
        $prefix      = static::class;
6,398✔
115
        $slashAt     = strrpos($prefix, '\\');
6,398✔
116
        $shortPrefix = strtolower(substr($prefix, $slashAt === false ? 0 : $slashAt + 1));
6,398✔
117

118
        foreach ($properties as $property) {
6,398✔
119
            $this->initEnvValue($this->{$property}, $property, $prefix, $shortPrefix);
6,398✔
120

121
            if ($this instanceof Encryption && $property === 'key') {
6,398✔
122
                if (str_starts_with($this->{$property}, 'hex2bin:')) {
34✔
123
                    // Handle hex2bin prefix
124
                    $this->{$property} = hex2bin(substr($this->{$property}, 8));
2✔
125
                } elseif (str_starts_with($this->{$property}, 'base64:')) {
32✔
126
                    // Handle base64 prefix
127
                    $this->{$property} = base64_decode(substr($this->{$property}, 7), true);
2✔
128
                }
129
            }
130
        }
131
    }
132

133
    /**
134
     * Initialization an environment-specific configuration setting
135
     *
136
     * @param array|bool|float|int|string|null $property
137
     *
138
     * @return void
139
     */
140
    protected function initEnvValue(&$property, string $name, string $prefix, string $shortPrefix)
141
    {
142
        if (is_array($property)) {
6,398✔
143
            foreach (array_keys($property) as $key) {
6,391✔
144
                $this->initEnvValue($property[$key], "{$name}.{$key}", $prefix, $shortPrefix);
6,391✔
145
            }
146
        } elseif (($value = $this->getEnvValue($name, $prefix, $shortPrefix)) !== false && $value !== null) {
6,398✔
147
            if ($value === 'false') {
6,346✔
148
                $value = false;
10✔
149
            } elseif ($value === 'true') {
6,346✔
150
                $value = true;
10✔
151
            }
152
            if (is_bool($value)) {
6,346✔
153
                $property = $value;
10✔
154

155
                return;
10✔
156
            }
157

158
            $value = trim($value, '\'"');
6,346✔
159

160
            if (is_int($property)) {
6,346✔
161
                $value = (int) $value;
10✔
162
            } elseif (is_float($property)) {
6,346✔
163
                $value = (float) $value;
10✔
164
            }
165

166
            // If the default value of the property is `null` and the type is not
167
            // `string`, TypeError will happen.
168
            // So cannot set `declare(strict_types=1)` in this file.
169
            $property = $value;
6,346✔
170
        }
171
    }
172

173
    /**
174
     * Retrieve an environment-specific configuration setting
175
     *
176
     * @return string|null
177
     */
178
    protected function getEnvValue(string $property, string $prefix, string $shortPrefix)
179
    {
180
        $shortPrefix        = ltrim($shortPrefix, '\\');
6,398✔
181
        $underscoreProperty = str_replace('.', '_', $property);
6,398✔
182

183
        switch (true) {
184
            case array_key_exists("{$shortPrefix}.{$property}", $_ENV):
6,398✔
185
                return $_ENV["{$shortPrefix}.{$property}"];
12✔
186

187
            case array_key_exists("{$shortPrefix}_{$underscoreProperty}", $_ENV):
6,398✔
188
                return $_ENV["{$shortPrefix}_{$underscoreProperty}"];
10✔
189

190
            case array_key_exists("{$shortPrefix}.{$property}", $_SERVER):
6,398✔
191
                return $_SERVER["{$shortPrefix}.{$property}"];
6,346✔
192

193
            case array_key_exists("{$shortPrefix}_{$underscoreProperty}", $_SERVER):
6,398✔
194
                return $_SERVER["{$shortPrefix}_{$underscoreProperty}"];
×
195

196
            case array_key_exists("{$prefix}.{$property}", $_ENV):
6,398✔
197
                return $_ENV["{$prefix}.{$property}"];
10✔
198

199
            case array_key_exists("{$prefix}_{$underscoreProperty}", $_ENV):
6,398✔
200
                return $_ENV["{$prefix}_{$underscoreProperty}"];
10✔
201

202
            case array_key_exists("{$prefix}.{$property}", $_SERVER):
6,398✔
203
                return $_SERVER["{$prefix}.{$property}"];
1✔
204

205
            case array_key_exists("{$prefix}_{$underscoreProperty}", $_SERVER):
6,398✔
206
                return $_SERVER["{$prefix}_{$underscoreProperty}"];
×
207

208
            default:
209
                $value = getenv("{$shortPrefix}.{$property}");
6,398✔
210
                $value = $value === false ? getenv("{$shortPrefix}_{$underscoreProperty}") : $value;
6,398✔
211
                $value = $value === false ? getenv("{$prefix}.{$property}") : $value;
6,398✔
212
                $value = $value === false ? getenv("{$prefix}_{$underscoreProperty}") : $value;
6,398✔
213

214
                return $value === false ? null : $value;
6,398✔
215
        }
216
    }
217

218
    /**
219
     * Provides external libraries a simple way to register one or more
220
     * options into a config file.
221
     *
222
     * @return void
223
     *
224
     * @throws ReflectionException
225
     */
226
    protected function registerProperties()
227
    {
228
        if (! static::$moduleConfig->shouldDiscover('registrars')) {
6,398✔
229
            return;
1✔
230
        }
231

232
        if (! static::$didDiscovery) {
6,398✔
233
            $locator         = service('locator');
19✔
234
            $registrarsFiles = $locator->search('Config/Registrar.php');
19✔
235

236
            foreach ($registrarsFiles as $file) {
19✔
237
                $className = $locator->findQualifiedNameFromPath($file);
19✔
238

239
                if ($className === false) {
19✔
NEW
240
                    continue;
×
241
                }
242

243
                static::$registrars[] = new $className();
19✔
244
            }
245

246
            static::$didDiscovery = true;
19✔
247
        }
248

249
        $shortName = (new ReflectionClass($this))->getShortName();
6,398✔
250

251
        // Check the registrar class for a method named after this class' shortName
252
        foreach (static::$registrars as $callable) {
6,398✔
253
            // ignore non-applicable registrars
254
            if (! method_exists($callable, $shortName)) {
6,398✔
255
                continue; // @codeCoverageIgnore
256
            }
257

258
            $properties = $callable::$shortName();
757✔
259

260
            if (! is_array($properties)) {
757✔
261
                throw new RuntimeException('Registrars must return an array of properties and their values.');
1✔
262
            }
263

264
            foreach ($properties as $property => $value) {
756✔
265
                if (isset($this->{$property}) && is_array($this->{$property}) && is_array($value)) {
682✔
266
                    $this->{$property} = array_merge($this->{$property}, $value);
682✔
267
                } else {
268
                    $this->{$property} = $value;
×
269
                }
270
            }
271
        }
272
    }
273
}
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

© 2026 Coveralls, Inc