summaryrefslogtreecommitdiffstats
path: root/modules-available/baseconfig
diff options
context:
space:
mode:
Diffstat (limited to 'modules-available/baseconfig')
-rw-r--r--modules-available/baseconfig/hooks/locations-column.inc.php76
-rw-r--r--modules-available/baseconfig/inc/baseconfig.inc.php27
-rw-r--r--modules-available/baseconfig/inc/baseconfigutil.inc.php14
-rw-r--r--modules-available/baseconfig/inc/configholder.inc.php19
-rw-r--r--modules-available/baseconfig/inc/validator.inc.php18
-rw-r--r--modules-available/baseconfig/lang/de/module.json3
-rw-r--r--modules-available/baseconfig/lang/en/module.json3
-rw-r--r--modules-available/baseconfig/page.inc.php44
-rw-r--r--modules-available/baseconfig/templates/_page.html5
9 files changed, 154 insertions, 55 deletions
diff --git a/modules-available/baseconfig/hooks/locations-column.inc.php b/modules-available/baseconfig/hooks/locations-column.inc.php
new file mode 100644
index 00000000..ca30d56e
--- /dev/null
+++ b/modules-available/baseconfig/hooks/locations-column.inc.php
@@ -0,0 +1,76 @@
+<?php
+
+if (!User::hasPermission('.baseconfig.view'))
+ return null;
+
+class BaseconfigLocationColumn extends AbstractLocationColumn
+{
+
+ private $byLoc;
+ private $byMachine;
+
+ public function __construct(array $allowedLocationIds)
+ {
+ if (in_array(0, $allowedLocationIds)) {
+ $extra = 'OR m.locationid IS NULL';
+ } else {
+ $extra = '';
+ }
+ // Count overridden config vars
+ $this->byLoc = Database::queryKeyValueList("SELECT locationid, Count(*) AS cnt
+ FROM `setting_location`
+ WHERE locationid IN (:allowedLocationIds)
+ GROUP BY locationid", compact('allowedLocationIds'));
+ // Confusing because the count might be inaccurate within a branch
+ //$this->propagateFields($locationList, '', 'overriddenVars', 'overriddenClass');
+ // Count machines with overriden var(s)
+ $this->byMachine = Database::queryKeyValueList("SELECT IFNULL(m.locationid, 0), Count(DISTINCT sm.machineuuid) AS cnt
+ FROM setting_machine sm
+ INNER JOIN machine m USING (machineuuid)
+ WHERE (m.locationid IN (:allowedLocationIds) $extra)
+ GROUP BY m.locationid", compact('allowedLocationIds'));
+ // There WHERE statement drops clients without location - but this cannot be displayed by the locations
+ // table anyways as of now - maybe implement some day? Or just encourage everyone to have a root location
+ }
+
+ public function getColumnHtml(int $locationId): string
+ {
+ $ret = '';
+ if ($this->byLoc[$locationId] ?? 0) {
+ $title = htmlspecialchars(Dictionary::translateFileModule('baseconfig', 'module', 'overriden-vars-for-location'));
+ $ret .= <<<EOF
+ <span class="badge" title="{$title}">
+ <span class="glyphicon glyphicon-home"></span> {$this->byLoc[$locationId]}
+ </span>
+EOF;
+ }
+ if ($this->byMachine[$locationId] ?? 0) {
+ $title = htmlspecialchars(Dictionary::translateFileModule('baseconfig', 'module', 'overriden-vars-machines'));
+ $ret .= <<<EOF
+ <span class="badge" title="{$title}">
+ <span class="glyphicon glyphicon-tasks"></span> {$this->byMachine[$locationId]}
+ </span>
+EOF;
+ }
+ return $ret;
+ }
+
+ public function getEditUrl(int $locationId): string
+ {
+ if (!User::hasPermission('.baseconfig.edit', $locationId))
+ return '';
+ return '?do=baseconfig&module=locations&locationid=' . $locationId;
+ }
+
+ public function header(): string
+ {
+ return Dictionary::translateFileModule('baseconfig', 'module', 'location-column-header');
+ }
+
+ public function priority(): int
+ {
+ return 1000;
+ }
+}
+
+return new BaseconfigLocationColumn($allowedLocationIds); \ No newline at end of file
diff --git a/modules-available/baseconfig/inc/baseconfig.inc.php b/modules-available/baseconfig/inc/baseconfig.inc.php
index 064e0f89..36622dce 100644
--- a/modules-available/baseconfig/inc/baseconfig.inc.php
+++ b/modules-available/baseconfig/inc/baseconfig.inc.php
@@ -17,13 +17,15 @@ class BaseConfig
*/
public static function prepareFromRequest()
{
- $ip = $_SERVER['REMOTE_ADDR'];
+ $ip = $_SERVER['REMOTE_ADDR'] ?? null;
+ if ($ip === null)
+ ErrorHandler::traceError('No REMOTE_ADDR given in $_SERVER');
if (substr($ip, 0, 7) === '::ffff:') {
$ip = substr($ip, 7);
}
- $uuid = Request::any('uuid', false, 'string');
- if ($uuid !== false && strlen($uuid) !== 36) {
- $uuid = false;
+ $uuid = Request::any('uuid', null, 'string');
+ if ($uuid !== null && strlen($uuid) !== 36) {
+ $uuid = null;
}
// Handle any hooks by other modules first
// other modules should generally only populate $configVars
@@ -42,10 +44,10 @@ class BaseConfig
* 'locationid'
* @param array $overrides key value pairs of overrides
*/
- public static function prepareWithOverrides($overrides)
+ public static function prepareWithOverrides(array $overrides): void
{
self::$overrides = $overrides;
- $ip = $uuid = false;
+ $ip = $uuid = null;
if (self::hasOverride('ip')) {
$ip = self::getOverride('ip');
}
@@ -78,12 +80,12 @@ class BaseConfig
// Dump global config from DB
ConfigHolder::setContext('<global>', function($id) {
return [
- 'name' => Dictionary::translate('source-global', true),
+ 'name' => Dictionary::translate('source-global'),
'locationid' => 0,
];
});
$res = Database::simpleQuery('SELECT setting, value, displayvalue FROM setting_global');
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
if (!isset($defaults[$row['setting']]))
continue; // Setting is not defined in any <module>/baseconfig/settings.json
ConfigHolder::add($row['setting'], $row, -1);
@@ -98,7 +100,7 @@ class BaseConfig
{
ConfigHolder::setContext('<default>', function($id) {
return [
- 'name' => Dictionary::translate('source-default', true),
+ 'name' => Dictionary::translate('source-default'),
'locationid' => 0,
];
});
@@ -107,8 +109,9 @@ class BaseConfig
}
}
- private static function handleModule($name, $ip, $uuid, $needJsonHook) // Pass ip and uuid instead of global to make them read only
+ private static function handleModule(string $name, ?string $ip, ?string $uuid, bool $needJsonHook): void
{
+ // Pass ip and uuid instead of global to make them read only
if (isset(self::$modulesDone[$name]))
return;
self::$modulesDone[$name] = true;
@@ -130,12 +133,12 @@ class BaseConfig
self::handleModule($dep, $ip, $uuid, $needJsonHook);
}
ConfigHolder::setContext($name);
- (function ($file, $ip, $uuid) {
+ (function (string $file, ?string $ip, ?string $uuid) {
include_once($file);
})($file, $ip, $uuid);
}
- public static function hasOverride($key)
+ public static function hasOverride($key): bool
{
return array_key_exists($key, self::$overrides);
}
diff --git a/modules-available/baseconfig/inc/baseconfigutil.inc.php b/modules-available/baseconfig/inc/baseconfigutil.inc.php
index a48eb93b..4d1ef8c1 100644
--- a/modules-available/baseconfig/inc/baseconfigutil.inc.php
+++ b/modules-available/baseconfig/inc/baseconfigutil.inc.php
@@ -16,7 +16,7 @@ class BaseConfigUtil
* @param \Module $module optional, only consider given module, not all enabled modules
* @return array all known config variables
*/
- public static function getVariables($module = false)
+ public static function getVariables($module = false): array
{
$settings = array();
if ($module === false) {
@@ -39,16 +39,13 @@ class BaseConfigUtil
/**
* Get configuration categories for given module, or all modules if false is passed.
- *
- * @param \Module $module
- * @return array
*/
- public static function getCategories($module = false)
+ public static function getCategories(Module $module = null): array
{
$categories = array();
- if ($module === false) {
+ if ($module === null) {
$module = '*';
- } elseif (is_object($module)) {
+ } else {
$module = $module->getIdentifier();
}
foreach (glob("modules/{$module}/baseconfig/categories.json", GLOB_NOSORT) as $file) {
@@ -70,7 +67,8 @@ class BaseConfigUtil
* @param array $vars list of vars as obtained from BaseConfigUtil::getVariables()
* @param array $values key-value-pairs of variable assignments to work with
*/
- public static function markShadowedVars(&$vars, $values) {
+ public static function markShadowedVars(array &$vars, array $values): void
+ {
foreach ($vars as $key => &$var) {
if (!isset($var['shadows']))
continue;
diff --git a/modules-available/baseconfig/inc/configholder.inc.php b/modules-available/baseconfig/inc/configholder.inc.php
index 224f2aab..75b43460 100644
--- a/modules-available/baseconfig/inc/configholder.inc.php
+++ b/modules-available/baseconfig/inc/configholder.inc.php
@@ -19,7 +19,7 @@ class ConfigHolder
* @param false|string|array $value false to unset, string value, or array with keys value and displayvalue
* @param int $prio priority of this value, in case the same key gets set multiple times
*/
- public static function add($key, $value, $prio = 0)
+ public static function add(string $key, $value, int $prio = 0): void
{
if (!isset(self::$config[$key])) {
self::$config[$key] = [];
@@ -43,22 +43,19 @@ class ConfigHolder
}
}
- public static function get($key)
+ public static function get(string $key): ?string
{
if (!isset(self::$config[$key]))
- return false;
+ return null;
return self::$config[$key][0]['value'];
}
- /**
- * @param callable $func
- */
- public static function addPostHook($func)
+ public static function addPostHook(callable $func): void
{
self::$postHooks[] = array('context' => &self::$context, 'function' => $func);
}
- public static function applyPostHooks()
+ public static function applyPostHooks(): void
{
foreach (self::$postHooks as $hook) {
$newContext = $hook['context'];
@@ -69,7 +66,7 @@ class ConfigHolder
self::$postHooks = [];
}
- public static function getRecursiveConfig($prettyPrint = true)
+ public static function getRecursiveConfig(bool $prettyPrint = true): array
{
$ret = [];
foreach (self::$config as $key => $list) {
@@ -97,7 +94,7 @@ class ConfigHolder
return $ret;
}
- public static function outputConfig()
+ public static function outputConfig(): void
{
foreach (self::$config as $key => $list) {
echo str_pad('# ' . $key . ' ', 35, '#', STR_PAD_BOTH), "\n";
@@ -129,7 +126,7 @@ class ConfigHolder
* @param string $string input
* @return string escaped sh string
*/
- private static function escape($string)
+ private static function escape(string $string): string
{
return str_replace(["'", "\n", "\r"], ["'\"'\"'", ' ', ' '], $string);
}
diff --git a/modules-available/baseconfig/inc/validator.inc.php b/modules-available/baseconfig/inc/validator.inc.php
index 60cda5a4..be71c3df 100644
--- a/modules-available/baseconfig/inc/validator.inc.php
+++ b/modules-available/baseconfig/inc/validator.inc.php
@@ -32,11 +32,12 @@ class Validator
case 'multilist':
return self::validateMultiList($data[1], $displayValue);
case 'multiinput':
- return self::validateMultiInput($data[1], $displayValue);
+ return self::validateMultiInput($data[1] ?? [], $displayValue);
+ case 'suggestions':
+ return true;
default:
- Util::traceError('Unknown validation method: ' . $data[0]);
+ ErrorHandler::traceError('Unknown validation method: ' . $data[0]);
}
- return false; // make code inspector happy - doesn't know traceError doesn't return
}
@@ -44,7 +45,7 @@ class Validator
* Validate linux password. If already in $6$ hash form,
* the unchanged value will be returned.
* if empty, an empty string will also be returned.
- * Otherwise it it assumed that the value is a plain text
+ * Otherwise, it is assumed that the value is a plain text
* password that is supposed to be hashed.
*/
private static function linuxPassword($displayValue)
@@ -62,7 +63,7 @@ class Validator
* @param string $displayValue network path
* @return string cleaned up path
*/
- private static function networkShare(&$displayValue)
+ private static function networkShare(string &$displayValue): string
{
$displayValue = trim($displayValue);
if (substr($displayValue, 0, 2) === '\\\\')
@@ -75,18 +76,19 @@ class Validator
/**
* Validate value against list.
+ *
* @param string $list The list as a string of items, separated by "|"
* @param string $displayValue The value to validate
* @return boolean|string The value, if in list, false otherwise
*/
- private static function validateList($list, &$displayValue)
+ private static function validateList(string $list, string $displayValue)
{
$list = explode('|', $list);
if (in_array($displayValue, $list))
return $displayValue;
return false;
}
- private static function validateMultiList($list, &$displayValue)
+ private static function validateMultiList(string $list, array &$displayValue): string
{
$allowedValues = explode('|', $list);
$values = [];
@@ -99,7 +101,7 @@ class Validator
return $displayValue;
}
- private static function validateMultiInput($list, &$displayValue)
+ private static function validateMultiInput($list, $displayValue)
{
return $displayValue;
}
diff --git a/modules-available/baseconfig/lang/de/module.json b/modules-available/baseconfig/lang/de/module.json
index f7dbf53a..a9c2c6bf 100644
--- a/modules-available/baseconfig/lang/de/module.json
+++ b/modules-available/baseconfig/lang/de/module.json
@@ -1,5 +1,8 @@
{
+ "location-column-header": "Konfig.-Variablen",
"module_name": "Konfigurationsvariablen",
+ "overriden-vars-for-location": "F\u00fcr diesen Ort \u00fcberschriebene Variablen",
+ "overriden-vars-machines": "Rechner an diesem Ort, die \u00fcberschriebene Variablen haben",
"source-default": "Auslieferungszustand",
"source-global": "Global"
} \ No newline at end of file
diff --git a/modules-available/baseconfig/lang/en/module.json b/modules-available/baseconfig/lang/en/module.json
index 97e19f92..5a25bcff 100644
--- a/modules-available/baseconfig/lang/en/module.json
+++ b/modules-available/baseconfig/lang/en/module.json
@@ -1,5 +1,8 @@
{
+ "location-column-header": "Config. Vars",
"module_name": "Config Variables",
+ "overriden-vars-for-location": "Number of variables overridden at this location",
+ "overriden-vars-machines": "Machines at this location that have overridden variables",
"source-default": "Factory default",
"source-global": "Global"
} \ No newline at end of file
diff --git a/modules-available/baseconfig/page.inc.php b/modules-available/baseconfig/page.inc.php
index 1566464b..5d684a8e 100644
--- a/modules-available/baseconfig/page.inc.php
+++ b/modules-available/baseconfig/page.inc.php
@@ -68,7 +68,7 @@ class Page_BaseConfig extends Page
if (isset($var['shadowed']))
continue;
$validator = $var['validator'];
- $displayValue = (isset($newValues[$key]) ? $newValues[$key] : '');
+ $displayValue = $newValues[$key] ?? '';
// Validate data first!
$mangledValue = Validator::validate($validator, $displayValue);
if ($mangledValue === false) {
@@ -101,7 +101,7 @@ class Page_BaseConfig extends Page
foreach ($this->categories as $catid => $val) {
Dashboard::addSubmenu(
'#category_' . $catid,
- Dictionary::translateFileModule($this->categories[$catid]['module'], 'config-variable-categories', $catid, true)
+ Dictionary::translateFileModule($this->categories[$catid]['module'], 'config-variable-categories', $catid)
);
}
}
@@ -120,12 +120,11 @@ class Page_BaseConfig extends Page
User::assertPermission('view', $lid);
$editForbidden = !User::hasPermission('edit', $lid);
// Get stuff that's set in DB already
+ $fields = '';
if ($this->targetModule !== false && isset($this->qry_extra['field'])) {
- $fields = '';
$where = " WHERE {$this->qry_extra['field']} = :field_value";
$params = array('field_value' => $this->qry_extra['field_value']);
} else {
- $fields = '';
$where = '';
$params = array();
}
@@ -136,7 +135,7 @@ class Page_BaseConfig extends Page
// Remember missing variables
$missing = $varsFromJson;
// Populate structure with existing config from db
- $this->fillSettings($varsFromJson, $settings, $missing, $this->qry_extra['table'], $fields, $where, $params, false);
+ $this->fillSettings($varsFromJson, $settings, $missing, $this->qry_extra['table'], $fields, $where, $params);
// Add entries that weren't in the db (global), setup override checkbox (module specific)
foreach ($varsFromJson as $key => $var) {
if ($this->targetModule !== false && !isset($settings[$var['catid']]['settings'][$key])) {
@@ -154,7 +153,7 @@ class Page_BaseConfig extends Page
}
}
if (!isset($entry['shadows'])) {
- $entry['shadows'] = isset($var['shadows']) ? $var['shadows'] : null;
+ $entry['shadows'] = $var['shadows'] ?? null;
}
$entry += array(
'item' => $this->makeInput(
@@ -166,7 +165,7 @@ class Page_BaseConfig extends Page
),
'description' => Util::markup(Dictionary::translateFileModule($var['module'], 'config-variables', $key)),
'setting' => $key,
- 'tree' => isset($parents[$key]) ? $parents[$key] : false,
+ 'tree' => $parents[$key] ?? false,
);
}
unset($entry);
@@ -195,15 +194,15 @@ class Page_BaseConfig extends Page
) + $this->qry_extra);
}
- private function fillSettings($vars, &$settings, &$missing, $table, $fields, $where, $params, $sourceName)
+ private function fillSettings($vars, &$settings, &$missing, $table, $fields, $where, $params): void
{
$res = Database::simpleQuery("SELECT setting, value, displayvalue $fields FROM $table "
. " {$where} ORDER BY setting ASC", $params);
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
if (!isset($missing[$row['setting']]))
continue;
if (!isset($vars[$row['setting']]) || !is_array($vars[$row['setting']])) {
- $unknown[] = $row['setting'];
+ //$unknown[] = $row['setting'];
continue;
}
unset($missing[$row['setting']]);
@@ -261,7 +260,7 @@ class Page_BaseConfig extends Page
$this->qry_extra = $hook;
}
- private function getPermissionLocationId()
+ private function getPermissionLocationId(): int
{
if (!isset($this->qry_extra['locationResolver']) || !isset($this->qry_extra['field_value']))
return 0;
@@ -281,10 +280,8 @@ class Page_BaseConfig extends Page
/**
* Create html snippet for setting, based on given validator
- * @param string $validator
- * @return boolean
*/
- private function makeInput($validator, $setting, $current, $shadows, $disabled)
+ private function makeInput(string $validator, string $setting, string $current, ?array $shadows, bool $disabled): string
{
/* for the html snippet we need: */
$args = array('class' => 'form-control', 'name' => "setting[$setting]", 'id' => $setting);
@@ -294,7 +291,7 @@ class Page_BaseConfig extends Page
if ($disabled) {
$args['disabled'] = true;
}
- $inner = "";
+ $extra = $inner = "";
/* -- */
$parts = explode(':', $validator, 2);
@@ -314,6 +311,21 @@ class Page_BaseConfig extends Page
unset($args['type']);
$current = '';
+ } elseif ($parts[0] === 'suggestions') {
+
+ $extra = '<datalist id="list-' . $setting . '">';
+ $items = explode('|', $parts[1]);
+ foreach ($items as $item) {
+ $extra .= '<option>' . htmlspecialchars($item) . '</option>';
+ }
+ $extra .= '</datalist>';
+
+ $tag = 'input';
+ $args['value'] = $current;
+ $args['type'] = 'text';
+ $args['list'] = 'list-' . $setting;
+ $current = '';
+
} elseif ($parts[0] == 'multilist') {
$items = explode('|', $parts[1]);
@@ -362,7 +374,7 @@ class Page_BaseConfig extends Page
$output .= '>' . $inner . "</$tag>";
}
- return $output;
+ return $output . $extra;
}
}
diff --git a/modules-available/baseconfig/templates/_page.html b/modules-available/baseconfig/templates/_page.html
index ef10ac26..5faff391 100644
--- a/modules-available/baseconfig/templates/_page.html
+++ b/modules-available/baseconfig/templates/_page.html
@@ -113,15 +113,20 @@ document.addEventListener("DOMContentLoaded", function () {
var rules = $this.data('shadows');
if (!rules) return;
var currentValue = $this.val();
+ const disabled = [];
for (var triggerVal in rules) {
if (!rules.hasOwnProperty(triggerVal))
continue;
var targets = rules[triggerVal];
for (var i = 0; i < targets.length; ++i) {
var target = targets[i];
+ if (disabled.includes(target)) {
+ continue;
+ }
var inp = $('#' + target);
var selitem = inp.data('selitem');
if (currentValue === triggerVal) {
+ disabled.push(target);
inp.prop('disabled', true);
if (selitem) selitem.disable();
inp.filter('.multilist').multiselect('disable');