220 lines
6.0 KiB
PHP
220 lines
6.0 KiB
PHP
|
<?php
|
||
|
|
||
|
namespace dokuwiki\plugin\config\core;
|
||
|
|
||
|
use dokuwiki\plugin\config\core\Setting\Setting;
|
||
|
use dokuwiki\plugin\config\core\Setting\SettingNoClass;
|
||
|
use dokuwiki\plugin\config\core\Setting\SettingNoDefault;
|
||
|
use dokuwiki\plugin\config\core\Setting\SettingNoKnownClass;
|
||
|
use dokuwiki\plugin\config\core\Setting\SettingUndefined;
|
||
|
|
||
|
/**
|
||
|
* Holds all the current settings and proxies the Loader and Writer
|
||
|
*
|
||
|
* @author Chris Smith <chris@jalakai.co.uk>
|
||
|
* @author Ben Coburn <btcoburn@silicodon.net>
|
||
|
* @author Andreas Gohr <andi@splitbrain.org>
|
||
|
*/
|
||
|
class Configuration {
|
||
|
|
||
|
const KEYMARKER = '____';
|
||
|
|
||
|
/** @var Setting[] metadata as array of Settings objects */
|
||
|
protected $settings = array();
|
||
|
/** @var Setting[] undefined and problematic settings */
|
||
|
protected $undefined = array();
|
||
|
|
||
|
/** @var array all metadata */
|
||
|
protected $metadata;
|
||
|
/** @var array all default settings */
|
||
|
protected $default;
|
||
|
/** @var array all local settings */
|
||
|
protected $local;
|
||
|
/** @var array all protected settings */
|
||
|
protected $protected;
|
||
|
|
||
|
/** @var bool have the settings been changed since loading from disk? */
|
||
|
protected $changed = false;
|
||
|
|
||
|
/** @var Loader */
|
||
|
protected $loader;
|
||
|
/** @var Writer */
|
||
|
protected $writer;
|
||
|
|
||
|
/**
|
||
|
* ConfigSettings constructor.
|
||
|
*/
|
||
|
public function __construct() {
|
||
|
$this->loader = new Loader(new ConfigParser());
|
||
|
$this->writer = new Writer();
|
||
|
|
||
|
$this->metadata = $this->loader->loadMeta();
|
||
|
$this->default = $this->loader->loadDefaults();
|
||
|
$this->local = $this->loader->loadLocal();
|
||
|
$this->protected = $this->loader->loadProtected();
|
||
|
|
||
|
$this->initSettings();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get all settings
|
||
|
*
|
||
|
* @return Setting[]
|
||
|
*/
|
||
|
public function getSettings() {
|
||
|
return $this->settings;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get all unknown or problematic settings
|
||
|
*
|
||
|
* @return Setting[]
|
||
|
*/
|
||
|
public function getUndefined() {
|
||
|
return $this->undefined;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Have the settings been changed since loading from disk?
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function hasChanged() {
|
||
|
return $this->changed;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check if the config can be written
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function isLocked() {
|
||
|
return $this->writer->isLocked();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Update the settings using the data provided
|
||
|
*
|
||
|
* @param array $input as posted
|
||
|
* @return bool true if all updates went through, false on errors
|
||
|
*/
|
||
|
public function updateSettings($input) {
|
||
|
$ok = true;
|
||
|
|
||
|
foreach($this->settings as $key => $obj) {
|
||
|
$value = isset($input[$key]) ? $input[$key] : null;
|
||
|
if($obj->update($value)) {
|
||
|
$this->changed = true;
|
||
|
}
|
||
|
if($obj->hasError()) $ok = false;
|
||
|
}
|
||
|
|
||
|
return $ok;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Save the settings
|
||
|
*
|
||
|
* This save the current state as defined in this object, including the
|
||
|
* undefined settings
|
||
|
*
|
||
|
* @throws \Exception
|
||
|
*/
|
||
|
public function save() {
|
||
|
// only save the undefined settings that have not been handled in settings
|
||
|
$undefined = array_diff_key($this->undefined, $this->settings);
|
||
|
$this->writer->save(array_merge($this->settings, $undefined));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Touch the settings
|
||
|
*
|
||
|
* @throws \Exception
|
||
|
*/
|
||
|
public function touch() {
|
||
|
$this->writer->touch();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Load the extension language strings
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
public function getLangs() {
|
||
|
return $this->loader->loadLangs();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Initalizes the $settings and $undefined properties
|
||
|
*/
|
||
|
protected function initSettings() {
|
||
|
$keys = array_merge(
|
||
|
array_keys($this->metadata),
|
||
|
array_keys($this->default),
|
||
|
array_keys($this->local),
|
||
|
array_keys($this->protected)
|
||
|
);
|
||
|
$keys = array_unique($keys);
|
||
|
|
||
|
foreach($keys as $key) {
|
||
|
$obj = $this->instantiateClass($key);
|
||
|
|
||
|
if($obj->shouldHaveDefault() && !isset($this->default[$key])) {
|
||
|
$this->undefined[$key] = new SettingNoDefault($key);
|
||
|
}
|
||
|
|
||
|
$d = isset($this->default[$key]) ? $this->default[$key] : null;
|
||
|
$l = isset($this->local[$key]) ? $this->local[$key] : null;
|
||
|
$p = isset($this->protected[$key]) ? $this->protected[$key] : null;
|
||
|
|
||
|
$obj->initialize($d, $l, $p);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Instantiates the proper class for the given config key
|
||
|
*
|
||
|
* The class is added to the $settings or $undefined arrays and returned
|
||
|
*
|
||
|
* @param string $key
|
||
|
* @return Setting
|
||
|
*/
|
||
|
protected function instantiateClass($key) {
|
||
|
if(isset($this->metadata[$key])) {
|
||
|
$param = $this->metadata[$key];
|
||
|
$class = $this->determineClassName(array_shift($param), $key); // first param is class
|
||
|
$obj = new $class($key, $param);
|
||
|
$this->settings[$key] = $obj;
|
||
|
} else {
|
||
|
$obj = new SettingUndefined($key);
|
||
|
$this->undefined[$key] = $obj;
|
||
|
}
|
||
|
return $obj;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return the class to load
|
||
|
*
|
||
|
* @param string $class the class name as given in the meta file
|
||
|
* @param string $key the settings key
|
||
|
* @return string
|
||
|
*/
|
||
|
protected function determineClassName($class, $key) {
|
||
|
// try namespaced class first
|
||
|
if(is_string($class)) {
|
||
|
$modern = str_replace('_', '', ucwords($class, '_'));
|
||
|
$modern = '\\dokuwiki\\plugin\\config\\core\\Setting\\Setting' . $modern;
|
||
|
if($modern && class_exists($modern)) return $modern;
|
||
|
// try class as given
|
||
|
if(class_exists($class)) return $class;
|
||
|
// class wasn't found add to errors
|
||
|
$this->undefined[$key] = new SettingNoKnownClass($key);
|
||
|
} else {
|
||
|
// no class given, add to errors
|
||
|
$this->undefined[$key] = new SettingNoClass($key);
|
||
|
}
|
||
|
return '\\dokuwiki\\plugin\\config\\core\\Setting\\Setting';
|
||
|
}
|
||
|
|
||
|
}
|