Passed
Push — main ( 8b73d6...c69a6f )
by Dimitri
03:18
created

Config::has()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
/**
4
 * This file is part of Blitz PHP framework.
5
 *
6
 * (c) 2022 Dimitri Sitchet Tomkeu <[email protected]>
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 BlitzPHP\Config;
13
14
use BlitzPHP\Container\Services;
15
use BlitzPHP\Exceptions\ConfigException;
16
use BlitzPHP\Utilities\Helpers;
17
use InvalidArgumentException;
18
use Nette\Schema\Expect;
19
use Nette\Schema\Schema;
20
21
class Config
22
{
23
    /**
24
     * Fichier de configuration déjà chargé
25
     */
26
    private static array $loaded = [];
27
28
	/**
29
	 * Drapeau permettant de savoir si la config a deja ete initialiser
30
	 */
31
	private static bool $initialized = false;
32
33
	private Configurator $configurator;
34
35
    public function __construct()
36
    {
37
		$this->configurator = new Configurator();
38
		$this->initialize();
39
    }
40
41
	/**
42
     * Détermine si une clé de configuration existe.
43
     */
44
	public function exists(string $key): bool
45
	{
46
		if (! $this->configurator->exists($key)) {
47
			$config = explode('.', $key);
48
        	$this->load($config[0]);
49
50
        	return $this->configurator->exists(implode('.', $config));
51
		}
52
53
		return true;
54
	}
55
56
	/**
57
     * Détermine s'il y'a une clé de configuration.
58
     */
59
	public function has(string $key): bool
60
	{
61
		return $this->exists($key);
62
	}
63
64
	/**
65
     * Détermine s'il manque une clé de configuration.
66
     */
67
	public function missing(string $key): bool
68
	{
69
		return ! $this->exists($key);
70
	}
71
72
    /**
73
     * Renvoyer une configuration de l'application
74
     *
75
     * @return mixed
76
     */
77
    public function get(string $key, mixed $default = null)
78
    {
79
        if ($this->exists($key)) {
80
            return $this->configurator->get($key);
81
        }
82
83
		if (func_num_args() > 1) {
84
			return $default;
85
		}
86
		
87
		$path = explode('.', $key);
88
89
		throw ConfigException::notFound(implode(' » ', $path));
90
	}
91
92
    /**
93
     * Définir une configuration de l'application
94
     */
95
    public function set(string $key, $value)
96
    {
97
       $this->configurator->set($key, $value);
98
    }
99
100
    /**
101
     * Charger la configuration spécifique dans le scoope
102
     *
103
     * @param string|string[] $config
104
     */
105
    public function load($config, ?string $file = null, ?Schema $schema = null)
106
    {
107
        if (is_array($config)) {
108
            foreach ($config as $key => $value) {
109
                if (! is_string($value) || empty($value)) {
110
                    continue;
111
                }
112
                if (is_string($key)) {
113
                    $file = $value;
114
                    $conf = $key;
115
                } else {
116
                    $file = null;
117
                    $conf = $value;
118
                }
119
                self::load($conf, $file);
0 ignored issues
show
Bug Best Practice introduced by
The method BlitzPHP\Config\Config::load() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

119
                self::/** @scrutinizer ignore-call */ 
120
                      load($conf, $file);
Loading history...
120
            }
121
        } elseif (is_string($config) && ! isset(self::$loaded[$config])) {
122
            if (empty($file)) {
123
                $file = self::path($config);
124
            }
125
126
            $configurations = [];
127
            if (file_exists($file) && ! in_array($file, get_included_files(), true)) {
128
                $configurations = (array) require $file;
129
            }
130
131
            if (empty($schema)) {
132
                $schema = self::schema($config);
133
            }
134
135
			$this->configurator->addSchema($config, $schema, false);
136
			$this->configurator->merge([$config => (array) $configurations]);
137
138
            self::$loaded[$config] = $file;
139
        }
140
    }
141
142
    /**
143
     * Affiche l'exception dû à la mauvaise definition d'une configuration
144
     *
145
     * @param array|string $accepts_values
146
     * @param string       $group          (app, data, database, etc.)
147
     */
148
    public static function exceptBadConfigValue(string $config_key, $accepts_values, string $group)
149
    {
150
        if (is_array($accepts_values)) {
151
            $accepts_values = '(Accept values: ' . implode('/', $accepts_values) . ')';
152
        } elseif (! is_string($accepts_values)) {
0 ignored issues
show
introduced by
The condition is_string($accepts_values) is always true.
Loading history...
153
            throw new InvalidArgumentException('Misuse of the method ' . __METHOD__);
154
        }
155
156
        throw new ConfigException("The '{$group}.{$config_key} configuration is not set correctly. {$accepts_values} \n Please edit '{" . self::path($group) . "}' file to correct it");
157
    }
158
159
    /**
160
     * Renvoie le chemin du fichier d'un groupe de configuration donné
161
     */
162
    public static function path(string $path): string
163
    {
164
        $path = preg_replace('#\.php$#', '', $path);
165
166
		if (file_exists($file = CONFIG_PATH . $path . '.php')) {
167
			return $file;
168
		}
169
170
		$paths = Services::locator()->search('Config/' . $path);
171
172
		if (isset($paths[0]) && file_exists($path[0])) {
173
			return $paths[0];
174
		}
175
		
176
		return '';
177
    }
178
179
    /**
180
     * Retrouve le schema de configuration d'un groupe
181
     */
182
    public static function schema(string $key): Schema
183
    {
184
        $file        = 'schemas' . DS . Helpers::ensureExt($key . '.config', 'php');
185
        $syst_schema = SYST_PATH . 'Constants' . DS . $file;
186
        $app_schema  = CONFIG_PATH . $file;
187
188
        if (file_exists($syst_schema)) {
189
            $schema = require $syst_schema;
190
        } elseif (file_exists($app_schema)) {
191
            $schema = require $app_schema;
192
        }
193
194
        if (empty($schema) || ! ($schema instanceof Schema)) {
195
            $schema = Expect::mixed();
196
        }
197
198
        return $schema;
199
    }
200
201
    /**
202
     * Initialiser la configuration du système avec les données des fichier de configuration
203
     */
204
    private function initialize()
205
    {
206
		if (self::$initialized) {
207
			return;
208
		}
209
		
210
		$this->load(['app']);
211
        
212
        ini_set('log_errors', 1);
213
        ini_set('error_log', LOG_PATH . 'blitz-logs');
214
215
        $this->initializeURL();
216
        $this->initializeEnvironment();
217
        $this->initializeDebugbar();
218
219
		self::$initialized = true;
220
    }
221
222
    /**
223
     * Initialise l'URL
224
     */
225
    private function initializeURL()
226
    {
227
        $config = $this->get('app.base_url', 'auto');
228
        
229
        if ($config === 'auto' || empty($config)) {
230
            $config = rtrim(str_replace('\\', '/', Helpers::findBaseUrl()), '/');
231
        }
232
233
        $this->set('app.base_url', $config);
234
    }
235
236
    /**
237
     * Initialise l'environnement d'execution de l'application
238
     */
239
    private function initializeEnvironment()
240
    {
241
        $environment = $config = $this->get('app.environment');
242
243
        if ($config === 'auto') {
244
            $config = is_online() ? 'production' : 'development';
245
        } elseif ($config === 'dev') {
246
            $config = 'development';
247
        } elseif ($config === 'prod') {
248
            $config = 'production';
249
        }
250
251
        if ($config !== $environment) {
252
            $this->set('app.environment', $config);
253
        }
254
255
        switch ($config) {
256
            case 'development':
257
                error_reporting(-1);
258
                ini_set('display_errors', 1);
259
                break;
260
261
            case 'test':
262
            case 'production':
263
                ini_set('display_errors', 0);
264
                error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED);
265
                break;
266
267
            default:
268
                self::exceptBadConfigValue('environment', ['development', 'production', 'test', 'auto'], 'app');
269
        }
270
271
        defined('BLITZ_DEBUG') || define('BLITZ_DEBUG', $config !== 'production');
272
    }
273
274
    /**
275
     * Initialise les paramètres de la bar de debug
276
     */
277
    private function initializeDebugbar()
278
    {
279
        $config = $this->get('app.show_debugbar', 'auto');
280
        
281
        if (! in_array($config, ['auto', true, false], true)) {
282
            self::exceptBadConfigValue('show_debugbar', ['auto', true, false], 'app');
283
        }
284
285
        if ($config === 'auto') {
286
            $this->set('app.show_debugbar', ! is_online());
287
        }
288
    }
289
}
290