diff options
Diffstat (limited to 'modules-available/baseconfig')
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'); |