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