From a8d23f91f6cfd803be1ecaae4c8d1b5e1268a699 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Fri, 18 Jul 2025 16:35:46 +0200 Subject: [locationinfo] Parametrize panel type configuration Avoids a lot of copy and paste and duplicate work in php and html part, for example explicitly handling every config variable for a specific panel when displaying the config dialog, when saving the config, and when loading the config for displaying the panel. This also parametrizes enums, limits and ranges, so dropdowns can be rendered automatically, validity of selected option can be checked, and putting numeric settings into bounds all happens generically. Edit dialog for DEFAULT panel is still completely custom, as it has too much special sauce going on with the room config overrides. URL-panel is half-half, but SUMMARY and UPCOMING are entirely generic now. --- modules-available/locationinfo/page.inc.php | 258 ++++++++-------------------- 1 file changed, 69 insertions(+), 189 deletions(-) (limited to 'modules-available/locationinfo/page.inc.php') diff --git a/modules-available/locationinfo/page.inc.php b/modules-available/locationinfo/page.inc.php index 538f2514..a6d56e5a 100644 --- a/modules-available/locationinfo/page.inc.php +++ b/modules-available/locationinfo/page.inc.php @@ -248,8 +248,6 @@ class Page_LocationInfo extends Page $params = $this->preparePanelConfigUrl(); break; case 'SUMMARY': - $params = $this->preparePanelConfigSummary(); - break; case 'UPCOMING': $params = [ 'config' => LocationInfo::panelConfigFromPost($paneltype), @@ -295,52 +293,29 @@ class Page_LocationInfo extends Page if (count($locationids) > 4) { $locationids = array_slice($locationids, 0, 4); } - // Build struct from POST - $conf = array( - 'language' => Request::post('language', 'en', 'string'), - 'mode' => Request::post('mode', 1, 'int'), - 'vertical' => Request::post('vertical', false, 'bool'), - 'eco' => Request::post('eco', false, 'bool'), - 'prettytime' => Request::post('prettytime', false, 'bool'), - 'roomplanner' => Request::post('roomplanner', true, 'bool'), - 'startday' => Request::post('startday', 0, 'int'), - 'scaledaysauto' => Request::post('scaledaysauto', false, 'bool'), - 'daystoshow' => Request::post('daystoshow', 7, 'int'), - 'rotation' => Request::post('rotation', 0, 'int'), - 'scale' => Request::post('scale', 50, 'int'), - 'switchtime' => Request::post('switchtime', 20, 'int'), - 'calupdate' => Request::post('calupdate', 120, 'int'), - 'roomupdate' => Request::post('roomupdate', 30, 'int'), - 'hostname' => Request::post('hostname', false, 'bool'), - ); - if ($conf['roomupdate'] < 15) { - $conf['roomupdate'] = 15; - } - if ($conf['calupdate'] < 30) { - $conf['calupdate'] = 30; - } + $conf = LocationInfo::panelConfigFromPost('DEFAULT'); - $overrides = array(); - for ($i = 0; $i < sizeof($locationids); $i++) { - $overrideLoc = Request::post('override'.$locationids[$i], false, 'bool'); + $overrides = []; + foreach ($locationids as $lid) { + $overrideLoc = Request::post('override'.$lid, false, 'bool'); if ($overrideLoc) { $overrideArray = array( - 'mode' => Request::post('override'.$locationids[$i].'mode', 1, 'int'), - 'roomplanner' => Request::post('override'.$locationids[$i].'roomplanner', false, 'bool'), - 'vertical' => Request::post('override'.$locationids[$i].'vertical', false, 'bool'), - 'startday' => Request::post('override'.$locationids[$i].'startday', 0, 'int'), - 'scaledaysauto' => Request::post('override'.$locationids[$i].'scaledaysauto', false, 'bool'), - 'daystoshow' => Request::post('override'.$locationids[$i].'daystoshow', 7, 'int'), - 'rotation' => Request::post('override'.$locationids[$i].'rotation', 0, 'int'), - 'scale' => Request::post('override'.$locationids[$i].'scale', 50, 'int'), - 'switchtime' => Request::post('override'.$locationids[$i].'switchtime', 60, 'int'), + 'mode' => Request::post('override'.$lid.'mode', 1, 'int'), + 'roomplanner' => Request::post('override'.$lid.'roomplanner', false, 'bool'), + 'vertical' => Request::post('override'.$lid.'vertical', false, 'bool'), + 'startday' => Request::post('override'.$lid.'startday', 0, 'int'), + 'scaledaysauto' => Request::post('override'.$lid.'scaledaysauto', false, 'bool'), + 'daystoshow' => Request::post('override'.$lid.'daystoshow', 7, 'int'), + 'rotation' => Request::post('override'.$lid.'rotation', 0, 'int'), + 'scale' => Request::post('override'.$lid.'scale', 50, 'int'), + 'switchtime' => Request::post('override'.$lid.'switchtime', 60, 'int'), ); - $overrides[$locationids[$i]] = $overrideArray; + $overrides[$lid] = $overrideArray; } } $conf['overrides'] = $overrides; - return array('config' => $conf, 'locationids' => $locationids); + return ['config' => $conf, 'locationids' => $locationids]; } /** @@ -352,56 +327,17 @@ class Page_LocationInfo extends Page $bookmarkUrls = Request::post('bookmarkUrls', [], 'array'); $bookmarkString = ''; for ($i = 0; $i < count($bookmarkNames); $i++) { - if ($bookmarkNames[$i] == '' || $bookmarkUrls[$i] == '') continue; - $bookmarkString .= rawurlencode($bookmarkNames[$i]); - $bookmarkString .= ","; - $bookmarkString .= rawurlencode($bookmarkUrls[$i]); - $bookmarkString .= " "; - } - $bookmarkString = substr($bookmarkString, 0, -1); - - $rotation = strtolower(Request::post('screen-rotation', '', 'string')); - if (!in_array($rotation, ['', 'left', 'right', 'inverted'])) { - $rotation = ''; - } - - $conf = array( - 'url' => Request::post('url', 'https://www.bwlehrpool.de/', 'string'), - 'insecure-ssl' => Request::post('insecure-ssl', 0, 'int'), - 'reload-minutes' => max(0, Request::post('reloadminutes', 0, 'int')), - 'whitelist' => preg_replace("/[\r\n]+/m", "\n", Request::post('whitelist', '', 'string')), - 'blacklist' => preg_replace("/[\r\n]+/m", "\n", Request::post('blacklist', '', 'string')), - 'split-login' => Request::post('split-login', 0, 'bool'), - 'browser' => Request::post('browser', 'firefox', 'string'), - 'interactive' => Request::post('interactive', '0', 'bool'), - 'hw-video' => Request::post('hw-video', '0', 'bool'), - 'bookmarks' => $bookmarkString ?: '', - 'allow-tty' => Request::post('allow-tty', '', 'string'), - 'zoom-factor' => max(0, Request::post('zoom-factor', 100, 'int')), - 'language' => str_replace(['_', ' '], ['-', ''], Request::post('language', '', 'string')), - 'screen-rotation' => $rotation, - ); - return array('config' => $conf, 'locationids' => []); - } - - /** - * @return array{config: array, locationids: array} - */ - private function preparePanelConfigSummary(): array - { - // Build json structure - $conf = array( - 'language' => Request::post('language', 'en', 'string'), - 'eco' => Request::post('eco', false, 'bool'), - 'roomplanner' => Request::post('roomplanner', false, 'bool'), - 'panelupdate' => Request::post('panelupdate', 30, 'int') - ); - if ($conf['panelupdate'] < 15) { - $conf['panelupdate'] = 15; + if (empty($bookmarkNames[$i]) || empty($bookmarkUrls[$i])) + continue; + $bookmarkString .= rawurlencode($bookmarkNames[$i]) . ',' + . rawurlencode($bookmarkUrls[$i]) . ' '; } - // Check locations - $locationids = self::getLocationIdsFromRequest(); - return array('config' => $conf, 'locationids' => $locationids); + $bookmarkString = trim($bookmarkString); + + $conf = LocationInfo::panelConfigFromPost('URL'); + $conf['bookmarks'] = $bookmarkString; + $conf['accept-language'] = str_replace(['_', ' '], ['-', ''], $conf['accept-language']); + return ['config' => $conf, 'locationids' => []]; } /** @@ -910,9 +846,6 @@ class Page_LocationInfo extends Page $array[$day][] = array($s, $e); } - /** - * Ajax the config of a panel. - */ private function showPanelConfig(): void { $id = Request::get('uuid', false, 'string'); @@ -953,43 +886,24 @@ class Page_LocationInfo extends Page } $config['panelname'] = $panel['panelname']; - $langs = Dictionary::getLanguages(true); - if (isset($config['language'])) { - foreach ($langs as &$lang) { - if ($lang['cc'] === $config['language']) { - $lang['selected'] = 'selected'; - } - } - } + $configData = LocationInfo::getEditTemplateData($panel['paneltype'], $config); + LocationInfo::makeCheckedProperties($panel['paneltype'], $config); if ($panel['paneltype'] === 'DEFAULT') { - Render::addTemplate('page-config-panel-default', array( + // The override part is unfortunately too specialized to use the LocationInfo::getEditTemplateData() + // helper, so we keep using our specialized template + Render::addTemplate('page-config-panel-default', [ 'new' => $id === 'new', 'uuid' => $id, 'panelname' => $panel['panelname'] ?? '', - 'languages' => $langs, - 'mode' => $config['mode'], - 'vertical_checked' => $config['vertical'] ? 'checked' : '', - 'eco_checked' => $config['eco'] ? 'checked' : '', - 'prettytime_checked' => $config['prettytime'] ? 'checked' : '', - 'roomplanner' => $config['roomplanner'], - 'startday' => $config['startday'], - 'scaledaysauto_checked' => $config['scaledaysauto'] ? 'checked' : '', - 'daystoshow' => $config['daystoshow'], - 'rotation' => $config['rotation'], - 'scale' => $config['scale'], - 'switchtime' => $config['switchtime'], - 'calupdate' => $config['calupdate'], - 'roomupdate' => $config['roomupdate'], 'locations' => Location::getLocations(), 'locationids' => $panel['locationids'] ?? '', 'overrides' => json_encode($config['overrides']), - 'hostname_checked' => $config['hostname'] ? 'checked' : '', - )); + ] + $config); } elseif ($panel['paneltype'] === 'URL') { - + // Bookmarks are handled differently $bookmarksArray = []; - if ($config['bookmarks'] !== '') { + if (!empty($config['bookmarks'])) { $bookmarksConfig = explode(' ', $config['bookmarks']); foreach ($bookmarksConfig AS $bookmark) { $bookmark = explode(',', $bookmark); @@ -1001,50 +915,26 @@ class Page_LocationInfo extends Page ]; } } - + unset($config['bookmarks']); + // URL filtering also has a custom style that can't be handled generically LocationInfo::cleanupUrlFilter($config); - Render::addTemplate('page-config-panel-url', array( 'new' => $id === 'new', 'uuid' => $id, - 'panelname' => $panel['panelname'] ?? '', - 'url' => $config['url'], - 'zoom-factor' => $config['zoom-factor'], - 'language' => $config['language'], - 'screen-rotation' => $config['screen-rotation'], - 'ssl_checked' => $config['insecure-ssl'] ? 'checked' : '', - 'reloadminutes' => (int)$config['reload-minutes'], - 'whitelist' => str_replace("\n", "\r\n", $config['whitelist']), - 'blacklist' => str_replace("\n", "\r\n", $config['blacklist']), - 'split-login_checked' => $config['split-login'] ? 'checked' : '', - 'browser' => $config['browser'], - 'interactive_checked' => $config['interactive'] ? 'checked' : '', - 'hwvideo_checked' => $config['hw-video'] ? 'checked' : '', + 'sections' => $configData, 'bookmarks' => $bookmarksArray, - 'allow-tty_' . $config['allow-tty'] . '_checked' => 'checked', + 'whitelist' => $config['whitelist'], + 'blacklist' => $config['blacklist'], )); - } elseif ($panel['paneltype'] === 'UPCOMING') { - $configData = LocationInfo::getEditTemplateData($panel['paneltype'], $config); - LocationInfo::makeCheckedProperties($panel['paneltype'], $config); - Render::addTemplate('page-config-panel-upcoming', array( + } else { + // Use generic edit template + Render::addTemplate('page-config-panel-generic', array( 'new' => $id === 'new', 'uuid' => $id, 'sections' => $configData, - 'locationtree' => Render::parse('fragment-locationtree', [ - 'locations' => Location::getLocations(explode(',', $panel['locationids'] ?? '')), - ]), - )); - } elseif ($panel['paneltype'] === 'SUMMARY') { - Render::addTemplate('page-config-panel-summary', array( - 'new' => $id === 'new', - 'uuid' => $id, - 'panelname' => $panel['panelname'] ?? '', - 'languages' => $langs, - 'panelupdate' => $config['panelupdate'], - 'roomplanner' => $config['roomplanner'], - 'locations' => Location::getLocations(), - 'locationids' => $panel['locationids'] ?? '', - 'eco_checked' => $config['eco'] ? 'checked' : '', + 'paneltype' => $panel['paneltype'], + 'heading-hint' => Dictionary::translateFile('panel-params', 'intro-' . $panel['paneltype']), + 'locations' => Location::getLocations(explode(',', $panel['locationids'] ?? '')), )); } } @@ -1062,27 +952,35 @@ class Page_LocationInfo extends Page http_response_code(404); die('Panel with given uuid not found'); } - - if ($type === 'URL') { + if ($type === 'URL') { // Shortcut - URL panel is just a redirect Util::redirect($config['url']); } - $data = []; + // Figure out if the panel is being accessed directly, or via the pretty rewrite preg_match('#^/(.*)/#', $_SERVER['PHP_SELF'], $script); preg_match('#^/([^?]+)/#', $_SERVER['REQUEST_URI'], $request); if ($script[1] !== $request[1]) { - // Working with server-side redirects - $data['api'] = 'api/'; + // Working with server-side rewrites + $config['api'] = 'api/'; } else { // 1:1 - $data['api'] = 'api.php?do=locationinfo&'; + $config['api'] = 'api.php?do=locationinfo&'; + } + + // Check if we have a customized template, build filename + $templateFile = 'frontend-' . strtolower($type); + if (!empty($config['mod']) && preg_match('#^[a-z0-9]+$#', $config['mod']) + && file_exists('modules/locationinfo/templates/' . $templateFile . '-' . $config['mod'] . '.html')) { + $templateFile .= '-' . $config['mod']; } $lang = $config['language'] ?? 'en'; $reqLang = Request::get('forcelang', false, 'string'); if ($reqLang !== false && Dictionary::hasLanguage($reqLang)) { + // Language overridden by parameter? $lang = $reqLang; } elseif ($config['language-system'] ?? false) { + // Language overridden by client's browser headers? $langs = preg_split('/[,\s]+/', $_SERVER['HTTP_ACCEPT_LANGUAGE']); foreach ($langs as $check) { $check = substr($check, 0, 2); @@ -1092,46 +990,28 @@ class Page_LocationInfo extends Page } } } - unset($config['language']); - unset($config['language-system']); + unset($config['language'], $config['language-system']); + $config['uuid'] = $uuid; + $config['language'] = $lang; + if ($type === 'SUMMARY') { $locations = LocationInfo::getLocationsOr404($uuid, false); $config['tree'] = Location::getTree(...$locations); - } - $data += array( - 'uuid' => $uuid, - 'config' => json_encode($config), - 'language' => $lang, - ) + $config; - - if ($type === 'DEFAULT') { - die(Render::parse('frontend-default', $data, null, $lang)); - } - - if ($type === 'UPCOMING') { - $mod = ''; - if (!empty($config['mod']) && preg_match('#^[a-z0-9]+$#', $config['mod']) && file_exists('modules/locationinfo/templates/frontend-upcoming-' . $config['mod'] . '.html')) { - $mod = '-' . $config['mod']; - } + } elseif ($type === 'UPCOMING') { $bg = $this->parseCssColor($config['color_bg'] ?? '#000'); if ($bg !== null) { - $data['color_grad1'] = 'rgba(' . $bg[0] . ',' . $bg[1] . ',' . $bg[2] . ', 0)'; - $data['color_grad2'] = 'rgba(' . $bg[0] . ',' . $bg[1] . ',' . $bg[2] . ', .1)'; - $data['color_grad3'] = 'rgba(' . $bg[0] . ',' . $bg[1] . ',' . $bg[2] . ', .9)'; + $config['color_grad1'] = 'rgba(' . $bg[0] . ',' . $bg[1] . ',' . $bg[2] . ', 0)'; + $config['color_grad2'] = 'rgba(' . $bg[0] . ',' . $bg[1] . ',' . $bg[2] . ', .1)'; + $config['color_grad3'] = 'rgba(' . $bg[0] . ',' . $bg[1] . ',' . $bg[2] . ', .9)'; } $fg = $this->parseCssColor($config['color_fg'] ?? '#fff'); if ($fg !== null) { - $data['color_half'] = 'rgba(' . $fg[0] . ',' . $fg[1] . ',' . $fg[2] . ', .5)'; + $config['color_half'] = 'rgba(' . $fg[0] . ',' . $fg[1] . ',' . $fg[2] . ', .5)'; } - die(Render::parse('frontend-upcoming' . $mod, $data, null, $lang)); - } - - if ($type === 'SUMMARY') { - die(Render::parse('frontend-summary', $data, null, $lang)); } - http_response_code(500); - die('Unknown panel type ' . $type); + $config['config'] = json_encode($config); // Must be last, obviously + die(Render::parse($templateFile, $config, null, $lang)); } /** -- cgit v1.2.3-55-g7522