From 50d28a0ad8dcf5d9fe697278b6ea05aa00f8fb87 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 5 Nov 2019 18:01:37 +0100 Subject: [baseconfig] Overhaul hook system This enables us to finally properly show the inheritance flow of all the config variables when editing the baseconfig for a certain location or machine. --- modules-available/baseconfig/api.inc.php | 175 +-------------------- .../baseconfig/inc/baseconfig.inc.php | 148 +++++++++++++++++ .../baseconfig/inc/configholder.inc.php | 137 ++++++++++++++++ modules-available/baseconfig/lang/de/module.json | 4 +- .../baseconfig/lang/de/template-tags.json | 3 +- modules-available/baseconfig/lang/en/module.json | 4 +- .../baseconfig/lang/en/template-tags.json | 3 +- modules-available/baseconfig/page.inc.php | 67 ++++---- modules-available/baseconfig/templates/_page.html | 108 +++++++------ .../locations/baseconfig/getconfig.inc.php | 25 ++- modules-available/locations/baseconfig/hook.json | 2 +- .../locations/inc/locationhooks.inc.php | 28 ++-- .../statistics/baseconfig/getconfig.inc.php | 3 + modules-available/statistics/baseconfig/hook.json | 2 +- .../statistics/inc/statisticshooks.inc.php | 20 ++- 15 files changed, 449 insertions(+), 280 deletions(-) create mode 100644 modules-available/baseconfig/inc/baseconfig.inc.php create mode 100644 modules-available/baseconfig/inc/configholder.inc.php diff --git a/modules-available/baseconfig/api.inc.php b/modules-available/baseconfig/api.inc.php index aab03b5a..350c6173 100644 --- a/modules-available/baseconfig/api.inc.php +++ b/modules-available/baseconfig/api.inc.php @@ -1,125 +1,5 @@ $value) { - self::add($key, $value, $prio); - } - } - - public static function add($key, $value, $prio = 0) - { - if (!isset(self::$config[$key])) { - self::$config[$key] = []; - } - $new = [ - 'prio' => $prio, - 'value' => $value, - 'context' => self::$context, - ]; - if (empty(self::$config[$key]) || self::$config[$key][0]['prio'] > $prio) { - // Existing is higher, append new one - array_push(self::$config[$key], $new); - } else { - // New one has highest prio or matches existing, put in front - array_unshift(self::$config[$key], $new); - } - } - - public static function get($key) - { - if (!isset(self::$config[$key])) - return false; - return self::$config[$key][0]['value']; - } - - /** - * @param callable $func - */ - public static function addPostHook($func) - { - self::$postHooks[] = array('context' => self::$context, 'function' => $func); - } - - public static function applyPostHooks() - { - foreach (self::$postHooks as $hook) { - self::$context = $hook['context'] . ':post'; - $hook['function'](); - } - self::$postHooks = []; - } - - public static function getConfig() - { - self::applyPostHooks(); - $ret = []; - foreach (self::$config as $key => $list) { - if ($list[0]['value'] === false) - continue; - $ret[$key] = $list[0]['value']; - } - return $ret; - } - - public static function outputConfig() - { - self::applyPostHooks(); - foreach (self::$config as $key => $list) { - echo str_pad('# ' . $key . ' ', 35, '#', STR_PAD_BOTH), "\n"; - foreach ($list as $pos => $item) { - if ($pos != 0 || $item['value'] === false) { - echo '# (', $item['context'], ':', $item['prio'], ')'; - if ($pos == 0) { - echo " \n"; - } else { - echo " \n"; - } - } else { - echo $key, "='", escape($item['value']), "'\n"; - echo '# (', $item['context'], ':', $item['prio'], ") \n"; - } - } - } - } - -} - -/** - * Escape given string so it is a valid string in sh that can be surrounded - * by single quotes ('). This basically turns _'_ into _'"'"'_ - * - * @param string $string input - * @return string escaped sh string - */ -function escape($string) -{ - return str_replace("'", "'\"'\"'", $string); -} - /* * We gather all config variables here. First, let other modules generate * their desired config vars. Afterwards, add the global config vars from @@ -127,58 +7,19 @@ function escape($string) * global setting. */ -function handleModule($name, $ip, $uuid) // Pass ip and uuid instead of global to make them read only -{ - // Module has getconfig hook - $file = 'modules/' . $name . '/baseconfig/getconfig.inc.php'; - if (!is_file($file)) - return; - // Properly registered and can be activated - $mod = Module::get($name); - if ($mod === false) - return; - if (!$mod->activate(1, false)) - return; - // Process dependencies first - foreach ($mod->getDependencies() as $dep) { - handleModule($dep, $ip, $uuid); - } - ConfigHolder::setContext($name); - (function($file, $ip, $uuid) { - include_once($file); - })($file, $ip, $uuid); -} - -// Handle any hooks by other modules first -// other modules should generally only populate $configVars -foreach (glob('modules/*/baseconfig/getconfig.inc.php') as $file) { - preg_match('#^modules/([^/]+)/#', $file, $out); - ConfigHolder::setContext($out[1]); - handleModule($out[1], $ip, $uuid); -} - -// Rest is handled by module -$defaults = BaseConfigUtil::getVariables(); -// Dump global config from DB -ConfigHolder::setContext(''); -$res = Database::simpleQuery('SELECT setting, value FROM setting_global'); -while ($row = $res->fetch(PDO::FETCH_ASSOC)) { - if (!isset($defaults[$row['setting']])) - continue; // Setting is not defined in any /baseconfig/settings.json - ConfigHolder::add($row['setting'], $row['value'], -1); -} +// Prepare ConfigHolder from request data +BaseConfig::prepareFromRequest(); -// Fallback to default values from json files -ConfigHolder::setContext(''); -foreach ($defaults as $setting => $value) { - ConfigHolder::add($setting, $value['defaultvalue'], -1000); -} +ConfigHolder::add('SLX_NOW', time(), PHP_INT_MAX); // All done, now output -ConfigHolder::add('SLX_NOW', time(), PHP_INT_MAX); +ConfigHolder::applyPostHooks(); ConfigHolder::outputConfig(); // For quick testing or custom extensions: Include external file that should do nothing // more than outputting more key-value-pairs. It's expected in the webroot of slxadmin -if (file_exists('client_config_additional.php')) @include('client_config_additional.php'); +if (file_exists('client_config_additional.php')) { + echo "########## client_config_additional.php:\n"; + @include('client_config_additional.php'); +} diff --git a/modules-available/baseconfig/inc/baseconfig.inc.php b/modules-available/baseconfig/inc/baseconfig.inc.php new file mode 100644 index 00000000..064e0f89 --- /dev/null +++ b/modules-available/baseconfig/inc/baseconfig.inc.php @@ -0,0 +1,148 @@ +', function($id) { + return [ + 'name' => Dictionary::translate('source-global', true), + 'locationid' => 0, + ]; + }); + $res = Database::simpleQuery('SELECT setting, value, displayvalue FROM setting_global'); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + if (!isset($defaults[$row['setting']])) + continue; // Setting is not defined in any /baseconfig/settings.json + ConfigHolder::add($row['setting'], $row, -1); + } + + // Fallback to default values from json files + self::addDefaults($defaults); + + } + + private static function addDefaults($defaults) + { + ConfigHolder::setContext('', function($id) { + return [ + 'name' => Dictionary::translate('source-default', true), + 'locationid' => 0, + ]; + }); + foreach ($defaults as $setting => $value) { + ConfigHolder::add($setting, $value['defaultvalue'], -1000); + } + } + + private static function handleModule($name, $ip, $uuid, $needJsonHook) // Pass ip and uuid instead of global to make them read only + { + if (isset(self::$modulesDone[$name])) + return; + self::$modulesDone[$name] = true; + // Module has getconfig hook + $file = 'modules/' . $name . '/baseconfig/getconfig.inc.php'; + if (!is_file($file)) + return; + // We want only static hooks that have a json config (currently used for displaying inheritance tree) + if ($needJsonHook && !is_file('modules/' . $name . '/baseconfig/hook.json')) + return; + // Properly registered and can be activated + $mod = Module::get($name); + if ($mod === false) + return; + if (!$mod->activate(1, false)) + return; + // Process dependencies first + foreach ($mod->getDependencies() as $dep) { + self::handleModule($dep, $ip, $uuid, $needJsonHook); + } + ConfigHolder::setContext($name); + (function ($file, $ip, $uuid) { + include_once($file); + })($file, $ip, $uuid); + } + + public static function hasOverride($key) + { + return array_key_exists($key, self::$overrides); + } + + public static function getOverride($key) + { + return self::$overrides[$key]; + } + +} \ No newline at end of file diff --git a/modules-available/baseconfig/inc/configholder.inc.php b/modules-available/baseconfig/inc/configholder.inc.php new file mode 100644 index 00000000..e5856128 --- /dev/null +++ b/modules-available/baseconfig/inc/configholder.inc.php @@ -0,0 +1,137 @@ + $id, 'resolver' => $resolver]; + self::$context =& $tmp; + } + + /** + * @param string $key config variable name + * @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) + { + if (!isset(self::$config[$key])) { + self::$config[$key] = []; + } + $new = [ + 'prio' => $prio, + 'context' => &self::$context, + ]; + if (is_array($value)) { + $new['value'] = $value['value']; + $new['displayvalue'] = $value['displayvalue']; + } else { + $new['value'] = $value; + } + if (empty(self::$config[$key]) || self::$config[$key][0]['prio'] > $prio) { + // Existing is higher, append new one + array_push(self::$config[$key], $new); + } else { + // New one has highest prio or matches existing, put in front + array_unshift(self::$config[$key], $new); + } + } + + public static function get($key) + { + if (!isset(self::$config[$key])) + return false; + return self::$config[$key][0]['value']; + } + + /** + * @param callable $func + */ + public static function addPostHook($func) + { + self::$postHooks[] = array('context' => &self::$context, 'function' => $func); + } + + public static function applyPostHooks() + { + foreach (self::$postHooks as $hook) { + $newContext = $hook['context']; + $newContext['post'] = true; + self::$context =& $newContext; + $hook['function'](); + } + self::$postHooks = []; + } + + public static function getRecursiveConfig($prettyPrint = true) + { + $ret = []; + foreach (self::$config as $key => $list) { + $last = false; + foreach ($list as $entry) { + if ($last !== false && $last['context']['id'] === '' + && $entry['context']['id'] === '' && $last['value'] === $entry['value']) + continue; + $cb =& $entry['context']['resolver']; + $valueKey = 'value'; + if ($prettyPrint && is_callable($cb)) { + $data = $cb($entry['context']['id']); + $name = $data['name']; + if (isset($data['locationid']) && isset($entry['displayvalue']) + && User::hasPermission('.baseconfig.view', $data['locationid'])) { + $valueKey = 'displayvalue'; + } + } else { + $name = $entry['context']['id']; + } + $ret[$key][] = ['name' => $name, 'value' => $entry[$valueKey]]; + $last = $entry; + } + } + return $ret; + } + + public static function outputConfig() + { + foreach (self::$config as $key => $list) { + echo str_pad('# ' . $key . ' ', 35, '#', STR_PAD_BOTH), "\n"; + foreach ($list as $pos => $item) { + $ctx = $item['context']['id']; + if (isset($item['context']['post'])) { + $ctx .= '[post-hook]'; + } + $ctx .= ' :: ' . $item['prio']; + if ($pos != 0 || $item['value'] === false) { + echo '# (', $ctx, ')'; + if ($pos == 0) { + echo " \n"; + } else { + echo " \n"; + } + } else { + echo $key, "='", self::escape($item['value']), "'\n"; + echo '# (', $ctx, ") \n"; + } + } + } + } + + /** + * Escape given string so it is a valid string in sh that can be surrounded + * by single quotes ('). This basically turns _'_ into _'"'"'_ + * + * @param string $string input + * @return string escaped sh string + */ + private static function escape($string) + { + return str_replace("'", "'\"'\"'", $string); + } + +} diff --git a/modules-available/baseconfig/lang/de/module.json b/modules-available/baseconfig/lang/de/module.json index 44b51ec3..f7dbf53a 100644 --- a/modules-available/baseconfig/lang/de/module.json +++ b/modules-available/baseconfig/lang/de/module.json @@ -1,3 +1,5 @@ { - "module_name": "Konfigurationsvariablen" + "module_name": "Konfigurationsvariablen", + "source-default": "Auslieferungszustand", + "source-global": "Global" } \ No newline at end of file diff --git a/modules-available/baseconfig/lang/de/template-tags.json b/modules-available/baseconfig/lang/de/template-tags.json index dfaecc96..1ce62c87 100644 --- a/modules-available/baseconfig/lang/de/template-tags.json +++ b/modules-available/baseconfig/lang/de/template-tags.json @@ -1,8 +1,7 @@ { "lang_basicConfiguration": "Basiskonfiguration", "lang_clientRelatedConfig": "Die Optionen auf dieser Seite beziehen sich auf das Verhalten der bwLehrpool-Clients.", - "lang_defaultValue": "Standard", "lang_editOverrideNotice": "Sie bearbeiten die Einstellungen f\u00fcr einen Unterbereich", "lang_enableOverride": "\u00dcberschreiben", - "lang_inheritSource": "Geerbt von" + "lang_showParents": "Geerbte Werte" } \ 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 9ad9d10f..97e19f92 100644 --- a/modules-available/baseconfig/lang/en/module.json +++ b/modules-available/baseconfig/lang/en/module.json @@ -1,3 +1,5 @@ { - "module_name": "Config Variables" + "module_name": "Config Variables", + "source-default": "Factory default", + "source-global": "Global" } \ No newline at end of file diff --git a/modules-available/baseconfig/lang/en/template-tags.json b/modules-available/baseconfig/lang/en/template-tags.json index 471fef35..9ac578e7 100644 --- a/modules-available/baseconfig/lang/en/template-tags.json +++ b/modules-available/baseconfig/lang/en/template-tags.json @@ -1,8 +1,7 @@ { "lang_basicConfiguration": "Basic Configuration", "lang_clientRelatedConfig": "The options on this page are related to the bwLehrpool client machines.", - "lang_defaultValue": "Default", "lang_editOverrideNotice": "You're editing the settings of a sub-section", "lang_enableOverride": "Override", - "lang_inheritSource": "Inherited from" + "lang_showParents": "Inherited values" } \ No newline at end of file diff --git a/modules-available/baseconfig/page.inc.php b/modules-available/baseconfig/page.inc.php index 0c11d5e1..a931d3f3 100644 --- a/modules-available/baseconfig/page.inc.php +++ b/modules-available/baseconfig/page.inc.php @@ -127,59 +127,47 @@ class Page_BaseConfig extends Page $where = ''; $params = array(); } + $parents = $this->getInheritanceData(); // List config options $settings = array(); - $vars = BaseConfigUtil::getVariables(); + $varsFromJson = BaseConfigUtil::getVariables(); // Remember missing variables - $missing = $vars; + $missing = $varsFromJson; // Populate structure with existing config from db - $this->fillSettings($vars, $settings, $missing, $this->qry_extra['table'], $fields, $where, $params, false); - if (isset($this->qry_extra['getfallback']) && !empty($missing)) { - $method = explode('::', $this->qry_extra['getfallback']); - $fieldValue = $this->qry_extra['field_value']; - $tries = 0; - while (++$tries < 100 && !empty($missing)) { - $ret = call_user_func($method, $fieldValue); - if ($ret === false) - break; - $fieldValue = $ret['value']; - $params = array('field_value' => $fieldValue); - $this->fillSettings($vars, $settings, $missing, $this->qry_extra['table'], $fields, $where, $params, $ret['display']); - } - } - if ($this->targetModule !== false && !empty($missing)) { - $this->fillSettings($vars, $settings, $missing, 'setting_global', '', '', array(), 'Global'); - } + $this->fillSettings($varsFromJson, $settings, $missing, $this->qry_extra['table'], $fields, $where, $params, false); // Add entries that weren't in the db (global), setup override checkbox (module specific) - foreach ($vars as $key => $var) { + foreach ($varsFromJson as $key => $var) { if ($this->targetModule !== false && !isset($settings[$var['catid']]['settings'][$key])) { // Module specific - value is not set in DB - $settings[$var['catid']]['settings'][$key] = $var + array( + $settings[$var['catid']]['settings'][$key] = array( 'setting' => $key ); } - if (!isset($settings[$var['catid']]['settings'][$key]['displayvalue'])) { - $settings[$var['catid']]['settings'][$key]['displayvalue'] = $var['defaultvalue']; - } - if (!isset($settings[$var['catid']]['settings'][$key]['defaultvalue'])) { - $settings[$var['catid']]['settings'][$key]['defaultvalue'] = $var['defaultvalue']; + $entry =& $settings[$var['catid']]['settings'][$key]; + if (!isset($entry['displayvalue'])) { + if (isset($parents[$key][0]['value'])) { + $entry['displayvalue'] = $parents[$key][0]['value']; + } else { + $entry['displayvalue'] = $var['defaultvalue']; + } } - if (!isset($settings[$var['catid']]['settings'][$key]['shadows'])) { - $settings[$var['catid']]['settings'][$key]['shadows'] = isset($var['shadows']) ? $var['shadows'] : null; + if (!isset($entry['shadows'])) { + $entry['shadows'] = isset($var['shadows']) ? $var['shadows'] : null; } - $settings[$var['catid']]['settings'][$key] += array( + $entry += array( 'item' => $this->makeInput( $var['validator'], $key, - $settings[$var['catid']]['settings'][$key]['displayvalue'], - $settings[$var['catid']]['settings'][$key]['shadows'], + $entry['displayvalue'], + $entry['shadows'], $editForbidden ), 'description' => Util::markup(Dictionary::translateFileModule($var['module'], 'config-variables', $key)), 'setting' => $key, + 'tree' => isset($parents[$key]) ? $parents[$key] : false, ); } - //die(); + unset($entry); // Sort categories @@ -216,10 +204,7 @@ class Page_BaseConfig extends Page continue; } unset($missing[$row['setting']]); - if ($sourceName !== false) { - $row['defaultvalue'] = ''; - $row['defaultsource'] = $sourceName; - } elseif ($this->targetModule !== false) { + if ($this->targetModule !== false) { $row['checked'] = 'checked'; } $row += $vars[$row['setting']]; @@ -280,6 +265,16 @@ class Page_BaseConfig extends Page $func = explode('::', $this->qry_extra['locationResolver']); return (int)call_user_func($func, $this->qry_extra['field_value']); } + + private function getInheritanceData() + { + if (!isset($this->qry_extra['getInheritance']) || !isset($this->qry_extra['field_value'])) { + BaseConfig::prepareDefaults(); + return ConfigHolder::getRecursiveConfig(true); + } + $func = explode('::', $this->qry_extra['getInheritance']); + return call_user_func($func, $this->qry_extra['field_value']); + } /** * Create html snippet for setting, based on given validator diff --git a/modules-available/baseconfig/templates/_page.html b/modules-available/baseconfig/templates/_page.html index 7f7c33d0..1f9bcafb 100644 --- a/modules-available/baseconfig/templates/_page.html +++ b/modules-available/baseconfig/templates/_page.html @@ -18,52 +18,53 @@ {{category_name}} -
-
- {{#settings}} -
-
-
-
{{setting}}
-
- {{#defaultvalue}}{{lang_defaultValue}}:{{/defaultvalue}} - {{defaultvalue}} -
- {{#override}} -
- - -
- {{/override}} +
+ {{#settings}} +
+
+
+
{{setting}}
+ {{#override}} +
+ +
-
- {{{item}}} -
- {{#defaultsource}}{{lang_inheritSource}}:{{/defaultsource}} - {{defaultsource}} -
+ {{/override}} +
+
+ {{{item}}} +
+ {{#tree.0}} + {{lang_showParents}} + + {{/tree.0}}
-
- +
+ {{#tree}} +
{{name}}: {{value}}
+ {{/tree}}
+
+ +
- {{/categories}} @@ -135,25 +136,44 @@ document.addEventListener("DOMContentLoaded", function () { var updateCheckbox = function() { var id = '#CB_' + $(this).attr('id'); - $(id).prop('checked', true); + var $cb = $(id).prop('checked', true); + if ($cb.length > 0) { + syncCheckbox.call($cb[0]); + } + }; + var syncCheckbox = function() { + var setting = this.id.substr(3); + var $itm = $('#tree-' + setting + ' > div:first-child'); + if (this.checked) { + $itm.addClass('slx-strike'); + } else { + $itm.removeClass('slx-strike'); + } }; var $cont = $('.config-container'); $cont.find('select, input').on('change', updateCheckbox); $cont.find('input').on('input', updateCheckbox); $('.override-cb').on('change', function() { - if (this.checked) return; - var input = document.getElementById(this.id.substr(3)); + var setting = this.id.substr(3); + syncCheckbox.call(this); + var input = document.getElementById(setting); if (!input) return; + var defaults = this.checked ? false : ('' + $('#default-' + setting).text()); if (input.tagName.toUpperCase() === 'SELECT') { + var items = defaults === false ? false : defaults.split(/\s+/); $(input).find('option').each(function() { - $(this).prop('selected', this.defaultSelected); + $(this).prop('selected', items === false ? this.defaultSelected : (items.indexOf(this.value) !== -1)); }); $(input).filter('.multilist').multiselect('refresh'); } else if (input.type && input.type.toUpperCase() === 'CHECKBOX') { - $(input).prop('checked', input.defaultChecked); - } else if (input.defaultValue !== undefined) { - $(input).val(input.defaultValue); - } + $(input).prop('checked', defaults === false ? input.defaultChecked : !!defaults); + } else { + $(input).val(defaults === false ? input.defaultValue : defaults); + } // TODO: Make this work for multiinput/selectize (or get rid of them) + $allShadowingFields.each(updateShadows); + }).each(syncCheckbox); + window.addEventListener('unload', function() { + $('.multilist').multiselect('refresh'); }); }); diff --git a/modules-available/locations/baseconfig/getconfig.inc.php b/modules-available/locations/baseconfig/getconfig.inc.php index f21503f1..26e43ed8 100644 --- a/modules-available/locations/baseconfig/getconfig.inc.php +++ b/modules-available/locations/baseconfig/getconfig.inc.php @@ -2,7 +2,9 @@ // Location handling: figure out location $locationId = false; -if (Request::any('force', 0, 'int') === 1 && Request::any('module', false, 'string') === 'locations') { +if (BaseConfig::hasOverride('locationid')) { + $locationId = BaseConfig::getOverride('locationid'); +} elseif (Request::any('force', 0, 'int') === 1 && Request::any('module', false, 'string') === 'locations') { // Force location for testing, but require logged in admin if (User::load()) { $locationId = Request::any('value', 0, 'int'); @@ -10,6 +12,8 @@ if (Request::any('force', 0, 'int') === 1 && Request::any('module', false, 'stri } if ($locationId === false) { + if (!$ip) // Required at this point, bail out if not given + return; $locationId = Location::getFromIpAndUuid($ip, $uuid); } @@ -23,19 +27,30 @@ if ($locationId !== false) { // Query location specific settings (from bottom to top) if (!empty($matchingLocations)) { // First get all settings for all locations we're in - $list = implode(',', $matchingLocations); - $res = Database::simpleQuery("SELECT locationid, setting, value FROM setting_location WHERE locationid IN ($list)"); + $res = Database::simpleQuery("SELECT locationid, setting, value, displayvalue + FROM setting_location WHERE locationid IN (:list)", + ['list' => $matchingLocations]); $tmp = array(); while ($row = $res->fetch(PDO::FETCH_ASSOC)) { - $tmp[(int)$row['locationid']][$row['setting']] = $row['value']; + $tmp[(int)$row['locationid']][$row['setting']] = $row; // Put whole row so we have value and displayvalue } + // Callback for pretty printing + $cb = function($id) { + if (substr($id, 0, 9) !== 'location-') + return ['name' => $id, 'locationid' => 0]; + $lid = (int)substr($id, 9); + return [ + 'name' => Location::getName($lid), + 'locationid' => $lid, + ]; + }; // $matchingLocations contains the location ids sorted from closest to furthest, so we use it to make sure the order // in which they override is correct (closest setting wins, e.g. room setting beats department setting) $prio = count($matchingLocations) + 1; foreach ($matchingLocations as $lid) { if (!isset($tmp[$lid])) continue; - ConfigHolder::setContext('location-' . $lid); + ConfigHolder::setContext('location-' . $lid, $cb); foreach ($tmp[$lid] as $setting => $value) { ConfigHolder::add($setting, $value, $prio); } diff --git a/modules-available/locations/baseconfig/hook.json b/modules-available/locations/baseconfig/hook.json index 1d69647e..fabb4686 100644 --- a/modules-available/locations/baseconfig/hook.json +++ b/modules-available/locations/baseconfig/hook.json @@ -3,5 +3,5 @@ "field": "locationid", "locationResolver": "LocationHooks::baseconfigLocationResolver", "tostring": "Location::getName", - "getfallback": "LocationHooks::getBaseconfigParent" + "getInheritance": "LocationHooks::baseconfigInheritance" } \ No newline at end of file diff --git a/modules-available/locations/inc/locationhooks.inc.php b/modules-available/locations/inc/locationhooks.inc.php index c15c34ab..5ce3bbfe 100644 --- a/modules-available/locations/inc/locationhooks.inc.php +++ b/modules-available/locations/inc/locationhooks.inc.php @@ -4,28 +4,26 @@ class LocationHooks { /** - * Used for baseconfig hook - * @param $locationId - * @return bool|array ('value' => x, 'display' => y), false if no parent or unknown id + * Resolve baseconfig id to locationid -- noop in this case */ - public static function getBaseconfigParent($locationId) + public static function baseconfigLocationResolver($id) { - $locationId = (int)$locationId; - $assoc = Location::getLocationsAssoc(); - if (!isset($assoc[$locationId])) - return false; - $locationId = (int)$assoc[$locationId]['parentlocationid']; - if (!isset($assoc[$locationId])) - return false; - return array('value' => $locationId, 'display' => $assoc[$locationId]['locationname']); + return $id; } /** - * Resolve baseconfig id to locationid -- noop in this case + * Hook to get inheritance tree for all config vars + * @param int $id Locationid currently being edited */ - public static function baseconfigLocationResolver($id) + public static function baseconfigInheritance($id) { - return $id; + $locs = Location::getLocationsAssoc(); + if ($locs === false || !isset($locs[$id])) + return []; + BaseConfig::prepareWithOverrides([ + 'locationid' => $locs[$id]['parentlocationid'] + ]); + return ConfigHolder::getRecursiveConfig(true); } } \ No newline at end of file diff --git a/modules-available/statistics/baseconfig/getconfig.inc.php b/modules-available/statistics/baseconfig/getconfig.inc.php index ea351d15..053827db 100644 --- a/modules-available/statistics/baseconfig/getconfig.inc.php +++ b/modules-available/statistics/baseconfig/getconfig.inc.php @@ -8,6 +8,9 @@ if (Request::any('force', 0, 'int') === 1 && Request::any('module', false, 'stri } } +if (!$uuid) // Required at this point, bail out if not given + return; + // Query machine specific settings $res = Database::simpleQuery("SELECT setting, value FROM setting_machine WHERE machineuuid = :uuid", ['uuid' => $uuid]); while ($row = $res->fetch(PDO::FETCH_ASSOC)) { diff --git a/modules-available/statistics/baseconfig/hook.json b/modules-available/statistics/baseconfig/hook.json index da28ad5d..4a406653 100644 --- a/modules-available/statistics/baseconfig/hook.json +++ b/modules-available/statistics/baseconfig/hook.json @@ -3,5 +3,5 @@ "field": "machineuuid", "locationResolver": "StatisticsHooks::baseconfigLocationResolver", "tostring": "StatisticsHooks::getBaseconfigName", - "getfallback": "StatisticsHooks::getBaseconfigParent" + "getInheritance": "StatisticsHooks::baseconfigInheritance" } \ No newline at end of file diff --git a/modules-available/statistics/inc/statisticshooks.inc.php b/modules-available/statistics/inc/statisticshooks.inc.php index ead4917b..746bdabf 100644 --- a/modules-available/statistics/inc/statisticshooks.inc.php +++ b/modules-available/statistics/inc/statisticshooks.inc.php @@ -21,11 +21,6 @@ class StatisticsHooks return self::$row['hostname'] ? self::$row['hostname'] : self::$row['clientip']; } - public static function getBaseconfigParent($machineuuid) - { - return false; // TODO - } - public static function baseconfigLocationResolver($machineuuid) { self::getRow($machineuuid); @@ -34,4 +29,19 @@ class StatisticsHooks return (int)self::$row['locationid']; } + /** + * Hook to get inheritance tree for all config vars + * @param int $machineuuid MachineUUID currently being edited + */ + public static function baseconfigInheritance($machineuuid) + { + self::getRow($machineuuid); + if (self::$row === false) + return []; + BaseConfig::prepareWithOverrides([ + 'locationid' => self::$row['locationid'] + ]); + return ConfigHolder::getRecursiveConfig(true); + } + } \ No newline at end of file -- cgit v1.2.3-55-g7522