Subversion Repositories oidplus

Rev

Rev 360 | Rev 569 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /*
  4.  * OIDplus 2.0
  5.  * Copyright 2019 - 2021 Daniel Marschall, ViaThinkSoft
  6.  *
  7.  * Licensed under the Apache License, Version 2.0 (the "License");
  8.  * you may not use this file except in compliance with the License.
  9.  * You may obtain a copy of the License at
  10.  *
  11.  *     http://www.apache.org/licenses/LICENSE-2.0
  12.  *
  13.  * Unless required by applicable law or agreed to in writing, software
  14.  * distributed under the License is distributed on an "AS IS" BASIS,
  15.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16.  * See the License for the specific language governing permissions and
  17.  * limitations under the License.
  18.  */
  19.  
  20. if (!defined('INSIDE_OIDPLUS')) die();
  21.  
  22. // OIDplusConfig contains settings that are stored in the database.
  23. // Not to be confused with OIDplusBaseConfig which is the basic ("static")
  24. // configuration stored in userdata/baseconfig/config.inc.php,
  25. // e.g. database access credentials.
  26. class OIDplusConfig implements OIDplusConfigInterface {
  27.  
  28.         /*public*/ const PROTECTION_EDITABLE = 0;
  29.         /*public*/ const PROTECTION_READONLY = 1;
  30.         /*public*/ const PROTECTION_HIDDEN   = 2;
  31.  
  32.         protected $configTableReadOnce = false; // this ensures that all $values and $descriptions were read
  33.  
  34.         protected $values = array();
  35.         protected $descriptions = array();
  36.         protected $validateCallbacks = array();
  37.  
  38.         public function prepareConfigKey($name, $description, $init_value, $protection, $validateCallback) {
  39.                 // Check if the protection flag is valid
  40.                 switch ($protection) {
  41.                         case OIDplusConfig::PROTECTION_EDITABLE:
  42.                                 $protected = 0;
  43.                                 $visible   = 1;
  44.                                 break;
  45.                         case OIDplusConfig::PROTECTION_READONLY:
  46.                                 $protected = 1;
  47.                                 $visible   = 1;
  48.                                 break;
  49.                         case OIDplusConfig::PROTECTION_HIDDEN:
  50.                                 $protected = 1;
  51.                                 $visible   = 0;
  52.                                 break;
  53.                         default:
  54.                                 throw new OIDplusException(_L('Invalid protection flag, use OIDplusConfig::PROTECTION_* constants'));
  55.                 }
  56.  
  57.                 // Check length limitations given by the database tables
  58.                 if (strlen($name) > 50) {
  59.                         throw new OIDplusException(_L('Config key name "%1" is too long (max %2).',$name,50));
  60.                 }
  61.                 if (strlen($description) > 255) {
  62.                         throw new OIDplusException(_L('Description for config key "%1" is too long (max %2).',$name,255));
  63.                 }
  64.  
  65.                 // Read all values and descriptions from the database once.
  66.                 $this->buildConfigArray();
  67.  
  68.                 // Figure out if we need to create/update something at database level
  69.                 if (!isset($this->values[$name])) {
  70.                         // Case A: The config setting does not exist in the database. So we create it now.
  71.                         OIDplus::db()->query("insert into ###config (name, description, value, protected, visible) values (?, ?, ?, ?, ?)", array($name, $description, $init_value, $protected, $visible));
  72.                         $this->values[$name] = $init_value;
  73.                         $this->descriptions[$name] = $description;
  74.                 } else {
  75.                         // Case B: The config setting exists ...
  76.                         if ($this->descriptions[$name] != $description) {
  77.                                 // ... but the human readable description is different.
  78.                                 // We want to give the plugin authors the possibility to automatically update the config descriptions for their plugins
  79.                                 // So we just edit the description
  80.                                 OIDplus::db()->query("update ###config set description = ? where name = ?", array($description, $name));
  81.                                 $this->descriptions[$name] = $description;
  82.                         }
  83.                 }
  84.  
  85.                 // Register the validation callback
  86.                 if (!is_null($validateCallback)) {
  87.                         $this->validateCallbacks[$name] = $validateCallback;
  88.                 }
  89.         }
  90.  
  91.         public function clearCache() {
  92.                 $this->configTableReadOnce = false;
  93.                 $this->buildConfigArray();
  94.         }
  95.  
  96.         protected function buildConfigArray() {
  97.                 if ($this->configTableReadOnce) return;
  98.  
  99.                 $this->values = array();
  100.                 $this->descriptions = array();
  101.                 $res = OIDplus::db()->query("select name, description, value from ###config");
  102.                 while ($row = $res->fetch_object()) {
  103.                         $this->values[$row->name] = $row->value;
  104.                         $this->descriptions[$row->name] = $row->description;
  105.                 }
  106.  
  107.                 $this->configTableReadOnce = true;
  108.         }
  109.  
  110.         public function getValue($name, $default=null) {
  111.                 if (isset($this->values[$name])) {
  112.                         // There is a rare case where this might succeed even
  113.                         // before buildConfigArray() was called once:
  114.                         // If a setValue() was called, and then getValue() for
  115.                         // that same name!
  116.                         return $this->values[$name];
  117.                 }
  118.  
  119.                 // Read all config settings once and write them in array $this->values
  120.                 $this->buildConfigArray();
  121.  
  122.                 // Now we can see if our desired attribute is available
  123.                 if (isset($this->values[$name])) {
  124.                         return $this->values[$name];
  125.                 } else {
  126.                         return $default;
  127.                 }
  128.         }
  129.  
  130.         public function exists($name) {
  131.                 return !is_null($this->getValue($name, null));
  132.         }
  133.  
  134.         public function setValue($name, $value) {
  135.                 // Avoid unnecessary database writes
  136.                 // We do not call getValue() or buildConfigArray(), because they could cause an unnecessary database read
  137.                 if (isset($this->values[$name])) {
  138.                         if ($this->values[$name] == $value) return;
  139.                 }
  140.  
  141.                 // Give plugins the possibility to stop the process by throwing an Exception (e.g. if the value is invalid)
  142.                 // Required is that the plugin previously prepared the config setting using prepareConfigKey()
  143.                 if (isset($this->validateCallbacks[$name])) {
  144.                         $this->validateCallbacks[$name]($value);
  145.                 }
  146.  
  147.                 // Now change the value in the database
  148.                 OIDplus::db()->query("update ###config set value = ? where name = ?", array($value, $name));
  149.                 $this->values[$name] = $value;
  150.         }
  151.  
  152.         public function deleteConfigKey($name) {
  153.                 if ($this->configTableReadOnce) {
  154.                         if (isset($this->values[$name])) {
  155.                                 OIDplus::db()->query("delete from ###config where name = ?", array($name));
  156.                         }
  157.                 } else {
  158.                         // We do not know if the value exists.
  159.                         // buildConfigArray() would do many reads which are unnecessary.
  160.                         // So we just do a MySQL command to delete the stuff:
  161.                         OIDplus::db()->query("delete from ###config where name = ?", array($name));
  162.                 }
  163.  
  164.                 unset($this->values[$name]);
  165.                 unset($this->descriptions[$name]);
  166.                 unset($this->validateCallbacks[$name]);
  167.         }
  168.  
  169. }