User preferences:
[phpmyadmin.git] / libraries / config / ConfigFile.class.php
blob4eff1d13ab2b7b283afc9a021ad0b9852eeefe01
1 <?php
2 /**
3 * Config file management and generation
5 * @license http://www.gnu.org/licenses/gpl.html GNU GPL 2.0
6 * @package phpMyAdmin
7 */
9 /**
10 * Config file management and generation class
12 * @package phpMyAdmin
14 class ConfigFile
16 /**
17 * Stores default PMA config from config.default.php
18 * @var array
20 private $cfg;
22 /**
23 * Stores allowed values for non-standard fields
24 * @var array
26 private $cfgDb;
28 /**
29 * Keys which will be always written to config file
30 * @var array
32 private $persistKeys = array();
34 /**
35 * Key filter for {@link set()}
36 * @var array|null
38 private $setFilter;
40 /**
41 * Instance id (key in $_SESSION array, separate for each server - ConfigFile{server id})
42 * @var string
44 private $id;
46 /**
47 * Result for {@link _flattenArray()}
48 * @var array
50 private $_flattenArrayResult;
52 /**
53 * ConfigFile instance
54 * @var ConfigFile
56 private static $_instance;
58 /**
59 * Private constructor, use {@link getInstance()}
61 private function __construct()
63 // load default config values
64 $cfg = &$this->cfg;
65 require './libraries/config.default.php';
67 // load additionsl config information
68 $cfg_db = &$this->cfgDb;
69 require './libraries/config.values.php';
71 // apply default values overrides
72 if (count($cfg_db['_overrides'])) {
73 foreach ($cfg_db['_overrides'] as $path => $value) {
74 PMA_array_write($path, $cfg, $value);
78 $this->id = 'ConfigFile' . $GLOBALS['server'];
79 if (!isset($_SESSION[$this->id])) {
80 $_SESSION[$this->id] = array();
84 /**
85 * Returns class instance
87 * @return ConfigFile
89 public static function getInstance()
91 if (is_null(self::$_instance)) {
92 self::$_instance = new ConfigFile();
94 return self::$_instance;
97 /**
98 * Sets names of config options which will be placed in config file even if they are set
99 * to their default values (use only full paths)
101 * @param array $keys
103 public function setPersistKeys($keys)
105 // checking key presence is much faster than searching so move values to keys
106 $this->persistKeys = array_flip($keys);
110 * By default ConfigFile allows setting of all configuration keys, use this method
111 * to set up a filter on {@link set()} method
113 * @param array|null $keys array of allowed keys or null to remove filter
115 public function setAllowedKeys($keys)
117 if ($keys === null) {
118 $this->setFilter = null;
119 return;
121 // checking key presence is much faster than searching so move values to keys
122 $this->setFilter = array_flip($keys);
126 * Resets configuration data
128 public function resetConfigData()
130 $_SESSION[$this->id] = array();
134 * Sets configuration data (overrides old data)
136 * @param array $cfg
138 public function setConfigData(array $cfg)
140 $_SESSION[$this->id] = $cfg;
144 * Sets config value
146 * @param string $path
147 * @param mixed $value
148 * @param string $canonical_path
150 public function set($path, $value, $canonical_path = null)
152 if ($canonical_path === null) {
153 $canonical_path = $this->getCanonicalPath($path);
155 // apply key whitelist
156 if ($this->setFilter !== null && !isset($this->setFilter[$canonical_path])) {
157 return;
159 // remove if the path isn't protected and it's empty or has a default value
160 $default_value = $this->getDefault($canonical_path);
161 if (!isset($this->persistKeys[$canonical_path])
162 && (($value == $default_value) || (empty($value) && empty($default_value)))) {
163 PMA_array_remove($path, $_SESSION[$this->id]);
164 } else {
165 PMA_array_write($path, $_SESSION[$this->id], $value);
170 * Flattens multidimensional array, changes indices to paths (eg. 'key/subkey').
171 * Used as array_walk() callback.
173 * @param mixed $value
174 * @param mixed $key
175 * @param mixed $prefix
177 private function _flattenArray($value, $key, $prefix)
179 // no recursion for numeric arrays
180 if (is_array($value) && !isset($value[0])) {
181 $prefix .= $key . '/';
182 array_walk($value, array($this, '_flattenArray'), $prefix);
183 } else {
184 $this->_flattenArrayResult[$prefix . $key] = $value;
189 * Updates config with values read from PMA_Config class
190 * (config will contain differences to defaults from config.defaults.php).
192 * @param PMA_Config $PMA_Config
194 public function updateWithGlobalConfig(PMA_Config $PMA_Config)
196 // load config array and flatten it
197 $this->_flattenArrayResult = array();
198 array_walk($PMA_Config->settings, array($this, '_flattenArray'), '');
199 $flat_cfg = $this->_flattenArrayResult;
200 $this->_flattenArrayResult = null;
202 // save values
203 foreach ($flat_cfg as $path => $value) {
204 $this->set($path, $value, $path);
209 * Returns config value or $default if it's not set
211 * @param string $path
212 * @param mixed $default
213 * @return mixed
215 public function get($path, $default = null)
217 return PMA_array_read($path, $_SESSION[$this->id], $default);
221 * Returns default config value or $default it it's not set ie. it doesn't
222 * exist in config.default.php ($cfg) and config.values.php
223 * ($_cfg_db['_overrides'])
225 * @param string $canonical_path
226 * @param mixed $default
227 * @return mixed
229 public function getDefault($canonical_path, $default = null)
231 return PMA_array_read($canonical_path, $this->cfg, $default);
235 * Returns config value, if it's not set uses the default one; returns
236 * $default if the path isn't set and doesn't contain a default value
238 * @param string $path
239 * @param mixed $default
240 * @return mixed
242 public function getValue($path, $default = null)
244 $v = PMA_array_read($path, $_SESSION[$this->id], null);
245 if ($v !== null) {
246 return $v;
248 $path = $this->getCanonicalPath($path);
249 return $this->getDefault($path, $default);
253 * Returns canonical path
255 * @param string $path
256 * @return string
258 public function getCanonicalPath($path) {
259 return preg_replace('#^Servers/([\d]+)/#', 'Servers/1/', $path);
263 * Returns config database entry for $path ($cfg_db in config_info.php)
265 * @param string $path
266 * @param mixed $default
267 * @return mixed
269 public function getDbEntry($path, $default = null)
271 return PMA_array_read($path, $this->cfgDb, $default);
275 * Returns server count
277 * @return int
279 public function getServerCount()
281 return isset($_SESSION[$this->id]['Servers'])
282 ? count($_SESSION[$this->id]['Servers'])
283 : 0;
287 * Returns server list
289 * @return array|null
291 public function getServers()
293 return isset($_SESSION[$this->id]['Servers'])
294 ? $_SESSION[$this->id]['Servers']
295 : null;
299 * Returns DSN of given server
301 * @param integer $server
302 * @return string
304 function getServerDSN($server)
306 if (!isset($_SESSION[$this->id]['Servers'][$server])) {
307 return '';
310 $path = 'Servers/' . $server;
311 $dsn = $this->getValue("$path/extension") . '://';
312 if ($this->getValue("$path/auth_type") == 'config') {
313 $dsn .= $this->getValue("$path/user");
314 if (!$this->getValue("$path/nopassword")) {
315 $dsn .= ':***';
317 $dsn .= '@';
319 if ($this->getValue("$path/connect_type") == 'tcp') {
320 $dsn .= $this->getValue("$path/host");
321 $port = $this->getValue("$path/port");
322 if ($port) {
323 $dsn .= ':' . $port;
325 } else {
326 $dsn .= $this->getValue("$path/socket");
328 return $dsn;
332 * Returns server name
334 * @param int $id
335 * @return string
337 public function getServerName($id)
339 if (!isset($_SESSION[$this->id]['Servers'][$id])) {
340 return '';
342 $verbose = $this->get("Servers/$id/verbose");
343 if (!empty($verbose)) {
344 return $verbose;
346 $host = $this->get("Servers/$id/host");
347 return empty($host) ? 'localhost' : $host;
351 * Removes server
353 * @param int $server
355 public function removeServer($server)
357 if (!isset($_SESSION[$this->id]['Servers'][$server])) {
358 return;
360 $last_server = $this->getServerCount();
362 for ($i = $server; $i < $last_server; $i++) {
363 $_SESSION[$this->id]['Servers'][$i] = $_SESSION[$this->id]['Servers'][$i+1];
365 unset($_SESSION[$this->id]['Servers'][$last_server]);
367 if (isset($_SESSION[$this->id]['ServerDefault'])
368 && $_SESSION[$this->id]['ServerDefault'] >= 0) {
369 unset($_SESSION[$this->id]['ServerDefault']);
374 * Returns config file path, relative to phpMyAdmin's root path
376 * @return unknown
378 public function getFilePath()
380 // Load paths
381 if (!defined('SETUP_CONFIG_FILE')) {
382 require_once './libraries/vendor_config.php';
385 return SETUP_CONFIG_FILE;
389 * Returns configuration array (flat format)
391 * @return array
393 public function getConfigArray()
395 $this->_flattenArrayResult = array();
396 array_walk($_SESSION[$this->id], array($this, '_flattenArray'), '');
397 $c = $this->_flattenArrayResult;
398 $this->_flattenArrayResult = null;
400 $persistKeys = array_diff(array_keys($this->persistKeys), array_keys($c));
401 foreach ($persistKeys as $k) {
402 $c[$k] = $this->getDefault($k);
404 return $c;
408 * Creates config file
410 * @return string
412 public function getConfigFile()
414 $crlf = (isset($_SESSION['eol']) && $_SESSION['eol'] == 'win') ? "\r\n" : "\n";
415 $c = $_SESSION[$this->id];
417 // header
418 $ret = '<?php' . $crlf
419 . '/*' . $crlf
420 . ' * Generated configuration file' . $crlf
421 . ' * Generated by: phpMyAdmin '
422 . $GLOBALS['PMA_Config']->get('PMA_VERSION')
423 . ' setup script by Piotr Przybylski <piotrprz@gmail.com>' . $crlf
424 . ' * Date: ' . date(DATE_RFC1123) . $crlf
425 . ' */' . $crlf . $crlf;
427 // servers
428 if ($this->getServerCount() > 0) {
429 $ret .= "/* Servers configuration */$crlf\$i = 0;" . $crlf . $crlf;
430 foreach ($c['Servers'] as $id => $server) {
431 $ret .= '/* Server: ' . strtr($this->getServerName($id), '*/', '-') . " [$id] */" . $crlf
432 . '$i++;' . $crlf;
433 foreach ($server as $k => $v) {
434 $k = preg_replace('/[^A-Za-z0-9_]/', '_', $k);
435 $ret .= "\$cfg['Servers'][\$i]['$k'] = "
436 . var_export($v, true) . ';' . $crlf;
438 $ret .= $crlf;
440 $ret .= '/* End of servers configuration */' . $crlf . $crlf;
442 unset($c['Servers']);
444 // other settings
445 $persistKeys = $this->persistKeys;
446 foreach ($c as $k => $v) {
447 $k = preg_replace('/[^A-Za-z0-9_]/', '_', $k);
448 $ret .= $this->_getVarExport($k, $v, $crlf);
449 if (isset($persistKeys[$k])) {
450 unset($persistKeys[$k]);
453 // keep 1d array keys which are present in $persist_keys (config.values.php)
454 foreach (array_keys($persistKeys) as $k) {
455 if (strpos($k, '/') === false) {
456 $k = preg_replace('/[^A-Za-z0-9_]/', '_', $k);
457 $ret .= $this->_getVarExport($k, $this->getDefault($k), $crlf);
460 $ret .= '?>';
462 return $ret;
466 * Returns exported configuration variable
468 * @param string $var_name
469 * @param mixed $var_value
470 * @param string $crlf
471 * @return string
473 private function _getVarExport($var_name, $var_value, $crlf)
475 if (!is_array($var_value) || empty($var_value)) {
476 return "\$cfg['$var_name'] = " . var_export($var_value, true) . ';' . $crlf;
478 $numeric_keys = true;
479 foreach (array_keys($var_value) as $k) {
480 if (!is_numeric($k)) {
481 $numeric_keys = false;
482 break;
485 if ($numeric_keys) {
486 for ($i = 0; $i < count($var_value); $i++) {
487 if (!isset($var_value[$i])) {
488 $numeric_keys = false;
489 break;
493 $ret = '';
494 if ($numeric_keys) {
495 $retv = array();
496 foreach ($var_value as $v) {
497 $retv[] = var_export($v, true);
499 if (count($retv) <= 4) {
500 // up to 4 values - one line
501 $ret = "\$cfg['$var_name'] = array(" . implode(', ', $retv) . ');' . $crlf;
502 } else {
503 // more than 4 values - value per line
504 $ret = "\$cfg['$var_name'] = array(";
505 $imax = count($retv)-1;
506 for ($i = 0; $i <= $imax; $i++) {
507 $ret .= ($i < $imax ? ($i > 0 ? ',' : '') : '') . $crlf . ' ' . $retv[$i];
509 $ret .= ');' . $crlf;
511 } else {
512 // string keys: $cfg[key][subkey] = value
513 foreach ($var_value as $k => $v) {
514 $k = preg_replace('/[^A-Za-z0-9_]/', '_', $k);
515 $ret = "\$cfg['$var_name']['$k'] = " . var_export($v, true) . ';' . $crlf;
518 return $ret;