[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/lib/plugins/config/core/ -> Configuration.php (source)

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