Subversion Repositories oidplus

Rev

Rev 730 | Rev 1086 | 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. namespace ViaThinkSoft\OIDplus;
  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 extends OIDplusBaseClass implements OIDplusGetterSetterInterface {
  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 $protectSettings = array();
  37.         protected $visibleSettings = array();
  38.         protected $validateCallbacks = array();
  39.  
  40.         public function prepareConfigKey($name, $description, $init_value, $protection, $validateCallback) {
  41.                 // Check if the protection flag is valid
  42.                 switch ($protection) {
  43.                         case OIDplusConfig::PROTECTION_EDITABLE:
  44.                                 $protected = 0;
  45.                                 $visible   = 1;
  46.                                 break;
  47.                         case OIDplusConfig::PROTECTION_READONLY:
  48.                                 $protected = 1;
  49.                                 $visible   = 1;
  50.                                 break;
  51.                         case OIDplusConfig::PROTECTION_HIDDEN:
  52.                                 $protected = 1;
  53.                                 $visible   = 0;
  54.                                 break;
  55.                         default:
  56.                                 throw new OIDplusException(_L('Invalid protection flag, use OIDplusConfig::PROTECTION_* constants'));
  57.                 }
  58.  
  59.                 // Check length limitations given by the database tables
  60.                 if (strlen($name) > 50) {
  61.                         throw new OIDplusException(_L('Config key name "%1" is too long (max %2).',$name,50));
  62.                 }
  63.                 if (strlen($description) > 255) {
  64.                         throw new OIDplusException(_L('Description for config key "%1" is too long (max %2).',$name,255));
  65.                 }
  66.  
  67.                 // Read all values and descriptions from the database once.
  68.                 $this->buildConfigArray();
  69.  
  70.                 // Figure out if we need to create/update something at database level
  71.                 if (!isset($this->values[$name])) {
  72.                         // Case A: The config setting does not exist in the database. So we create it now.
  73.                         try {
  74.                                 OIDplus::db()->query("insert into ###config (name, description, value, protected, visible) values (?, ?, ?, ?, ?)", array($name, $description, $init_value, $protected, $visible));
  75.                         } catch (\Exception $e) {
  76.                                 // After a software update that introduced a new config setting,
  77.                                 // there will be a race-condition at this place, because
  78.                                 // jsTree and content are loading simultaneously!
  79.                                 // So we ignore the error here.
  80.                         }
  81.                         $this->values[$name] = $init_value;
  82.                         $this->descriptions[$name] = $description;
  83.                         $this->protectSettings[$name] = $protected;
  84.                         $this->visibleSettings[$name] = $visible;
  85.                 } else {
  86.                         // Case B: The config setting exists ...
  87.                         if ($this->descriptions[$name] != $description) {
  88.                                 // ... but the human readable description is different.
  89.                                 // We want to give the plugin authors the possibility to automatically update the config descriptions for their plugins
  90.                                 // So we just edit the description
  91.                                 OIDplus::db()->query("update ###config set description = ? where name = ?", array($description, $name));
  92.                                 $this->descriptions[$name] = $description;
  93.                         }
  94.                         if ($this->protectSettings[$name] != $protected) {
  95.                                 OIDplus::db()->query("update ###config set protected = ? where name = ?", array($protected, $name));
  96.                                 $this->protectSettings[$name] = $protected;
  97.                         }
  98.                         if ($this->visibleSettings[$name] != $visible) {
  99.                                 OIDplus::db()->query("update ###config set visible = ? where name = ?", array($visible, $name));
  100.                                 $this->visibleSettings[$name] = $visible;
  101.                         }
  102.                 }
  103.  
  104.                 // Register the validation callback
  105.                 if (!is_null($validateCallback)) {
  106.                         $this->validateCallbacks[$name] = $validateCallback;
  107.                 }
  108.         }
  109.  
  110.         public function clearCache() {
  111.                 $this->configTableReadOnce = false;
  112.                 $this->buildConfigArray();
  113.         }
  114.  
  115.         protected function buildConfigArray() {
  116.                 if ($this->configTableReadOnce) return;
  117.  
  118.                 $this->values = array();
  119.                 $this->descriptions = array();
  120.                 $this->protectSettings = array();
  121.                 $this->visibleSettings = array();
  122.                 $res = OIDplus::db()->query("select name, description, protected, visible, value from ###config");
  123.                 while ($row = $res->fetch_object()) {
  124.                         $this->values[$row->name] = $row->value;
  125.                         $this->descriptions[$row->name] = $row->description;
  126.                         $this->protectSettings[$row->name] = $row->protected;
  127.                         $this->visibleSettings[$row->name] = $row->visible;
  128.                 }
  129.  
  130.                 $this->configTableReadOnce = true;
  131.         }
  132.  
  133.         public function getValue($name, $default=null) {
  134.                 // Read all config settings once and write them in array $this->values
  135.                 $this->buildConfigArray();
  136.  
  137.                 // Now we can see if our desired attribute is available
  138.                 if (isset($this->values[$name])) {
  139.                         return $this->values[$name];
  140.                 } else {
  141.                         return $default;
  142.                 }
  143.         }
  144.  
  145.         public function exists($name) {
  146.                 return !is_null($this->getValue($name, null));
  147.         }
  148.  
  149.         public function setValue($name, $value) {
  150.                 // Read all config settings once and write them in array $this->values
  151.                 $this->buildConfigArray();
  152.  
  153.                 if (isset($this->values[$name])) {
  154.                         // Avoid unnecessary database writes
  155.                         if ($this->values[$name] == $value) return;
  156.                 } else {
  157.                         throw new OIDplusException(_L('Config value "%1" cannot be written because it was not prepared!', $name));
  158.                 }
  159.  
  160.                 // Give plugins the possibility to stop the process by throwing an Exception (e.g. if the value is invalid)
  161.                 // Required is that the plugin previously prepared the config setting using prepareConfigKey()
  162.                 if (isset($this->validateCallbacks[$name])) {
  163.                         $this->validateCallbacks[$name]($value);
  164.                 }
  165.  
  166.                 // Now change the value in the database
  167.                 OIDplus::db()->query("update ###config set value = ? where name = ?", array($value, $name));
  168.                 $this->values[$name] = $value;
  169.         }
  170.  
  171.         public function setValueNoCallback($name, $value) {
  172.                 // Read all config settings once and write them in array $this->values
  173.                 $this->buildConfigArray();
  174.  
  175.                 if (isset($this->values[$name])) {
  176.                         // Avoid unnecessary database writes
  177.                         if ($this->values[$name] == $value) return;
  178.                 } else {
  179.                         throw new OIDplusException(_L('Config value "%1" cannot be written because it was not prepared!', $name));
  180.                 }
  181.  
  182.                 // Now change the value in the database
  183.                 OIDplus::db()->query("update ###config set value = ? where name = ?", array($value, $name));
  184.                 $this->values[$name] = $value;
  185.         }
  186.  
  187.         public function delete($name) {
  188.                 if ($this->configTableReadOnce) {
  189.                         if (isset($this->values[$name])) {
  190.                                 OIDplus::db()->query("delete from ###config where name = ?", array($name));
  191.                         }
  192.                 } else {
  193.                         // We do not know if the value exists.
  194.                         // buildConfigArray() would do many reads which are unnecessary.
  195.                         // So we just do a MySQL command to delete the stuff:
  196.                         OIDplus::db()->query("delete from ###config where name = ?", array($name));
  197.                 }
  198.  
  199.                 unset($this->values[$name]);
  200.                 unset($this->descriptions[$name]);
  201.                 unset($this->validateCallbacks[$name]);
  202.                 unset($this->protectSettings[$name]);
  203.                 unset($this->visibleSettings[$name]);
  204.         }
  205.  
  206. }
  207.