Translated using Weblate (Dutch)
[phpmyadmin.git] / libraries / config / ConfigFile.php
blob26a28438004caaaf452e3ecbbd7e4ff72860d63c
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * Config file management
6 * @package PhpMyAdmin
7 */
8 namespace PMA\libraries\config;
10 use PMA\libraries\Config;
11 use PMA\libraries\Core;
13 /**
14 * Config file management class.
15 * Stores its data in $_SESSION
17 * @package PhpMyAdmin
19 class ConfigFile
21 /**
22 * Stores default PMA config from config.default.php
23 * @var array
25 private $_defaultCfg;
27 /**
28 * Stores allowed values for non-standard fields
29 * @var array
31 private $_cfgDb;
33 /**
34 * Stores original PMA config, not modified by user preferences
35 * @var Config
37 private $_baseCfg;
39 /**
40 * Whether we are currently working in PMA Setup context
41 * @var bool
43 private $_isInSetup;
45 /**
46 * Keys which will be always written to config file
47 * @var array
49 private $_persistKeys = array();
51 /**
52 * Changes keys while updating config in {@link updateWithGlobalConfig()}
53 * or reading by {@link getConfig()} or {@link getConfigArray()}
54 * @var array
56 private $_cfgUpdateReadMapping = array();
58 /**
59 * Key filter for {@link set()}
60 * @var array|null
62 private $_setFilter;
64 /**
65 * Instance id (key in $_SESSION array, separate for each server -
66 * ConfigFile{server id})
67 * @var string
69 private $_id;
71 /**
72 * Result for {@link _flattenArray()}
73 * @var array|null
75 private $_flattenArrayResult;
77 /**
78 * Constructor
80 * @param array $base_config base configuration read from
81 * {@link PMA\libraries\Config::$base_config},
82 * use only when not in PMA Setup
84 public function __construct(array $base_config = null)
86 // load default config values
87 $cfg = &$this->_defaultCfg;
88 include './libraries/config.default.php';
89 $cfg['fontsize'] = '82%';
91 // load additional config information
92 $cfg_db = &$this->_cfgDb;
93 include './libraries/config.values.php';
95 // apply default values overrides
96 if (count($cfg_db['_overrides'])) {
97 foreach ($cfg_db['_overrides'] as $path => $value) {
98 Core::arrayWrite($path, $cfg, $value);
102 $this->_baseCfg = $base_config;
103 $this->_isInSetup = is_null($base_config);
104 $this->_id = 'ConfigFile' . $GLOBALS['server'];
105 if (!isset($_SESSION[$this->_id])) {
106 $_SESSION[$this->_id] = array();
111 * Sets names of config options which will be placed in config file even if
112 * they are set to their default values (use only full paths)
114 * @param array $keys the names of the config options
116 * @return void
118 public function setPersistKeys(array $keys)
120 // checking key presence is much faster than searching so move values
121 // to keys
122 $this->_persistKeys = array_flip($keys);
126 * Returns flipped array set by {@link setPersistKeys()}
128 * @return array
130 public function getPersistKeysMap()
132 return $this->_persistKeys;
136 * By default ConfigFile allows setting of all configuration keys, use
137 * this method to set up a filter on {@link set()} method
139 * @param array|null $keys array of allowed keys or null to remove filter
141 * @return void
143 public function setAllowedKeys($keys)
145 if ($keys === null) {
146 $this->_setFilter = null;
147 return;
149 // checking key presence is much faster than searching so move values
150 // to keys
151 $this->_setFilter = array_flip($keys);
155 * Sets path mapping for updating config in
156 * {@link updateWithGlobalConfig()} or reading
157 * by {@link getConfig()} or {@link getConfigArray()}
159 * @param array $mapping Contains the mapping of "Server/config options"
160 * to "Server/1/config options"
162 * @return void
164 public function setCfgUpdateReadMapping(array $mapping)
166 $this->_cfgUpdateReadMapping = $mapping;
170 * Resets configuration data
172 * @return void
174 public function resetConfigData()
176 $_SESSION[$this->_id] = array();
180 * Sets configuration data (overrides old data)
182 * @param array $cfg Configuration options
184 * @return void
186 public function setConfigData(array $cfg)
188 $_SESSION[$this->_id] = $cfg;
192 * Sets config value
194 * @param string $path Path
195 * @param mixed $value Value
196 * @param string $canonical_path Canonical path
198 * @return void
200 public function set($path, $value, $canonical_path = null)
202 if ($canonical_path === null) {
203 $canonical_path = $this->getCanonicalPath($path);
205 // apply key whitelist
206 if ($this->_setFilter !== null
207 && ! isset($this->_setFilter[$canonical_path])
209 return;
211 // if the path isn't protected it may be removed
212 if (isset($this->_persistKeys[$canonical_path])) {
213 Core::arrayWrite($path, $_SESSION[$this->_id], $value);
214 return;
217 $default_value = $this->getDefault($canonical_path);
218 $remove_path = $value === $default_value;
219 if ($this->_isInSetup) {
220 // remove if it has a default value or is empty
221 $remove_path = $remove_path
222 || (empty($value) && empty($default_value));
223 } else {
224 // get original config values not overwritten by user
225 // preferences to allow for overwriting options set in
226 // config.inc.php with default values
227 $instance_default_value = Core::arrayRead(
228 $canonical_path,
229 $this->_baseCfg
231 // remove if it has a default value and base config (config.inc.php)
232 // uses default value
233 $remove_path = $remove_path
234 && ($instance_default_value === $default_value);
236 if ($remove_path) {
237 Core::arrayRemove($path, $_SESSION[$this->_id]);
238 return;
241 Core::arrayWrite($path, $_SESSION[$this->_id], $value);
245 * Flattens multidimensional array, changes indices to paths
246 * (eg. 'key/subkey').
247 * Used as array_walk() callback.
249 * @param mixed $value Value
250 * @param mixed $key Key
251 * @param mixed $prefix Prefix
253 * @return void
255 private function _flattenArray($value, $key, $prefix)
257 // no recursion for numeric arrays
258 if (is_array($value) && !isset($value[0])) {
259 $prefix .= $key . '/';
260 array_walk($value, array($this, '_flattenArray'), $prefix);
261 } else {
262 $this->_flattenArrayResult[$prefix . $key] = $value;
267 * Returns default config in a flattened array
269 * @return array
271 public function getFlatDefaultConfig()
273 $this->_flattenArrayResult = array();
274 array_walk($this->_defaultCfg, array($this, '_flattenArray'), '');
275 $flat_cfg = $this->_flattenArrayResult;
276 $this->_flattenArrayResult = null;
277 return $flat_cfg;
281 * Updates config with values read from given array
282 * (config will contain differences to defaults from config.defaults.php).
284 * @param array $cfg Configuration
286 * @return void
288 public function updateWithGlobalConfig(array $cfg)
290 // load config array and flatten it
291 $this->_flattenArrayResult = array();
292 array_walk($cfg, array($this, '_flattenArray'), '');
293 $flat_cfg = $this->_flattenArrayResult;
294 $this->_flattenArrayResult = null;
296 // save values map for translating a few user preferences paths,
297 // should be complemented by code reading from generated config
298 // to perform inverse mapping
299 foreach ($flat_cfg as $path => $value) {
300 if (isset($this->_cfgUpdateReadMapping[$path])) {
301 $path = $this->_cfgUpdateReadMapping[$path];
303 $this->set($path, $value, $path);
308 * Returns config value or $default if it's not set
310 * @param string $path Path of config file
311 * @param mixed $default Default values
313 * @return mixed
315 public function get($path, $default = null)
317 return Core::arrayRead($path, $_SESSION[$this->_id], $default);
321 * Returns default config value or $default it it's not set ie. it doesn't
322 * exist in config.default.php ($cfg) and config.values.php
323 * ($_cfg_db['_overrides'])
325 * @param string $canonical_path Canonical path
326 * @param mixed $default Default value
328 * @return mixed
330 public function getDefault($canonical_path, $default = null)
332 return Core::arrayRead($canonical_path, $this->_defaultCfg, $default);
336 * Returns config value, if it's not set uses the default one; returns
337 * $default if the path isn't set and doesn't contain a default value
339 * @param string $path Path
340 * @param mixed $default Default value
342 * @return mixed
344 public function getValue($path, $default = null)
346 $v = Core::arrayRead($path, $_SESSION[$this->_id], null);
347 if ($v !== null) {
348 return $v;
350 $path = $this->getCanonicalPath($path);
351 return $this->getDefault($path, $default);
355 * Returns canonical path
357 * @param string $path Path
359 * @return string
361 public function getCanonicalPath($path)
363 return preg_replace('#^Servers/([\d]+)/#', 'Servers/1/', $path);
367 * Returns config database entry for $path ($cfg_db in config_info.php)
369 * @param string $path path of the variable in config db
370 * @param mixed $default default value
372 * @return mixed
374 public function getDbEntry($path, $default = null)
376 return Core::arrayRead($path, $this->_cfgDb, $default);
380 * Returns server count
382 * @return int
384 public function getServerCount()
386 return isset($_SESSION[$this->_id]['Servers'])
387 ? count($_SESSION[$this->_id]['Servers'])
388 : 0;
392 * Returns server list
394 * @return array|null
396 public function getServers()
398 return isset($_SESSION[$this->_id]['Servers'])
399 ? $_SESSION[$this->_id]['Servers']
400 : null;
404 * Returns DSN of given server
406 * @param integer $server server index
408 * @return string
410 public function getServerDSN($server)
412 if (!isset($_SESSION[$this->_id]['Servers'][$server])) {
413 return '';
416 $path = 'Servers/' . $server;
417 $dsn = 'mysqli://';
418 if ($this->getValue("$path/auth_type") == 'config') {
419 $dsn .= $this->getValue("$path/user");
420 if (! empty($this->getValue("$path/password"))) {
421 $dsn .= ':***';
423 $dsn .= '@';
425 if ($this->getValue("$path/host") != 'localhost') {
426 $dsn .= $this->getValue("$path/host");
427 $port = $this->getValue("$path/port");
428 if ($port) {
429 $dsn .= ':' . $port;
431 } else {
432 $dsn .= $this->getValue("$path/socket");
434 return $dsn;
438 * Returns server name
440 * @param int $id server index
442 * @return string
444 public function getServerName($id)
446 if (!isset($_SESSION[$this->_id]['Servers'][$id])) {
447 return '';
449 $verbose = $this->get("Servers/$id/verbose");
450 if (!empty($verbose)) {
451 return $verbose;
453 $host = $this->get("Servers/$id/host");
454 return empty($host) ? 'localhost' : $host;
458 * Removes server
460 * @param int $server server index
462 * @return void
464 public function removeServer($server)
466 if (!isset($_SESSION[$this->_id]['Servers'][$server])) {
467 return;
469 $last_server = $this->getServerCount();
471 for ($i = $server; $i < $last_server; $i++) {
472 $_SESSION[$this->_id]['Servers'][$i]
473 = $_SESSION[$this->_id]['Servers'][$i + 1];
475 unset($_SESSION[$this->_id]['Servers'][$last_server]);
477 if (isset($_SESSION[$this->_id]['ServerDefault'])
478 && $_SESSION[$this->_id]['ServerDefault'] == $last_server
480 unset($_SESSION[$this->_id]['ServerDefault']);
485 * Returns configuration array (full, multidimensional format)
487 * @return array
489 public function getConfig()
491 $c = $_SESSION[$this->_id];
492 foreach ($this->_cfgUpdateReadMapping as $map_to => $map_from) {
493 // if the key $c exists in $map_to
494 if (Core::arrayRead($map_to, $c) !== null) {
495 Core::arrayWrite($map_to, $c, Core::arrayRead($map_from, $c));
496 Core::arrayRemove($map_from, $c);
499 return $c;
503 * Returns configuration array (flat format)
505 * @return array
507 public function getConfigArray()
509 $this->_flattenArrayResult = array();
510 array_walk($_SESSION[$this->_id], array($this, '_flattenArray'), '');
511 $c = $this->_flattenArrayResult;
512 $this->_flattenArrayResult = null;
514 $persistKeys = array_diff(
515 array_keys($this->_persistKeys),
516 array_keys($c)
518 foreach ($persistKeys as $k) {
519 $c[$k] = $this->getDefault($this->getCanonicalPath($k));
522 foreach ($this->_cfgUpdateReadMapping as $map_to => $map_from) {
523 if (!isset($c[$map_from])) {
524 continue;
526 $c[$map_to] = $c[$map_from];
527 unset($c[$map_from]);
529 return $c;