1c6639e6aSAndreas Gohr<?php 2c6639e6aSAndreas Gohr 3c6639e6aSAndreas Gohrnamespace dokuwiki\plugin\config\core; 4c6639e6aSAndreas Gohr 5c6639e6aSAndreas Gohr/** 65675a07cSAndreas Gohr * Holds all the current settings and proxies the Loader and Writer 7077c27b2SAndreas Gohr * 8077c27b2SAndreas Gohr * @author Chris Smith <chris@jalakai.co.uk> 9077c27b2SAndreas Gohr * @author Ben Coburn <btcoburn@silicodon.net> 10077c27b2SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 11c6639e6aSAndreas Gohr */ 12c6639e6aSAndreas Gohrclass Configuration { 13c6639e6aSAndreas Gohr 14c6639e6aSAndreas Gohr const KEYMARKER = '____'; 15c6639e6aSAndreas Gohr 16077c27b2SAndreas Gohr /** @var Setting[] metadata as array of Settings objects */ 17077c27b2SAndreas Gohr protected $settings = array(); 18077c27b2SAndreas Gohr /** @var array problematic keys */ 19077c27b2SAndreas Gohr protected $errors; 20077c27b2SAndreas Gohr /** @var Setting[] undefined settings */ 21077c27b2SAndreas Gohr protected $undefined = array(); 228ea5685fSAndreas Gohr 23077c27b2SAndreas Gohr /** @var array all metadata */ 24077c27b2SAndreas Gohr protected $metadata; 25077c27b2SAndreas Gohr /** @var array all default settings */ 26077c27b2SAndreas Gohr protected $default; 27077c27b2SAndreas Gohr /** @var array all local settings */ 28077c27b2SAndreas Gohr protected $local; 29077c27b2SAndreas Gohr /** @var array all protected settings */ 30077c27b2SAndreas Gohr protected $protected; 31077c27b2SAndreas Gohr 32077c27b2SAndreas Gohr /** @var bool have the settings been changed since loading from disk? */ 33077c27b2SAndreas Gohr protected $changed = false; 34077c27b2SAndreas Gohr 355675a07cSAndreas Gohr /** @var Loader */ 365675a07cSAndreas Gohr protected $loader; 37077c27b2SAndreas Gohr /** @var Writer */ 38077c27b2SAndreas Gohr protected $writer; 398ea5685fSAndreas Gohr 40c6639e6aSAndreas Gohr /** 41077c27b2SAndreas Gohr * ConfigSettings constructor. 42c6639e6aSAndreas Gohr */ 435a38a129SAndreas Gohr public function __construct() { 445675a07cSAndreas Gohr $this->loader = new Loader(new ConfigParser()); 45077c27b2SAndreas Gohr $this->writer = new Writer(); 46077c27b2SAndreas Gohr 475675a07cSAndreas Gohr $this->metadata = $this->loader->loadMeta(); 485675a07cSAndreas Gohr $this->default = $this->loader->loadDefaults(); 495675a07cSAndreas Gohr $this->local = $this->loader->loadLocal(); 505675a07cSAndreas Gohr $this->protected = $this->loader->loadProtected(); 51077c27b2SAndreas Gohr 52077c27b2SAndreas Gohr $this->initSettings(); 53c6639e6aSAndreas Gohr } 54c6639e6aSAndreas Gohr 55c6639e6aSAndreas Gohr /** 56077c27b2SAndreas Gohr * Get all settings 57c6639e6aSAndreas Gohr * 58077c27b2SAndreas Gohr * @return Setting[] 59c6639e6aSAndreas Gohr */ 60077c27b2SAndreas Gohr public function getSettings() { 61077c27b2SAndreas Gohr return $this->settings; 62c6639e6aSAndreas Gohr } 63c6639e6aSAndreas Gohr 64077c27b2SAndreas Gohr /** 65077c27b2SAndreas Gohr * Get all unknown settings 66077c27b2SAndreas Gohr * 67077c27b2SAndreas Gohr * @return Setting[] 68077c27b2SAndreas Gohr */ 69077c27b2SAndreas Gohr public function getUndefined() { 70077c27b2SAndreas Gohr return $this->undefined; 71c6639e6aSAndreas Gohr } 72c6639e6aSAndreas Gohr 73077c27b2SAndreas Gohr /** 74077c27b2SAndreas Gohr * Get the settings that had some kind of setup problem 75077c27b2SAndreas Gohr * 76077c27b2SAndreas Gohr * @return array associative error, key is the setting, value the error 77077c27b2SAndreas Gohr */ 78077c27b2SAndreas Gohr public function getErrors() { 79077c27b2SAndreas Gohr return $this->errors; 80077c27b2SAndreas Gohr } 81077c27b2SAndreas Gohr 82077c27b2SAndreas Gohr /** 83077c27b2SAndreas Gohr * Have the settings been changed since loading from disk? 84077c27b2SAndreas Gohr * 85077c27b2SAndreas Gohr * @return bool 86077c27b2SAndreas Gohr */ 87077c27b2SAndreas Gohr public function hasChanged() { 88077c27b2SAndreas Gohr return $this->changed; 89077c27b2SAndreas Gohr } 90077c27b2SAndreas Gohr 91077c27b2SAndreas Gohr /** 92077c27b2SAndreas Gohr * Check if the config can be written 93077c27b2SAndreas Gohr * 94077c27b2SAndreas Gohr * @return bool 95077c27b2SAndreas Gohr */ 96077c27b2SAndreas Gohr public function isLocked() { 97077c27b2SAndreas Gohr return $this->writer->isLocked(); 98077c27b2SAndreas Gohr } 99077c27b2SAndreas Gohr 100077c27b2SAndreas Gohr /** 101077c27b2SAndreas Gohr * Update the settings using the data provided 102077c27b2SAndreas Gohr * 103077c27b2SAndreas Gohr * @param array $input as posted 104077c27b2SAndreas Gohr * @return bool true if all updates went through, false on errors 105077c27b2SAndreas Gohr */ 106077c27b2SAndreas Gohr public function updateSettings($input) { 107077c27b2SAndreas Gohr $ok = true; 108077c27b2SAndreas Gohr 109077c27b2SAndreas Gohr foreach($this->settings as $key => $obj) { 110077c27b2SAndreas Gohr $value = isset($input[$key]) ? $input[$key] : null; 111077c27b2SAndreas Gohr if($obj->update($value)) { 112077c27b2SAndreas Gohr $this->changed = true; 113077c27b2SAndreas Gohr } 114*5c17d2d3SAndreas Gohr if($obj->hasError()) $ok = false; 115077c27b2SAndreas Gohr } 116077c27b2SAndreas Gohr 117077c27b2SAndreas Gohr return $ok; 118077c27b2SAndreas Gohr } 119077c27b2SAndreas Gohr 120077c27b2SAndreas Gohr /** 121077c27b2SAndreas Gohr * Save the settings 122077c27b2SAndreas Gohr * 123077c27b2SAndreas Gohr * @throws \Exception 124077c27b2SAndreas Gohr */ 125077c27b2SAndreas Gohr public function save() { 126077c27b2SAndreas Gohr $this->writer->save($this->settings); 127077c27b2SAndreas Gohr } 128077c27b2SAndreas Gohr 129077c27b2SAndreas Gohr /** 130077c27b2SAndreas Gohr * Touch the settings 131077c27b2SAndreas Gohr * 132077c27b2SAndreas Gohr * @throws \Exception 133077c27b2SAndreas Gohr */ 134077c27b2SAndreas Gohr public function touch() { 135077c27b2SAndreas Gohr $this->writer->touch(); 136077c27b2SAndreas Gohr } 137077c27b2SAndreas Gohr 138077c27b2SAndreas Gohr /** 1395675a07cSAndreas Gohr * Load the extension language strings 1405675a07cSAndreas Gohr * 1415675a07cSAndreas Gohr * @return array 1425675a07cSAndreas Gohr */ 1435675a07cSAndreas Gohr public function getLangs() { 1445675a07cSAndreas Gohr return $this->loader->loadLangs(); 1455675a07cSAndreas Gohr } 1465675a07cSAndreas Gohr 1475675a07cSAndreas Gohr /** 148077c27b2SAndreas Gohr * Initalizes the $settings and $undefined properties 149077c27b2SAndreas Gohr */ 150077c27b2SAndreas Gohr protected function initSettings() { 151077c27b2SAndreas Gohr $keys = array_merge( 152077c27b2SAndreas Gohr array_keys($this->metadata), 153077c27b2SAndreas Gohr array_keys($this->default), 154077c27b2SAndreas Gohr array_keys($this->local), 155077c27b2SAndreas Gohr array_keys($this->protected) 156077c27b2SAndreas Gohr ); 157077c27b2SAndreas Gohr $keys = array_unique($keys); 158077c27b2SAndreas Gohr 159077c27b2SAndreas Gohr foreach($keys as $key) { 160077c27b2SAndreas Gohr $obj = $this->instantiateClass($key); 161077c27b2SAndreas Gohr 162077c27b2SAndreas Gohr if($obj->shouldHaveDefault() && !isset($this->default[$key])) { 163077c27b2SAndreas Gohr $this->errors[$key] = 'no default'; 164077c27b2SAndreas Gohr } 165077c27b2SAndreas Gohr 166077c27b2SAndreas Gohr $d = isset($this->default[$key]) ? $this->default[$key] : null; 167077c27b2SAndreas Gohr $l = isset($this->local[$key]) ? $this->local[$key] : null; 168077c27b2SAndreas Gohr $p = isset($this->protected[$key]) ? $this->protected[$key] : null; 169077c27b2SAndreas Gohr 170077c27b2SAndreas Gohr $obj->initialize($d, $l, $p); 171077c27b2SAndreas Gohr } 172077c27b2SAndreas Gohr } 173077c27b2SAndreas Gohr 174077c27b2SAndreas Gohr /** 175077c27b2SAndreas Gohr * Instantiates the proper class for the given config key 176077c27b2SAndreas Gohr * 177077c27b2SAndreas Gohr * The class is added to the $settings or $undefined arrays and returned 178077c27b2SAndreas Gohr * 179077c27b2SAndreas Gohr * @param string $key 180077c27b2SAndreas Gohr * @return Setting 181077c27b2SAndreas Gohr */ 182077c27b2SAndreas Gohr protected function instantiateClass($key) { 183077c27b2SAndreas Gohr if(isset($this->metadata[$key])) { 184077c27b2SAndreas Gohr $param = $this->metadata[$key]; 185077c27b2SAndreas Gohr $class = $this->determineClassName(array_shift($param), $key); // first param is class 186077c27b2SAndreas Gohr $obj = new $class($key, $param); 187077c27b2SAndreas Gohr $this->settings[] = $obj; 188077c27b2SAndreas Gohr } else { 189077c27b2SAndreas Gohr $obj = new SettingUndefined($key); 190077c27b2SAndreas Gohr $this->undefined[] = $obj; 191077c27b2SAndreas Gohr } 192077c27b2SAndreas Gohr return $obj; 193077c27b2SAndreas Gohr } 194077c27b2SAndreas Gohr 195077c27b2SAndreas Gohr /** 196077c27b2SAndreas Gohr * Return the class to load 197077c27b2SAndreas Gohr * 198077c27b2SAndreas Gohr * @param string $class the class name as given in the meta file 199077c27b2SAndreas Gohr * @param string $key the settings key 200077c27b2SAndreas Gohr * @return string 201077c27b2SAndreas Gohr */ 202077c27b2SAndreas Gohr protected function determineClassName($class, $key) { 203077c27b2SAndreas Gohr // try namespaced class first 204077c27b2SAndreas Gohr if($class) { 205077c27b2SAndreas Gohr $modern = str_replace('_', '', ucwords($class, '_')); 206077c27b2SAndreas Gohr $modern = '\\dokuwiki\\plugin\\config\\core\\' . $modern; 207077c27b2SAndreas Gohr if($modern && class_exists($modern)) return $modern; 208077c27b2SAndreas Gohr // class wasn't found add to errors 209077c27b2SAndreas Gohr $this->errors[$key] = 'unknown class'; 210077c27b2SAndreas Gohr } else { 211077c27b2SAndreas Gohr // no class given, add to errors 212077c27b2SAndreas Gohr $this->errors[$key] = 'no class'; 213077c27b2SAndreas Gohr } 214077c27b2SAndreas Gohr return '\\dokuwiki\\plugin\\config\\core\\Setting'; 215077c27b2SAndreas Gohr } 216077c27b2SAndreas Gohr 217077c27b2SAndreas Gohr} 218