Fixed: Not selecting a datalabel used to issue a notice(undefined offset)
[phpmyadmin/ammaryasirr.git] / libraries / config / ConfigFile.class.php
blobc1b4e77fdf9d6286aec89647af52fff2c3bac028
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * Config file management
6 * @package phpMyAdmin
7 */
9 /**
10 * Config file management class.
11 * Stores its data in $_SESSION
13 * @package phpMyAdmin
15 class ConfigFile
17 /**
18 * Stores default PMA config from config.default.php
19 * @var array
21 private $cfg;
23 /**
24 * Stores original PMA_Config object, not modified by user preferences
25 * @var PMA_Config
27 private $orgCfgObject;
29 /**
30 * Stores allowed values for non-standard fields
31 * @var array
33 private $cfgDb;
35 /**
36 * Keys which will be always written to config file
37 * @var array
39 private $persistKeys = array();
41 /**
42 * Changes keys while updating config in {@link updateWithGlobalConfig()} or reading
43 * by {@link getConfig()} or {@link getConfigArray()}
44 * @var array
46 private $cfgUpdateReadMapping = array();
48 /**
49 * Key filter for {@link set()}
50 * @var array|null
52 private $setFilter;
54 /**
55 * Instance id (key in $_SESSION array, separate for each server - ConfigFile{server id})
56 * @var string
58 private $id;
60 /**
61 * Result for {@link _flattenArray()}
62 * @var array
64 private $_flattenArrayResult;
66 /**
67 * ConfigFile instance
68 * @var ConfigFile
70 private static $_instance;
72 /**
73 * Private constructor, use {@link getInstance()}
76 private function __construct()
78 // load default config values
79 $cfg = &$this->cfg;
80 require './libraries/config.default.php';
81 $cfg['fontsize'] = '82%';
83 // create PMA_Config to read config.inc.php values
84 $this->orgCfgObject = new PMA_Config(CONFIG_FILE);
86 // load additional config information
87 $cfg_db = &$this->cfgDb;
88 require './libraries/config.values.php';
90 // apply default values overrides
91 if (count($cfg_db['_overrides'])) {
92 foreach ($cfg_db['_overrides'] as $path => $value) {
93 PMA_array_write($path, $cfg, $value);
97 $this->id = 'ConfigFile' . $GLOBALS['server'];
98 if (!isset($_SESSION[$this->id])) {
99 $_SESSION[$this->id] = array();
104 * Returns class instance
106 * @return ConfigFile
108 public static function getInstance()
110 if (is_null(self::$_instance)) {
111 self::$_instance = new ConfigFile();
113 return self::$_instance;
117 * Returns PMA_Config without user preferences applied
119 * @return PMA_Config
121 public function getOrgConfigObj()
123 return $this->orgCfgObject;
127 * Sets names of config options which will be placed in config file even if they are set
128 * to their default values (use only full paths)
130 * @param array $keys
132 public function setPersistKeys($keys)
134 // checking key presence is much faster than searching so move values to keys
135 $this->persistKeys = array_flip($keys);
139 * Returns flipped array set by {@link setPersistKeys()}
141 * @return array
143 public function getPersistKeysMap()
145 return $this->persistKeys;
149 * By default ConfigFile allows setting of all configuration keys, use this method
150 * to set up a filter on {@link set()} method
152 * @param array|null $keys array of allowed keys or null to remove filter
154 public function setAllowedKeys($keys)
156 if ($keys === null) {
157 $this->setFilter = null;
158 return;
160 // checking key presence is much faster than searching so move values to keys
161 $this->setFilter = array_flip($keys);
165 * Sets path mapping for updating config in {@link updateWithGlobalConfig()} or reading
166 * by {@link getConfig()} or {@link getConfigArray()}
167 * @var array
169 public function setCfgUpdateReadMapping(array $mapping)
171 $this->cfgUpdateReadMapping = $mapping;
175 * Resets configuration data
177 public function resetConfigData()
179 $_SESSION[$this->id] = array();
183 * Sets configuration data (overrides old data)
185 * @param array $cfg
187 public function setConfigData(array $cfg)
189 $_SESSION[$this->id] = $cfg;
193 * Sets config value
195 * @param string $path
196 * @param mixed $value
197 * @param string $canonical_path
199 public function set($path, $value, $canonical_path = null)
201 if ($canonical_path === null) {
202 $canonical_path = $this->getCanonicalPath($path);
204 // apply key whitelist
205 if ($this->setFilter !== null && !isset($this->setFilter[$canonical_path])) {
206 return;
208 // remove if the path isn't protected and it's empty or has a default value
209 if (!isset($this->persistKeys[$canonical_path])) {
210 $default_value = $this->getDefault($canonical_path);
211 // we need oryginal config values not overwritten by user preferences
212 // to allow for overwriting options set in config.inc.php with default values
213 $instance_default_value = PMA_array_read($canonical_path, $this->orgCfgObject->settings);
214 if (($value === $default_value && (defined('PMA_SETUP') || $instance_default_value === $default_value))
215 || (empty($value) && empty($default_value) && (defined('PMA_SETUP') || empty($current_global)))) {
216 PMA_array_remove($path, $_SESSION[$this->id]);
217 return;
220 PMA_array_write($path, $_SESSION[$this->id], $value);
224 * Flattens multidimensional array, changes indices to paths (eg. 'key/subkey').
225 * Used as array_walk() callback.
227 * @param mixed $value
228 * @param mixed $key
229 * @param mixed $prefix
231 private function _flattenArray($value, $key, $prefix)
233 // no recursion for numeric arrays
234 if (is_array($value) && !isset($value[0])) {
235 $prefix .= $key . '/';
236 array_walk($value, array($this, '_flattenArray'), $prefix);
237 } else {
238 $this->_flattenArrayResult[$prefix . $key] = $value;
243 * Returns default config in a flattened array
245 * @return array
247 public function getFlatDefaultConfig()
249 $this->_flattenArrayResult = array();
250 array_walk($this->cfg, array($this, '_flattenArray'), '');
251 $flat_cfg = $this->_flattenArrayResult;
252 $this->_flattenArrayResult = null;
253 return $flat_cfg;
257 * Updates config with values read from given array
258 * (config will contain differences to defaults from config.defaults.php).
260 * @param array $cfg
262 public function updateWithGlobalConfig(array $cfg)
264 // load config array and flatten it
265 $this->_flattenArrayResult = array();
266 array_walk($cfg, array($this, '_flattenArray'), '');
267 $flat_cfg = $this->_flattenArrayResult;
268 $this->_flattenArrayResult = null;
270 // save values
271 // map for translating a few user preferences paths, should be complemented
272 // by code reading from generated config to perform inverse mapping
273 foreach ($flat_cfg as $path => $value) {
274 if (isset($this->cfgUpdateReadMapping[$path])) {
275 $path = $this->cfgUpdateReadMapping[$path];
277 $this->set($path, $value, $path);
282 * Returns config value or $default if it's not set
284 * @param string $path
285 * @param mixed $default
286 * @return mixed
288 public function get($path, $default = null)
290 return PMA_array_read($path, $_SESSION[$this->id], $default);
294 * Returns default config value or $default it it's not set ie. it doesn't
295 * exist in config.default.php ($cfg) and config.values.php
296 * ($_cfg_db['_overrides'])
298 * @param string $canonical_path
299 * @param mixed $default
300 * @return mixed
302 public function getDefault($canonical_path, $default = null)
304 return PMA_array_read($canonical_path, $this->cfg, $default);
308 * Returns config value, if it's not set uses the default one; returns
309 * $default if the path isn't set and doesn't contain a default value
311 * @param string $path
312 * @param mixed $default
313 * @return mixed
315 public function getValue($path, $default = null)
317 $v = PMA_array_read($path, $_SESSION[$this->id], null);
318 if ($v !== null) {
319 return $v;
321 $path = $this->getCanonicalPath($path);
322 return $this->getDefault($path, $default);
326 * Returns canonical path
328 * @param string $path
329 * @return string
331 public function getCanonicalPath($path) {
332 return preg_replace('#^Servers/([\d]+)/#', 'Servers/1/', $path);
336 * Returns config database entry for $path ($cfg_db in config_info.php)
338 * @param string $path
339 * @param mixed $default
340 * @return mixed
342 public function getDbEntry($path, $default = null)
344 return PMA_array_read($path, $this->cfgDb, $default);
348 * Returns server count
350 * @return int
352 public function getServerCount()
354 return isset($_SESSION[$this->id]['Servers'])
355 ? count($_SESSION[$this->id]['Servers'])
356 : 0;
360 * Returns server list
362 * @return array|null
364 public function getServers()
366 return isset($_SESSION[$this->id]['Servers'])
367 ? $_SESSION[$this->id]['Servers']
368 : null;
372 * Returns DSN of given server
374 * @param integer $server
375 * @return string
377 function getServerDSN($server)
379 if (!isset($_SESSION[$this->id]['Servers'][$server])) {
380 return '';
383 $path = 'Servers/' . $server;
384 $dsn = $this->getValue("$path/extension") . '://';
385 if ($this->getValue("$path/auth_type") == 'config') {
386 $dsn .= $this->getValue("$path/user");
387 if (!$this->getValue("$path/nopassword")) {
388 $dsn .= ':***';
390 $dsn .= '@';
392 if ($this->getValue("$path/connect_type") == 'tcp') {
393 $dsn .= $this->getValue("$path/host");
394 $port = $this->getValue("$path/port");
395 if ($port) {
396 $dsn .= ':' . $port;
398 } else {
399 $dsn .= $this->getValue("$path/socket");
401 return $dsn;
405 * Returns server name
407 * @param int $id
408 * @return string
410 public function getServerName($id)
412 if (!isset($_SESSION[$this->id]['Servers'][$id])) {
413 return '';
415 $verbose = $this->get("Servers/$id/verbose");
416 if (!empty($verbose)) {
417 return $verbose;
419 $host = $this->get("Servers/$id/host");
420 return empty($host) ? 'localhost' : $host;
424 * Removes server
426 * @param int $server
428 public function removeServer($server)
430 if (!isset($_SESSION[$this->id]['Servers'][$server])) {
431 return;
433 $last_server = $this->getServerCount();
435 for ($i = $server; $i < $last_server; $i++) {
436 $_SESSION[$this->id]['Servers'][$i] = $_SESSION[$this->id]['Servers'][$i+1];
438 unset($_SESSION[$this->id]['Servers'][$last_server]);
440 if (isset($_SESSION[$this->id]['ServerDefault'])
441 && $_SESSION[$this->id]['ServerDefault'] >= 0) {
442 unset($_SESSION[$this->id]['ServerDefault']);
447 * Returns config file path, relative to phpMyAdmin's root path
449 * @return string
451 public function getFilePath()
453 // Load paths
454 if (!defined('SETUP_CONFIG_FILE')) {
455 require_once './libraries/vendor_config.php';
458 return SETUP_CONFIG_FILE;
462 * Returns configuration array (full, multidimensional format)
464 * @return array
466 public function getConfig()
468 $c = $_SESSION[$this->id];
469 foreach ($this->cfgUpdateReadMapping as $map_to => $map_from) {
470 PMA_array_write($map_to, $c, PMA_array_read($map_from, $c));
471 PMA_array_remove($map_from, $c);
473 return $c;
477 * Returns configuration array (flat format)
479 * @return array
481 public function getConfigArray()
483 $this->_flattenArrayResult = array();
484 array_walk($_SESSION[$this->id], array($this, '_flattenArray'), '');
485 $c = $this->_flattenArrayResult;
486 $this->_flattenArrayResult = null;
488 $persistKeys = array_diff(array_keys($this->persistKeys), array_keys($c));
489 foreach ($persistKeys as $k) {
490 $c[$k] = $this->getDefault($k);
493 foreach ($this->cfgUpdateReadMapping as $map_to => $map_from) {
494 if (!isset($c[$map_from])) {
495 continue;
497 $c[$map_to] = $c[$map_from];
498 unset($c[$map_from]);
500 return $c;