Subversion Repositories oidplus

Rev

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