1<?php 2 3namespace dokuwiki\plugin\config\core; 4 5/** 6 * Holds all the current settings 7 * 8 * @author Chris Smith <chris@jalakai.co.uk> 9 * @author Ben Coburn <btcoburn@silicodon.net> 10 * @author Andreas Gohr <andi@splitbrain.org> 11 */ 12class Configuration { 13 14 const KEYMARKER = '____'; 15 16 /** @var Setting[] metadata as array of Settings objects */ 17 protected $settings = array(); 18 /** @var array problematic keys */ 19 protected $errors; 20 /** @var Setting[] undefined settings */ 21 protected $undefined = array(); 22 23 /** @var array all metadata */ 24 protected $metadata; 25 /** @var array all default settings */ 26 protected $default; 27 /** @var array all local settings */ 28 protected $local; 29 /** @var array all protected settings */ 30 protected $protected; 31 32 /** @var bool have the settings been changed since loading from disk? */ 33 protected $changed = false; 34 35 /** @var Writer */ 36 protected $writer; 37 38 /** 39 * ConfigSettings constructor. 40 */ 41 public function __construct() { 42 $loader = new Loader(new ConfigParser()); 43 $this->writer = new Writer(); 44 45 $this->metadata = $loader->loadMeta(); 46 $this->default = $loader->loadDefaults(); 47 $this->local = $loader->loadLocal(); 48 $this->protected = $loader->loadProtected(); 49 50 $this->initSettings(); 51 } 52 53 /** 54 * Get all settings 55 * 56 * @return Setting[] 57 */ 58 public function getSettings() { 59 return $this->settings; 60 } 61 62 /** 63 * Get all unknown settings 64 * 65 * @return Setting[] 66 */ 67 public function getUndefined() { 68 return $this->undefined; 69 } 70 71 /** 72 * Get the settings that had some kind of setup problem 73 * 74 * @return array associative error, key is the setting, value the error 75 */ 76 public function getErrors() { 77 return $this->errors; 78 } 79 80 /** 81 * Have the settings been changed since loading from disk? 82 * 83 * @return bool 84 */ 85 public function hasChanged() { 86 return $this->changed; 87 } 88 89 /** 90 * Check if the config can be written 91 * 92 * @return bool 93 */ 94 public function isLocked() { 95 return $this->writer->isLocked(); 96 } 97 98 /** 99 * Update the settings using the data provided 100 * 101 * @param array $input as posted 102 * @return bool true if all updates went through, false on errors 103 */ 104 public function updateSettings($input) { 105 $ok = true; 106 107 foreach($this->settings as $key => $obj) { 108 $value = isset($input[$key]) ? $input[$key] : null; 109 if($obj->update($value)) { 110 $this->changed = true; 111 } 112 if($obj->error()) $ok = false; 113 } 114 115 return $ok; 116 } 117 118 /** 119 * Save the settings 120 * 121 * @throws \Exception 122 */ 123 public function save() { 124 $this->writer->save($this->settings); 125 } 126 127 /** 128 * Touch the settings 129 * 130 * @throws \Exception 131 */ 132 public function touch() { 133 $this->writer->touch(); 134 } 135 136 /** 137 * Initalizes the $settings and $undefined properties 138 */ 139 protected function initSettings() { 140 $keys = array_merge( 141 array_keys($this->metadata), 142 array_keys($this->default), 143 array_keys($this->local), 144 array_keys($this->protected) 145 ); 146 $keys = array_unique($keys); 147 148 foreach($keys as $key) { 149 $obj = $this->instantiateClass($key); 150 151 if($obj->shouldHaveDefault() && !isset($this->default[$key])) { 152 $this->errors[$key] = 'no default'; 153 } 154 155 $d = isset($this->default[$key]) ? $this->default[$key] : null; 156 $l = isset($this->local[$key]) ? $this->local[$key] : null; 157 $p = isset($this->protected[$key]) ? $this->protected[$key] : null; 158 159 $obj->initialize($d, $l, $p); 160 } 161 } 162 163 /** 164 * Instantiates the proper class for the given config key 165 * 166 * The class is added to the $settings or $undefined arrays and returned 167 * 168 * @param string $key 169 * @return Setting 170 */ 171 protected function instantiateClass($key) { 172 if(isset($this->metadata[$key])) { 173 $param = $this->metadata[$key]; 174 $class = $this->determineClassName(array_shift($param), $key); // first param is class 175 $obj = new $class($key, $param); 176 $this->settings[] = $obj; 177 } else { 178 $obj = new SettingUndefined($key); 179 $this->undefined[] = $obj; 180 } 181 return $obj; 182 } 183 184 /** 185 * Return the class to load 186 * 187 * @param string $class the class name as given in the meta file 188 * @param string $key the settings key 189 * @return string 190 */ 191 protected function determineClassName($class, $key) { 192 // try namespaced class first 193 if($class) { 194 $modern = str_replace('_', '', ucwords($class, '_')); 195 $modern = '\\dokuwiki\\plugin\\config\\core\\' . $modern; 196 if($modern && class_exists($modern)) return $modern; 197 // class wasn't found add to errors 198 $this->errors[$key] = 'unknown class'; 199 } else { 200 // no class given, add to errors 201 $this->errors[$key] = 'no class'; 202 } 203 return '\\dokuwiki\\plugin\\config\\core\\Setting'; 204 } 205 206} 207