1c6639e6aSAndreas Gohr<?php 2c6639e6aSAndreas Gohr 3c6639e6aSAndreas Gohrnamespace dokuwiki\plugin\config\core; 4*0a5b05ebSAndreas Gohruse dokuwiki\plugin\config\core\Setting\Setting; 5*0a5b05ebSAndreas Gohruse dokuwiki\plugin\config\core\Setting\SettingUndefined; 6c6639e6aSAndreas Gohr 7c6639e6aSAndreas Gohr/** 85675a07cSAndreas Gohr * Holds all the current settings and proxies the Loader and Writer 9077c27b2SAndreas Gohr * 10077c27b2SAndreas Gohr * @author Chris Smith <chris@jalakai.co.uk> 11077c27b2SAndreas Gohr * @author Ben Coburn <btcoburn@silicodon.net> 12077c27b2SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 13c6639e6aSAndreas Gohr */ 14c6639e6aSAndreas Gohrclass Configuration { 15c6639e6aSAndreas Gohr 16c6639e6aSAndreas Gohr const KEYMARKER = '____'; 17c6639e6aSAndreas Gohr 18077c27b2SAndreas Gohr /** @var Setting[] metadata as array of Settings objects */ 19077c27b2SAndreas Gohr protected $settings = array(); 20077c27b2SAndreas Gohr /** @var array problematic keys */ 21077c27b2SAndreas Gohr protected $errors; 22077c27b2SAndreas Gohr /** @var Setting[] undefined settings */ 23077c27b2SAndreas Gohr protected $undefined = array(); 248ea5685fSAndreas Gohr 25077c27b2SAndreas Gohr /** @var array all metadata */ 26077c27b2SAndreas Gohr protected $metadata; 27077c27b2SAndreas Gohr /** @var array all default settings */ 28077c27b2SAndreas Gohr protected $default; 29077c27b2SAndreas Gohr /** @var array all local settings */ 30077c27b2SAndreas Gohr protected $local; 31077c27b2SAndreas Gohr /** @var array all protected settings */ 32077c27b2SAndreas Gohr protected $protected; 33077c27b2SAndreas Gohr 34077c27b2SAndreas Gohr /** @var bool have the settings been changed since loading from disk? */ 35077c27b2SAndreas Gohr protected $changed = false; 36077c27b2SAndreas Gohr 375675a07cSAndreas Gohr /** @var Loader */ 385675a07cSAndreas Gohr protected $loader; 39077c27b2SAndreas Gohr /** @var Writer */ 40077c27b2SAndreas Gohr protected $writer; 418ea5685fSAndreas Gohr 42c6639e6aSAndreas Gohr /** 43077c27b2SAndreas Gohr * ConfigSettings constructor. 44c6639e6aSAndreas Gohr */ 455a38a129SAndreas Gohr public function __construct() { 465675a07cSAndreas Gohr $this->loader = new Loader(new ConfigParser()); 47077c27b2SAndreas Gohr $this->writer = new Writer(); 48077c27b2SAndreas Gohr 495675a07cSAndreas Gohr $this->metadata = $this->loader->loadMeta(); 505675a07cSAndreas Gohr $this->default = $this->loader->loadDefaults(); 515675a07cSAndreas Gohr $this->local = $this->loader->loadLocal(); 525675a07cSAndreas Gohr $this->protected = $this->loader->loadProtected(); 53077c27b2SAndreas Gohr 54077c27b2SAndreas Gohr $this->initSettings(); 55c6639e6aSAndreas Gohr } 56c6639e6aSAndreas Gohr 57c6639e6aSAndreas Gohr /** 58077c27b2SAndreas Gohr * Get all settings 59c6639e6aSAndreas Gohr * 60077c27b2SAndreas Gohr * @return Setting[] 61c6639e6aSAndreas Gohr */ 62077c27b2SAndreas Gohr public function getSettings() { 63077c27b2SAndreas Gohr return $this->settings; 64c6639e6aSAndreas Gohr } 65c6639e6aSAndreas Gohr 66077c27b2SAndreas Gohr /** 67077c27b2SAndreas Gohr * Get all unknown settings 68077c27b2SAndreas Gohr * 69077c27b2SAndreas Gohr * @return Setting[] 70077c27b2SAndreas Gohr */ 71077c27b2SAndreas Gohr public function getUndefined() { 72077c27b2SAndreas Gohr return $this->undefined; 73c6639e6aSAndreas Gohr } 74c6639e6aSAndreas Gohr 75077c27b2SAndreas Gohr /** 76077c27b2SAndreas Gohr * Get the settings that had some kind of setup problem 77077c27b2SAndreas Gohr * 78077c27b2SAndreas Gohr * @return array associative error, key is the setting, value the error 79077c27b2SAndreas Gohr */ 80077c27b2SAndreas Gohr public function getErrors() { 81077c27b2SAndreas Gohr return $this->errors; 82077c27b2SAndreas Gohr } 83077c27b2SAndreas Gohr 84077c27b2SAndreas Gohr /** 85077c27b2SAndreas Gohr * Have the settings been changed since loading from disk? 86077c27b2SAndreas Gohr * 87077c27b2SAndreas Gohr * @return bool 88077c27b2SAndreas Gohr */ 89077c27b2SAndreas Gohr public function hasChanged() { 90077c27b2SAndreas Gohr return $this->changed; 91077c27b2SAndreas Gohr } 92077c27b2SAndreas Gohr 93077c27b2SAndreas Gohr /** 94077c27b2SAndreas Gohr * Check if the config can be written 95077c27b2SAndreas Gohr * 96077c27b2SAndreas Gohr * @return bool 97077c27b2SAndreas Gohr */ 98077c27b2SAndreas Gohr public function isLocked() { 99077c27b2SAndreas Gohr return $this->writer->isLocked(); 100077c27b2SAndreas Gohr } 101077c27b2SAndreas Gohr 102077c27b2SAndreas Gohr /** 103077c27b2SAndreas Gohr * Update the settings using the data provided 104077c27b2SAndreas Gohr * 105077c27b2SAndreas Gohr * @param array $input as posted 106077c27b2SAndreas Gohr * @return bool true if all updates went through, false on errors 107077c27b2SAndreas Gohr */ 108077c27b2SAndreas Gohr public function updateSettings($input) { 109077c27b2SAndreas Gohr $ok = true; 110077c27b2SAndreas Gohr 111077c27b2SAndreas Gohr foreach($this->settings as $key => $obj) { 112077c27b2SAndreas Gohr $value = isset($input[$key]) ? $input[$key] : null; 113077c27b2SAndreas Gohr if($obj->update($value)) { 114077c27b2SAndreas Gohr $this->changed = true; 115077c27b2SAndreas Gohr } 1165c17d2d3SAndreas Gohr if($obj->hasError()) $ok = false; 117077c27b2SAndreas Gohr } 118077c27b2SAndreas Gohr 119077c27b2SAndreas Gohr return $ok; 120077c27b2SAndreas Gohr } 121077c27b2SAndreas Gohr 122077c27b2SAndreas Gohr /** 123077c27b2SAndreas Gohr * Save the settings 124077c27b2SAndreas Gohr * 125077c27b2SAndreas Gohr * @throws \Exception 126077c27b2SAndreas Gohr */ 127077c27b2SAndreas Gohr public function save() { 128077c27b2SAndreas Gohr $this->writer->save($this->settings); 129077c27b2SAndreas Gohr } 130077c27b2SAndreas Gohr 131077c27b2SAndreas Gohr /** 132077c27b2SAndreas Gohr * Touch the settings 133077c27b2SAndreas Gohr * 134077c27b2SAndreas Gohr * @throws \Exception 135077c27b2SAndreas Gohr */ 136077c27b2SAndreas Gohr public function touch() { 137077c27b2SAndreas Gohr $this->writer->touch(); 138077c27b2SAndreas Gohr } 139077c27b2SAndreas Gohr 140077c27b2SAndreas Gohr /** 1415675a07cSAndreas Gohr * Load the extension language strings 1425675a07cSAndreas Gohr * 1435675a07cSAndreas Gohr * @return array 1445675a07cSAndreas Gohr */ 1455675a07cSAndreas Gohr public function getLangs() { 1465675a07cSAndreas Gohr return $this->loader->loadLangs(); 1475675a07cSAndreas Gohr } 1485675a07cSAndreas Gohr 1495675a07cSAndreas Gohr /** 150077c27b2SAndreas Gohr * Initalizes the $settings and $undefined properties 151077c27b2SAndreas Gohr */ 152077c27b2SAndreas Gohr protected function initSettings() { 153077c27b2SAndreas Gohr $keys = array_merge( 154077c27b2SAndreas Gohr array_keys($this->metadata), 155077c27b2SAndreas Gohr array_keys($this->default), 156077c27b2SAndreas Gohr array_keys($this->local), 157077c27b2SAndreas Gohr array_keys($this->protected) 158077c27b2SAndreas Gohr ); 159077c27b2SAndreas Gohr $keys = array_unique($keys); 160077c27b2SAndreas Gohr 161077c27b2SAndreas Gohr foreach($keys as $key) { 162077c27b2SAndreas Gohr $obj = $this->instantiateClass($key); 163077c27b2SAndreas Gohr 164077c27b2SAndreas Gohr if($obj->shouldHaveDefault() && !isset($this->default[$key])) { 165077c27b2SAndreas Gohr $this->errors[$key] = 'no default'; 166077c27b2SAndreas Gohr } 167077c27b2SAndreas Gohr 168077c27b2SAndreas Gohr $d = isset($this->default[$key]) ? $this->default[$key] : null; 169077c27b2SAndreas Gohr $l = isset($this->local[$key]) ? $this->local[$key] : null; 170077c27b2SAndreas Gohr $p = isset($this->protected[$key]) ? $this->protected[$key] : null; 171077c27b2SAndreas Gohr 172077c27b2SAndreas Gohr $obj->initialize($d, $l, $p); 173077c27b2SAndreas Gohr } 174077c27b2SAndreas Gohr } 175077c27b2SAndreas Gohr 176077c27b2SAndreas Gohr /** 177077c27b2SAndreas Gohr * Instantiates the proper class for the given config key 178077c27b2SAndreas Gohr * 179077c27b2SAndreas Gohr * The class is added to the $settings or $undefined arrays and returned 180077c27b2SAndreas Gohr * 181077c27b2SAndreas Gohr * @param string $key 182077c27b2SAndreas Gohr * @return Setting 183077c27b2SAndreas Gohr */ 184077c27b2SAndreas Gohr protected function instantiateClass($key) { 185077c27b2SAndreas Gohr if(isset($this->metadata[$key])) { 186077c27b2SAndreas Gohr $param = $this->metadata[$key]; 187077c27b2SAndreas Gohr $class = $this->determineClassName(array_shift($param), $key); // first param is class 188077c27b2SAndreas Gohr $obj = new $class($key, $param); 189077c27b2SAndreas Gohr $this->settings[] = $obj; 190077c27b2SAndreas Gohr } else { 191077c27b2SAndreas Gohr $obj = new SettingUndefined($key); 192077c27b2SAndreas Gohr $this->undefined[] = $obj; 193077c27b2SAndreas Gohr } 194077c27b2SAndreas Gohr return $obj; 195077c27b2SAndreas Gohr } 196077c27b2SAndreas Gohr 197077c27b2SAndreas Gohr /** 198077c27b2SAndreas Gohr * Return the class to load 199077c27b2SAndreas Gohr * 200077c27b2SAndreas Gohr * @param string $class the class name as given in the meta file 201077c27b2SAndreas Gohr * @param string $key the settings key 202077c27b2SAndreas Gohr * @return string 203077c27b2SAndreas Gohr */ 204077c27b2SAndreas Gohr protected function determineClassName($class, $key) { 205077c27b2SAndreas Gohr // try namespaced class first 206077c27b2SAndreas Gohr if($class) { 207077c27b2SAndreas Gohr $modern = str_replace('_', '', ucwords($class, '_')); 208*0a5b05ebSAndreas Gohr $modern = '\\dokuwiki\\plugin\\config\\core\\Setting\\Setting' . $modern; 209077c27b2SAndreas Gohr if($modern && class_exists($modern)) return $modern; 210*0a5b05ebSAndreas Gohr // try class as given 211*0a5b05ebSAndreas Gohr if(class_exists($class)) return $class; 212077c27b2SAndreas Gohr // class wasn't found add to errors 213077c27b2SAndreas Gohr $this->errors[$key] = 'unknown class'; 214077c27b2SAndreas Gohr } else { 215077c27b2SAndreas Gohr // no class given, add to errors 216077c27b2SAndreas Gohr $this->errors[$key] = 'no class'; 217077c27b2SAndreas Gohr } 218*0a5b05ebSAndreas Gohr return '\\dokuwiki\\plugin\\config\\core\\Setting\\Setting'; 219077c27b2SAndreas Gohr } 220077c27b2SAndreas Gohr 221077c27b2SAndreas Gohr} 222