diff options
author | Simon Rettberg | 2023-11-14 14:47:55 +0100 |
---|---|---|
committer | Simon Rettberg | 2023-11-14 14:47:55 +0100 |
commit | 06bff0b9b84d47c43f9bc8aff06a29d85ebb7ed0 (patch) | |
tree | 7e5493b102074672d8cfd8fe1a61e49f080edbe8 | |
parent | Update phpstorm config (diff) | |
download | slx-admin-06bff0b9b84d47c43f9bc8aff06a29d85ebb7ed0.tar.gz slx-admin-06bff0b9b84d47c43f9bc8aff06a29d85ebb7ed0.tar.xz slx-admin-06bff0b9b84d47c43f9bc8aff06a29d85ebb7ed0.zip |
Add function param/return types, fix a lot more phpstorm complaints
182 files changed, 1958 insertions, 2108 deletions
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index cb285b8f..953381a3 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -243,7 +243,7 @@ <inspection_tool class="PhpArrayKeyDoesNotMatchArrayShapeInspection" enabled="true" level="WARNING" enabled_by_default="true" editorAttributes="WARNING_ATTRIBUTES" /> <inspection_tool class="PhpArrayMapCanBeConvertedToLoopInspection" enabled="false" level="WARNING" enabled_by_default="false" editorAttributes="WARNING_ATTRIBUTES" /> <inspection_tool class="PhpArrayModificationWillNotHaveEffectInspection" enabled="true" level="WARNING" enabled_by_default="true" editorAttributes="WARNING_ATTRIBUTES" /> - <inspection_tool class="PhpArrayPushWithOneElementInspection" enabled="true" level="WARNING" enabled_by_default="true" editorAttributes="WARNING_ATTRIBUTES" /> + <inspection_tool class="PhpArrayPushWithOneElementInspection" enabled="false" level="WARNING" enabled_by_default="false" editorAttributes="WARNING_ATTRIBUTES" /> <inspection_tool class="PhpArraySearchInBooleanContextInspection" enabled="true" level="WARNING" enabled_by_default="true" editorAttributes="WARNING_ATTRIBUTES" /> <inspection_tool class="PhpArrayShapeCanBeAddedInspection" enabled="true" level="WARNING" enabled_by_default="true" editorAttributes="WARNING_ATTRIBUTES" /> <inspection_tool class="PhpArrayTraversableCanBeReplacedWithIterableInspection" enabled="true" level="WARNING" enabled_by_default="true" editorAttributes="WARNING_ATTRIBUTES" /> diff --git a/Mustache/Compiler.php b/Mustache/Compiler.php index 2b0d1f93..fd93741a 100644 --- a/Mustache/Compiler.php +++ b/Mustache/Compiler.php @@ -96,7 +96,7 @@ class Mustache_Compiler $code .= $this->section( $node[Mustache_Tokenizer::NODES], $node[Mustache_Tokenizer::NAME], - isset($node[Mustache_Tokenizer::FILTERS]) ? $node[Mustache_Tokenizer::FILTERS] : array(), + $node[Mustache_Tokenizer::FILTERS] ?? array(), $node[Mustache_Tokenizer::INDEX], $node[Mustache_Tokenizer::END], $node[Mustache_Tokenizer::OTAG], @@ -109,7 +109,7 @@ class Mustache_Compiler $code .= $this->invertedSection( $node[Mustache_Tokenizer::NODES], $node[Mustache_Tokenizer::NAME], - isset($node[Mustache_Tokenizer::FILTERS]) ? $node[Mustache_Tokenizer::FILTERS] : array(), + $node[Mustache_Tokenizer::FILTERS] ?? array(), $level ); break; @@ -117,8 +117,8 @@ class Mustache_Compiler case Mustache_Tokenizer::T_PARTIAL: $code .= $this->partial( $node[Mustache_Tokenizer::NAME], - isset($node[Mustache_Tokenizer::DYNAMIC]) ? $node[Mustache_Tokenizer::DYNAMIC] : false, - isset($node[Mustache_Tokenizer::INDENT]) ? $node[Mustache_Tokenizer::INDENT] : '', + $node[Mustache_Tokenizer::DYNAMIC] ?? false, + $node[Mustache_Tokenizer::INDENT] ?? '', $level ); break; @@ -126,8 +126,8 @@ class Mustache_Compiler case Mustache_Tokenizer::T_PARENT: $code .= $this->parent( $node[Mustache_Tokenizer::NAME], - isset($node[Mustache_Tokenizer::DYNAMIC]) ? $node[Mustache_Tokenizer::DYNAMIC] : false, - isset($node[Mustache_Tokenizer::INDENT]) ? $node[Mustache_Tokenizer::INDENT] : '', + $node[Mustache_Tokenizer::DYNAMIC] ?? false, + $node[Mustache_Tokenizer::INDENT] ?? '', $node[Mustache_Tokenizer::NODES], $level ); @@ -165,7 +165,7 @@ class Mustache_Compiler case Mustache_Tokenizer::T_UNESCAPED_2: $code .= $this->variable( $node[Mustache_Tokenizer::NAME], - isset($node[Mustache_Tokenizer::FILTERS]) ? $node[Mustache_Tokenizer::FILTERS] : array(), + $node[Mustache_Tokenizer::FILTERS] ?? array(), $node[Mustache_Tokenizer::TYPE] === Mustache_Tokenizer::T_ESCAPED, $level ); diff --git a/Mustache/Engine.php b/Mustache/Engine.php index 7a31ac03..0ac2a738 100644 --- a/Mustache/Engine.php +++ b/Mustache/Engine.php @@ -689,6 +689,7 @@ class Mustache_Engine array('name' => $e->getTemplateName()) ); } + return null; } /** diff --git a/Mustache/Parser.php b/Mustache/Parser.php index 5db58244..e5523b24 100644 --- a/Mustache/Parser.php +++ b/Mustache/Parser.php @@ -222,7 +222,7 @@ class Mustache_Parser { if ($this->lineTokens > 1) { // this is the third or later node on this line, so it can't be standalone - return; + return null; } $prev = null; @@ -231,7 +231,7 @@ class Mustache_Parser // unless the previous node is whitespace. if ($prev = end($nodes)) { if (!$this->tokenIsWhitespace($prev)) { - return; + return null; } } } @@ -239,19 +239,19 @@ class Mustache_Parser if ($next = reset($tokens)) { // If we're on a new line, bail. if ($next[Mustache_Tokenizer::LINE] !== $this->lineNum) { - return; + return null; } // If the next token isn't whitespace, bail. if (!$this->tokenIsWhitespace($next)) { - return; + return null; } if (count($tokens) !== 1) { // Unless it's the last token in the template, the next token // must end in newline for this to be standalone. if (substr($next[Mustache_Tokenizer::VALUE], -1) !== "\n") { - return; + return null; } } @@ -263,6 +263,7 @@ class Mustache_Parser // Return the whitespace prefix, if any return array_pop($nodes); } + return null; } /** @@ -23,7 +23,7 @@ spl_autoload_register(function ($class) { require_once $file; }); -function isLocalExecution() +function isLocalExecution(): bool { return !isset($_SERVER['REMOTE_ADDR']) || $_SERVER['REMOTE_ADDR'] === '127.0.0.1'; } diff --git a/apis/cron.inc.php b/apis/cron.inc.php index 0b1e92a9..03b6201f 100644 --- a/apis/cron.inc.php +++ b/apis/cron.inc.php @@ -14,7 +14,7 @@ define('CRON_KEY_STATUS', 'cron.key.status'); define('CRON_KEY_BLOCKED', 'cron.key.blocked'); // Crash report mode - used by system crontab entry -if (($report = Request::get('crashreport', false, 'string'))) { +if (($report = Request::get('crashreport', false, 'string')) !== false) { $list = Property::getList(CRON_KEY_STATUS); if (empty($list)) { error_log('Cron crash report triggered but no cronjob marked active.'); @@ -62,10 +62,7 @@ function getJobStatus($id) } // Hooks by other modules -/** - * @param Hook $hook - */ -function handleModule($hook) +function handleModule(Hook $hook): void { global $cron_log_text; $cron_log_text = ''; diff --git a/inc/arrayutil.inc.php b/inc/arrayutil.inc.php index 9ce5730f..7aded4db 100644 --- a/inc/arrayutil.inc.php +++ b/inc/arrayutil.inc.php @@ -6,9 +6,6 @@ class ArrayUtil /** * Take an array of arrays, take given key from each sub-array and return * new array with just those corresponding values. - * @param array $list - * @param string $key - * @return array */ public static function flattenByKey(array $list, string $key): array { @@ -18,8 +15,6 @@ class ArrayUtil /** * Pass an array of arrays you want to merge. The keys of the outer array will become * the inner keys of the resulting array, and vice versa. - * @param array $arrays - * @return array */ public static function mergeByKey(array $arrays): array { @@ -38,11 +33,8 @@ class ArrayUtil /** * Sort array by given column. - * @param array $array - * @param string $column - * @return void */ - public static function sortByColumn(array &$array, string $column, int $sortOrder = SORT_ASC, int $sortFlags = SORT_REGULAR) + public static function sortByColumn(array &$array, string $column, int $sortOrder = SORT_ASC, int $sortFlags = SORT_REGULAR): void { $sorter = array_column($array, $column); array_multisort($sorter, $sortOrder, $sortFlags, $array); @@ -53,7 +45,6 @@ class ArrayUtil * * @param array $array An array * @param array $keyList A list of strings which must all be valid keys in $array - * @return boolean */ public static function hasAllKeys(array $array, array $keyList): bool { diff --git a/inc/crypto.inc.php b/inc/crypto.inc.php index d26a94ab..c82a5d82 100644 --- a/inc/crypto.inc.php +++ b/inc/crypto.inc.php @@ -10,8 +10,11 @@ class Crypto */ public static function hash6(string $password): string { + $bytes = Util::randomBytes(16); + if ($bytes === null) + ErrorHandler::traceError('Could not get random bytes'); $salt = substr(str_replace('+', '.', - base64_encode(Util::randomBytes(16))), 0, 16); + base64_encode($bytes)), 0, 16); $hash = crypt($password, '$6$' . $salt); if ($hash === null || strlen($hash) < 60) { ErrorHandler::traceError('Error hashing password using SHA-512'); diff --git a/inc/dashboard.inc.php b/inc/dashboard.inc.php index 0b0f69e3..716776d3 100644 --- a/inc/dashboard.inc.php +++ b/inc/dashboard.inc.php @@ -7,12 +7,12 @@ class Dashboard private static $subMenu = array(); private static $disabled = false; - public static function disable() + public static function disable(): void { self::$disabled = true; } - public static function createMenu() + public static function createMenu(): void { if (self::$disabled) return; @@ -22,7 +22,7 @@ class Dashboard if (isset($MENU_CAT_OVERRIDE)) { foreach ($MENU_CAT_OVERRIDE as $cat => $list) { foreach ($list as $mod) { - $modByCategory[$cat][$mod] = false; + $modByCategory[$cat][$mod] = null; $modById[$mod] =& $modByCategory[$cat][$mod]; } } @@ -30,10 +30,10 @@ class Dashboard $all = Module::getEnabled(true); foreach ($all as $module) { $cat = $module->getCategory(); - if ($cat === false) + if (empty($cat)) continue; $modId = $module->getIdentifier(); - if (isset($modById[$modId])) { + if (array_key_exists($modId, $modById)) { $modById[$modId] = $module; } else { $modByCategory[$cat][$modId] = $module; @@ -43,10 +43,10 @@ class Dashboard $categories = array(); foreach ($modByCategory as $catId => $modList) { $collapse = true; - /* @var Module[] $modList */ + /* @var (?Module)[] $modList */ $modules = array(); - foreach ($modList as $modId => $module) { - if ($module === false) + foreach ($modList as $module) { + if ($module === null) continue; // Was set in $MENU_CAT_OVERRIDE, but is not enabled $newEntry = array( 'displayName' => $module->getDisplayName(), @@ -62,28 +62,25 @@ class Dashboard } $modules[] = $newEntry; } - $categories[] = array( + $categories[] = [ 'icon' => self::getCategoryIcon($catId), 'displayName' => Dictionary::getCategoryName($catId), 'modules' => $modules, 'collapse' => $collapse, - ); + ]; } - Render::setDashboard(array( + Render::setDashboard([ 'categories' => $categories, 'url' => urlencode($_SERVER['REQUEST_URI']), 'langs' => Dictionary::getLanguages(true), 'user' => User::getName(), 'warning' => User::getName() !== false && User::hasPermission('.eventlog.*') && User::getLastSeenEvent() < Property::getLastWarningId(), 'needsSetup' => User::getName() !== false && Property::getNeedsSetup() - )); + ]); } - public static function getCategoryIcon($category) + public static function getCategoryIcon(string $category): string { - if ($category === false) { - return ''; - } if (!preg_match('/^(\w+)\.(.*)$/', $category, $out)) { error_log('Requested category icon for invalid category "' . $category . '"'); return ''; @@ -105,12 +102,12 @@ class Dashboard return 'glyphicon glyphicon-' . self::$iconCache[$module][$icon]; } - public static function addSubmenu($url, $name) + public static function addSubmenu(string $url, string $name): void { self::$subMenu[] = array('url' => $url, 'name' => $name); } - public static function getSubmenus() + public static function getSubmenus(): array { return self::$subMenu; } diff --git a/inc/database.inc.php b/inc/database.inc.php index 0c8f40ae..7805b508 100644 --- a/inc/database.inc.php +++ b/inc/database.inc.php @@ -12,8 +12,10 @@ class Database */ private static $dbh = false; - private static $returnErrors; - private static $lastError = false; + /** @var bool */ + private static $returnErrors = false; + /** @var ?string */ + private static $lastError = null; private static $explainList = array(); private static $queryCount = 0; /** @var float */ @@ -165,9 +167,9 @@ class Database } /** - * @return string|false return last error returned by query + * @return ?string return last error returned by query */ - public static function lastError() + public static function lastError(): ?string { return self::$lastError; } @@ -183,7 +185,7 @@ class Database public static function simpleQuery(string $query, array $args = [], bool $ignoreError = null) { self::init(); - if (CONFIG_DEBUG && !isset(self::$explainList[$query]) && preg_match('/^\s*SELECT/is', $query)) { + if (CONFIG_DEBUG && !isset(self::$explainList[$query]) && preg_match('/^\s*SELECT/i', $query)) { self::$explainList[$query] = [$args]; } // Support passing nested arrays for IN statements, automagically refactor @@ -225,7 +227,6 @@ class Database return false; ErrorHandler::traceError("Database Error: \n" . self::$lastError); } - return false; } public static function examineLoggedQueries() diff --git a/inc/dictionary.inc.php b/inc/dictionary.inc.php index 4c98c63b..ee613d0b 100644 --- a/inc/dictionary.inc.php +++ b/inc/dictionary.inc.php @@ -6,16 +6,15 @@ class Dictionary /** * @var string[] Array of languages, numeric index, two letter CC as values */ - private static $languages = false; + private static $languages = []; /** - * @var array Array of languages, numeric index, values are ['name' => 'Language Name', 'cc' => 'xx'] + * @var array{'name': string, 'cc': string}|null Long name of language, and CC */ - private static $languagesLong = false; - private static $stringCache = array(); + private static $languagesLong = null; + private static $stringCache = []; - public static function init() + public static function init(): void { - self::$languages = array(); foreach (glob('lang/??', GLOB_ONLYDIR) as $lang) { if (!file_exists($lang . '/name.txt') && !file_exists($lang . '/flag.png')) continue; @@ -93,25 +92,25 @@ class Dictionary * * @param string $module Module name * @param string $file Dictionary name - * @param string|false $lang Language CC, false === current language + * @param ?string $lang Language CC, false === current language * @return array assoc array mapping language tags to the translated strings */ - public static function getArray($module, $file, $lang = false) + public static function getArray(string $module, string $file, ?string $lang = null): array { - if ($lang === false) + if ($lang === null) $lang = LANG; $path = Util::safePath("modules/{$module}/lang/{$lang}/{$file}.json"); if (isset(self::$stringCache[$path])) return self::$stringCache[$path]; if (!file_exists($path)) - return array(); + return []; $content = file_get_contents($path); if ($content === false) { // File does not exist for language $content = '[]'; } $json = json_decode($content, true); if (!is_array($json)) { - $json = array(); + $json = []; } return self::$stringCache[$path] = $json; } @@ -126,7 +125,7 @@ class Dictionary * @param bool $returnTagOnMissing If true, the tag name enclosed in {{}} will be returned if the tag does not exist * @return string|false The requested tag's translation, or false if not found and $returnTagOnMissing === false */ - public static function translateFileModule($moduleId, $file, $tag, $returnTagOnMissing = false) + public static function translateFileModule(string $moduleId, string $file, string $tag, bool $returnTagOnMissing = true) { $strings = self::getArray($moduleId, $file); if (!isset($strings[$tag])) { @@ -146,7 +145,7 @@ class Dictionary * @param bool $returnTagOnMissing If true, the tag name enclosed in {{}} will be returned if the tag does not exist * @return string|false The requested tag's translation, or false if not found and $returnTagOnMissing === false */ - public static function translateFile($file, $tag, $returnTagOnMissing = false) + public static function translateFile(string $file, string $tag, bool $returnTagOnMissing = true) { if (!class_exists('Page') || Page::getModule() === false) return false; // We have no page - return false for now, as we're most likely running in api or install mode @@ -160,9 +159,9 @@ class Dictionary * @param bool $returnTagOnMissing If true, the tag name enclosed in {{}} will be returned if the tag does not exist * @return string|false The requested tag's translation, or false if not found and $returnTagOnMissing === false */ - public static function translate($tag, $returnTagOnMissing = false) + public static function translate(string $tag, bool $returnTagOnMissing = true) { - $string = self::translateFile('module', $tag); + $string = self::translateFile('module', $tag, false); if ($string !== false) return $string; $string = self::translateFileModule('main', 'global-tags', $tag); @@ -176,9 +175,8 @@ class Dictionary * * @param string $module Module the message belongs to * @param string $id Message id - * @return string|false */ - public static function getMessage($module, $id) + public static function getMessage(string $module, string $id): string { $string = self::translateFileModule($module, 'messages', $id); if ($string === false) { @@ -190,19 +188,18 @@ class Dictionary /** * Get translation of the given category. * - * @param string $category + * @param string $category Menu category to get localized name for * @return string Category name, or some generic fallback to the given category id */ - public static function getCategoryName($category) + public static function getCategoryName(string $category): string { - if ($category === false) { - return 'No Category'; - } - if (!preg_match('/^(\w+)\.(.*)$/', $category, $out)) { - return 'Invalid Category ID format: ' . $category; + if (!empty($category)) { + if (!preg_match('/^(\w+)\.(.*)$/', $category, $out)) { + return 'Invalid Category ID format: ' . $category; + } + $string = self::translateFileModule($out[1], 'categories', $out[2]); } - $string = self::translateFileModule($out[1], 'categories', $out[2]); - if ($string === false) { + if (empty($category) || $string === false) { return "!!{$category}!!"; } return $string; @@ -215,12 +212,12 @@ class Dictionary * false = regular array containing only the ccs * @return array List of languages */ - public static function getLanguages($withName = false) + public static function getLanguages(bool $withName = false): ?array { if (!$withName) return self::$languages; - if (self::$languagesLong === false) { - self::$languagesLong = array(); + if (self::$languagesLong === null) { + self::$languagesLong = []; foreach (self::$languages as $lang) { if (file_exists("lang/$lang/name.txt")) { $name = file_get_contents("lang/$lang/name.txt"); @@ -230,10 +227,10 @@ class Dictionary if (!isset($name) || $name === false) { $name = $lang; } - self::$languagesLong[] = array( + self::$languagesLong[] = [ 'cc' => $lang, - 'name' => $name - ); + 'name' => $name, + ]; } } return self::$languagesLong; @@ -242,11 +239,8 @@ class Dictionary /** * Get name of language matching given language CC. * Default to the CC if the language isn't known. - * - * @param string $langCC - * @return string */ - public static function getLanguageName($langCC) + public static function getLanguageName(string $langCC): string { if (file_exists("lang/$langCC/name.txt")) { $name = file_get_contents("lang/$langCC/name.txt"); @@ -264,12 +258,12 @@ class Dictionary * to the image, otherwise, it is just added as the title attribute. * * @param $caption bool with caption next to <img> - * @param $langCC string Language cc to get flag code for - defaults to current language + * @param $langCC ?string Language cc to get flag code for - defaults to current language * @return string html code of img tag for language */ - public static function getFlagHtml($caption = false, $langCC = false) + public static function getFlagHtml(bool $caption = false, string $langCC = null): string { - if ($langCC === false) { + if ($langCC === null) { $langCC = LANG; } $flag = "lang/$langCC/flag.png"; diff --git a/inc/download.inc.php b/inc/download.inc.php index 10eac188..49ebbfbc 100644 --- a/inc/download.inc.php +++ b/inc/download.inc.php @@ -24,7 +24,6 @@ class Download curl_setopt(self::$curlHandle, CURLOPT_TIMEOUT, $timeout); curl_setopt(self::$curlHandle, CURLOPT_FOLLOWLOCATION, true); curl_setopt(self::$curlHandle, CURLOPT_AUTOREFERER, true); - curl_setopt(self::$curlHandle, CURLOPT_BINARYTRANSFER, true); curl_setopt(self::$curlHandle, CURLOPT_MAXREDIRS, 6); } @@ -37,7 +36,7 @@ class Download * Download file, obey given timeout in seconds * Return data on success, false on failure */ - public static function asString(string $url, int $timeout, &$code) + public static function asString(string $url, int $timeout, ?int &$code) { $ch = self::initCurl($url, $timeout); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); @@ -52,9 +51,10 @@ class Download * @param string $url URL to fetch * @param array|false $params POST params to set in body, list of key-value-pairs * @param int $timeout timeout in seconds - * @param int $code HTTP response code, or 999 on error + * @param ?int $code HTTP response code, or 999 on error + * @return string|false */ - public static function asStringPost(string $url, $params, int $timeout, &$code) + public static function asStringPost(string $url, $params, int $timeout, ?int &$code) { $string = ''; if (is_array($params)) { @@ -80,10 +80,9 @@ class Download * @param string $target destination path to download file to * @param string $url URL of file to download * @param int $timeout timeout in seconds - * @param int $code HTTP status code passed out by reference - * @return boolean + * @param ?int $code HTTP status code passed out by reference */ - public static function toFile(string $target, string $url, int $timeout, &$code): bool + public static function toFile(string $target, string $url, int $timeout, ?int &$code): bool { $fh = fopen($target, 'wb'); if ($fh === false) diff --git a/inc/errorhandler.inc.php b/inc/errorhandler.inc.php index c7a32b02..8e49353c 100644 --- a/inc/errorhandler.inc.php +++ b/inc/errorhandler.inc.php @@ -1,5 +1,7 @@ <?php +use JetBrains\PhpStorm\NoReturn; + class ErrorHandler { @@ -10,7 +12,8 @@ class ErrorHandler * and all globally defined variables. * (As this might reveal sensitive data you should never enable it in production) */ - public static function traceError($message) + #[NoReturn] + public static function traceError(string $message): void { if ((defined('API') && API) || (defined('AJAX') && AJAX) || php_sapi_name() === 'cli') { error_log('API ERROR: ' . $message); @@ -84,7 +87,7 @@ SADFACE; exit(0); } - public static function formatBacktraceHtml($trace): string + public static function formatBacktraceHtml(array $trace): string { $output = ''; foreach ($trace as $idx => $line) { @@ -104,7 +107,7 @@ SADFACE; return $output; } - public static function formatBacktracePlain($trace): string + public static function formatBacktracePlain(array $trace): string { $output = ''; foreach ($trace as $idx => $line) { @@ -121,7 +124,7 @@ SADFACE; return $output; } - private static function formatArgument($arg, $expandArray = true) + private static function formatArgument($arg, bool $expandArray = true): string { if (is_string($arg)) { $arg = "'$arg'"; diff --git a/inc/event.inc.php b/inc/event.inc.php index e622f74f..db5bf1f1 100644 --- a/inc/event.inc.php +++ b/inc/event.inc.php @@ -15,7 +15,7 @@ class Event * Called when the system (re)booted. Could be implemented * by a @reboot entry in crontab (running as the same user php does) */ - public static function systemBooted() + public static function systemBooted(): void { EventLog::info('System boot...'); $everythingFine = true; @@ -96,7 +96,7 @@ class Event /** * Server's primary IP address changed. */ - public static function serverIpChanged() + public static function serverIpChanged(): void { Trigger::ipxe(); if (Module::isAvailable('sysconfig')) { // TODO: Modularize events diff --git a/inc/fileutil.inc.php b/inc/fileutil.inc.php index f35f987e..86a5ebc5 100644 --- a/inc/fileutil.inc.php +++ b/inc/fileutil.inc.php @@ -8,9 +8,9 @@ class FileUtil * * @param string $file file to read * @param int $maxBytes maximum length to read - * @return boolean|string data, false on error + * @return false|string data, false on error */ - public static function readFile($file, $maxBytes = 1000) + public static function readFile(string $file, int $maxBytes = 1000) { $fh = @fopen($file, 'rb'); if ($fh === false) @@ -19,18 +19,18 @@ class FileUtil fclose($fh); return $data; } - + /** * Read a file of key=value lines to assoc array. * * @param string $file Filename - * @return boolean|array assoc array, false on error + * @return ?array assoc array, null on error */ - public static function fileToArray($file) + public static function fileToArray(string $file): ?array { $data = self::readFile($file, 2000); if ($data === false) - return false; + return null; $data = explode("\n", str_replace("\r", "\n", $data)); $ret = array(); foreach ($data as $line) { @@ -40,7 +40,7 @@ class FileUtil } return $ret; } - + /** * Write given associative array to file as key=value pairs. * @@ -48,7 +48,7 @@ class FileUtil * @param array $array Associative array to write * @return boolean success of operation */ - public static function arrayToFile($file, $array) + public static function arrayToFile(string $file, array $array): bool { $fh = fopen($file, 'wb'); if ($fh === false) diff --git a/inc/hook.inc.php b/inc/hook.inc.php index f74281f1..abeac68e 100644 --- a/inc/hook.inc.php +++ b/inc/hook.inc.php @@ -14,7 +14,7 @@ class Hook * * @param string $hookName Name of hook to search for. * @param bool $filterBroken if true, modules that have a hook but have missing deps will not be returned - * @return \Hook[] list of modules with requested hooks + * @return Hook[] list of modules with requested hooks */ public static function load(string $hookName, bool $filterBroken = true): array { @@ -34,17 +34,17 @@ class Hook * @param string $moduleName Module * @param string $hookName Hook * @param bool $filterBroken return false if the module has missing deps - * @return Hook|false hook instance, false on error or if module doesn't have given hook + * @return ?Hook hook instance, false on error or if module doesn't have given hook */ - public static function loadSingle(string $moduleName, string $hookName, bool $filterBroken = true) + public static function loadSingle(string $moduleName, string $hookName, bool $filterBroken = true): ?Hook { if (Module::get($moduleName) === false) // No such module - return false; + return null; if ($filterBroken && !Module::isAvailable($moduleName)) // Broken - return false; + return null; $file = 'modules/' . $moduleName . '/hooks/' . $hookName . '.inc.php'; if (!file_exists($file)) // No hook - return false; + return null; return new Hook($moduleName, $file); } diff --git a/inc/iputil.inc.php b/inc/iputil.inc.php index 69311d7f..ecd8c198 100644 --- a/inc/iputil.inc.php +++ b/inc/iputil.inc.php @@ -3,38 +3,39 @@ class IpUtil { - public static function rangeToCidr($start, $end) + public static function rangeToCidr(int $start, int $end): string { - $value = (int)$start ^ (int)$end; + $value = $start ^ $end; if (!self::isAllOnes($value)) return 'NOT SUBNET: ' . long2ip($start) . '-' . long2ip($end); - $ones = self::countOnes($value); + $ones = self::bitLength($value); return long2ip($start) . '/' . (32 - $ones); } - public static function isValidSubnetRange($start, $end) + public static function isValidSubnetRange(int $start, int $end): bool { - return self::isAllOnes((int)$start ^ (int)$end); + return self::isAllOnes($start ^ $end); } /** - * Return number of one bits required to represent - * this number. Assumes given number is 2^n - 1. + * Return number of bits required to represent + * this number. + * !! Assumes given number is 2^n - 1 !! */ - private static function countOnes($value) + private static function bitLength(int $value): int { // This is log(value) / log(2) // It should actually be $value + 1, but floating point errors // start to happen either way at higher values, so with // the round() thrown in, it doesn't matter... - return round(log($value) / 0.69314718055995); + return (int)round(log($value) / 0.69314718055995); } /** * Is the given number just ones if converted to * binary (ignoring leading zeros)? */ - private static function isAllOnes($value) + private static function isAllOnes(int $value): bool { return ($value & ($value + 1)) === 0; } @@ -44,16 +45,17 @@ class IpUtil * ['start' => (int), 'end' => (int)] representing * the according start and end addresses as integer * values. Returns false on malformed input. + * * @param string $cidr 192.168.101/24, 1.2.3.4/16, ... - * @return array|false start and end address, false on error + * @return array{start: int, end: int}|null start and end address, false on error */ - public static function parseCidr($cidr) + public static function parseCidr(string $cidr): ?array { $parts = explode('/', $cidr); if (count($parts) !== 2) { $ip = ip2long($cidr); if ($ip === false) - return false; + return null; if (PHP_INT_SIZE === 4) { $ip = sprintf('%u', $ip); } @@ -62,15 +64,15 @@ class IpUtil $ip = $parts[0]; $bits = $parts[1]; if (!is_numeric($bits) || $bits < 0 || $bits > 32) - return false; + return null; $dots = substr_count($ip, '.'); if ($dots < 3) { $ip .= str_repeat('.0', 3 - $dots); } $ip = ip2long($ip); if ($ip === false) - return false; - $bits = pow(2, 32 - $bits) - 1; + return null; + $bits = (int)((2 ** (32 - $bits)) - 1); if (PHP_INT_SIZE === 4) return ['start' => sprintf('%u', $ip & ~$bits), 'end' => sprintf('%u', $ip | $bits)]; return ['start' => $ip & ~$bits, 'end' => $ip | $bits]; diff --git a/inc/mailer.inc.php b/inc/mailer.inc.php index 1545e930..b2fb7741 100644 --- a/inc/mailer.inc.php +++ b/inc/mailer.inc.php @@ -93,7 +93,7 @@ class Mailer return preg_replace('/^\* Expire in \d+ ms for.*[\\r\\n]+(?=\* Expire)/m','$1', $this->errlog); } - public static function queue(int $configid, array $rcpts, string $subject, string $text) + public static function queue(int $configid, array $rcpts, string $subject, string $text): void { foreach ($rcpts as $rcpt) { Database::exec("INSERT INTO mail_queue (rcpt, subject, body, dateline, configid) @@ -102,7 +102,7 @@ class Mailer } } - public static function flushQueue() + public static function flushQueue(): void { $list = Database::queryGroupList("SELECT Concat(configid, rcpt, subject) AS keyval, mailid, configid, rcpt, subject, body, dateline FROM mail_queue @@ -167,19 +167,15 @@ class Mailer return self::$configs[$configId] ?? []; } - /** - * @param int $configId - * @return Mailer|null - */ - public static function instanceFromConfig(int $configId) + public static function instanceFromConfig(int $configId): ?Mailer { $config = self::getConfig($configId); if (empty($config)) return null; if ($config['ssl'] === 'IMPLICIT') { - $uri = "smtps://{$config['host']}:${config['port']}"; + $uri = "smtps://{$config['host']}:{$config['port']}"; } else { - $uri = "smtp://{$config['host']}:${config['port']}"; + $uri = "smtp://{$config['host']}:{$config['port']}"; } return new Mailer($uri, $config['ssl'] === 'EXPLICIT', $config['senderaddress'], $config['username'], $config['password'], $config['replyto']); diff --git a/inc/message.inc.php b/inc/message.inc.php index 9197e4c2..482e4ba4 100644 --- a/inc/message.inc.php +++ b/inc/message.inc.php @@ -11,40 +11,39 @@ class Message * yet, it will be added to the queue, otherwise it will be added * in place during rendering. */ - public static function addError($id) + public static function addError(string $id, ...$params): void { - self::add('danger', $id, func_get_args()); + self::add('danger', $id, $params); } - public static function addWarning($id) + public static function addWarning(string $id, ...$params): void { - self::add('warning', $id, func_get_args()); + self::add('warning', $id, $params); } - public static function addInfo($id) + public static function addInfo(string $id, ...$params): void { - self::add('info', $id, func_get_args()); + self::add('info', $id, $params); } - public static function addSuccess($id) + public static function addSuccess(string $id, ...$params): void { - self::add('success', $id, func_get_args()); + self::add('success', $id, $params); } /** * Internal function that adds a message. Used by * addError/Success/Info/... above. */ - private static function add($type, $id, $params) + private static function add(string $type, string $id, array $params): void { if (strstr($id, '.') === false) { $id = Page::getModule()->getIdentifier() . '.' . $id; } - if (count($params) > 1 && $params[1] === true) { - $params = array_slice($params, 2); + if (!empty($params) && $params[0] === true) { + $params = array_slice($params, 1); $linkModule = true; } else { - $params = array_slice($params, 1); $linkModule = false; } switch ($type) { @@ -70,7 +69,9 @@ class Message 'params' => $params, 'link' => $linkModule ); - if (self::$flushed) self::renderList(); + if (self::$flushed) { + self::renderList(); + } } /** @@ -78,7 +79,7 @@ class Message * After calling this, any further calls to add* will be rendered in * place in the current page output. */ - public static function renderList() + public static function renderList(): void { self::$flushed = true; if (empty(self::$list)) @@ -122,7 +123,7 @@ class Message * Get all queued messages, flushing the queue. * Useful in api/ajax mode. */ - public static function asString() + public static function asString(): string { $return = ''; foreach (self::$list as $item) { @@ -145,7 +146,7 @@ class Message * Deserialize any messages from the current HTTP request and * place them in the message queue. */ - public static function fromRequest() + public static function fromRequest(): void { $messages = is_array($_REQUEST['message']) ? $_REQUEST['message'] : array($_REQUEST['message']); foreach ($messages as $message) { @@ -163,7 +164,7 @@ class Message * Turn the current message queue into a serialized version, * suitable for appending to a GET or POST request */ - public static function toRequest() + public static function toRequest(): string { $parts = array(); foreach (array_merge(self::$list, self::$alreadyDisplayed) as $item) { diff --git a/inc/module.inc.php b/inc/module.inc.php index 042ea0c0..115c9e9a 100644 --- a/inc/module.inc.php +++ b/inc/module.inc.php @@ -7,16 +7,16 @@ class Module */ /** - * @var \Module[] + * @var ?Module[] */ - private static $modules = false; + private static $modules = null; /** * @param string $name ID/Internal name of module - * @param false $ignoreDepFail whether to return the module even if some of its dependencies failed + * @param bool $ignoreDepFail whether to return the module even if some of its dependencies failed * @return false|Module */ - public static function get($name, $ignoreDepFail = false) + public static function get(string $name, bool $ignoreDepFail = false) { if (!isset(self::$modules[$name])) return false; @@ -28,13 +28,13 @@ class Module /** * Check whether given module is available, that is, all dependencies are * met. If the module is available, it will be activated, so all its classes - * are available through the auto-loader, and any js or css is added to the + * are available through the autoloader, and any js or css is added to the * final page output. * * @param string $moduleId module to check * @return bool true if module is available and activated */ - public static function isAvailable($moduleId, $activate = true) + public static function isAvailable(string $moduleId, bool $activate = true): bool { $module = self::get($moduleId); if ($module === false) @@ -45,7 +45,7 @@ class Module return !$module->hasMissingDependencies(); } - private static function resolveDepsByName($name) + private static function resolveDepsByName(string $name): bool { if (!isset(self::$modules[$name])) return false; @@ -57,7 +57,7 @@ class Module * @param \Module $mod the module to check * @return boolean true iff module deps are all found and enabled */ - private static function resolveDeps($mod) + private static function resolveDeps(Module $mod): bool { if (!$mod->depsChecked) { $mod->depsChecked = true; @@ -75,7 +75,7 @@ class Module /** * @return \Module[] List of valid, enabled modules */ - public static function getEnabled($sortById = false) + public static function getEnabled(bool $sortById = false): array { $ret = array(); $sort = array(); @@ -96,7 +96,7 @@ class Module /** * @return \Module[] List of all modules, including with missing deps */ - public static function getAll() + public static function getAll(): array { foreach (self::$modules as $module) { self::resolveDeps($module); @@ -107,7 +107,7 @@ class Module /** * @return \Module[] List of modules that have been activated */ - public static function getActivated() + public static function getActivated(): array { $ret = array(); $i = 0; @@ -120,9 +120,9 @@ class Module return $ret; } - public static function init() + public static function init(): void { - if (self::$modules !== false) + if (self::$modules !== null) return; $dh = opendir('modules'); if ($dh === false) @@ -143,7 +143,8 @@ class Module * Non-static */ - private $category = false; + /** @var ?string category id */ + private $category = null; private $clientPlugin = false; private $depsMissing = false; private $depsChecked = false; @@ -161,7 +162,7 @@ class Module */ private $scripts = array(); - private function __construct($name) + private function __construct(string $name) { $file = 'modules/' . $name . '/config.json'; $json = @json_decode(@file_get_contents($file), true); @@ -180,12 +181,12 @@ class Module $this->name = $name; } - public function hasMissingDependencies() + public function hasMissingDependencies(): bool { return $this->depsMissing; } - public function newPage() + public function newPage(): Page { $modulePath = 'modules/' . $this->name . '/page.inc.php'; if (!file_exists($modulePath)) { @@ -196,7 +197,7 @@ class Module return new $class(); } - public function activate($depth, $direct) + public function activate(?int $depth, ?bool $direct): bool { if ($this->depsMissing) return false; @@ -228,14 +229,14 @@ class Module return true; } - public function getDependencies() + public function getDependencies(): array { $deps = array(); $this->getDepsInternal($deps); return array_keys($deps); } - private function getDepsInternal(&$deps) + private function getDepsInternal(array &$deps): void { if (!is_array($this->dependencies)) return; @@ -250,49 +251,49 @@ class Module } } - public function getIdentifier() + public function getIdentifier(): string { return $this->name; } - public function getDisplayName() + public function getDisplayName(): string { - $string = Dictionary::translateFileModule($this->name, 'module', 'module_name'); + $string = Dictionary::translateFileModule($this->name, 'module', 'module_name', false); if ($string === false) { return '!!' . $this->name . '!!'; } return $string; } - public function getPageTitle() + public function getPageTitle(): string { - $val = Dictionary::translateFileModule($this->name, 'module', 'page_title'); + $val = Dictionary::translateFileModule($this->name, 'module', 'page_title', false); if ($val !== false) return $val; return $this->getDisplayName(); } - public function getCategory() + public function getCategory(): ?string { return $this->category; } - public function getCategoryName() + public function getCategoryName(): string { return Dictionary::getCategoryName($this->category); } - public function doCollapse() + public function doCollapse(): bool { return $this->collapse; } - public function getDir() + public function getDir(): string { return 'modules/' . $this->name; } - public function getScripts() + public function getScripts(): array { if ($this->directActivation && $this->clientPlugin) { if (!in_array('clientscript.js', $this->scripts) && file_exists($this->getDir() . '/clientscript.js')) { @@ -303,7 +304,7 @@ class Module return []; } - public function getCss() + public function getCss(): array { if ($this->directActivation && $this->clientPlugin) { if (!in_array('style.css', $this->css) && file_exists($this->getDir() . '/style.css')) { diff --git a/inc/paginate.inc.php b/inc/paginate.inc.php index 3187261c..b9a1ed78 100644 --- a/inc/paginate.inc.php +++ b/inc/paginate.inc.php @@ -9,15 +9,14 @@ class Paginate private $totalRows = false; /** - * @query - The query that will return lines to show - * @currentPage - 0based index of currently viewed page - * @perPage - Number of items to show per page - * @url - URL of current wegpage + * @param string $query - The query that will return lines to show + * @param int $perPage - Number of items to show per page + * @param ?string $url - URL of current wegpage */ - public function __construct($query, $perPage, $url = false) + public function __construct(string $query, int $perPage, string $url = null) { $this->currentPage = (isset($_GET['page']) ? (int)$_GET['page'] : 0); - $this->perPage = (int)$perPage; + $this->perPage = $perPage; if ($this->currentPage < 0) { ErrorHandler::traceError('Current page < 0'); } @@ -25,17 +24,17 @@ class Paginate ErrorHandler::traceError('Per page < 1'); } // Query - if (!preg_match('/\s*SELECT\s/is', $query)) { + if (!preg_match('/\s*SELECT\s/i', $query)) { ErrorHandler::traceError('Query has to start with SELECT!'); } // XXX: MySQL only - if (preg_match('/^mysql/i', CONFIG_SQL_DSN)) { + if (preg_match('/^(mysql|mariadb)/i', CONFIG_SQL_DSN)) { // Sanity: Check for LIMIT specification at the end if (preg_match('/LIMIT\s+(\d+|\:\w+|\?)\s*,\s*(\d+|\:\w+|\?)(\s|;)*(\-\-.*)?$/is', $query)) { ErrorHandler::traceError("You cannot pass a query containing a LIMIT to the Paginator class!"); } // Sanity: no comment or semi-colon at end (sloppy, might lead to false negatives) - if (preg_match('/(\-\-|;)(\s|[^\'"`])*$/is', $query)) { + if (preg_match('/(\-\-|;)(\s|[^\'"`])*$/i', $query)) { ErrorHandler::traceError("Your query must not end in a comment or semi-colon!"); } // Don't use SQL_CALC_FOUND_ROWS as it leads to filesort frequently thus being slower than two queries @@ -45,7 +44,9 @@ class Paginate ErrorHandler::traceError('Unsupported database engine'); } // Mangle URL - if ($url === false) $url = $_SERVER['REQUEST_URI']; + if ($url === null) { + $url = $_SERVER['REQUEST_URI']; + } if (strpos($url, '?') === false) { $url .= '?'; } else { @@ -60,7 +61,7 @@ class Paginate /** * Execute the query, returning the PDO query object */ - public function exec($args = array()) + public function exec(array $args = []) { $countQuery = preg_replace('/ORDER\s+BY\s.*?(\sASC|\sDESC|$)/is', '', $this->query); $countQuery = preg_replace('/SELECT\s.*?\sFROM\s/is', 'SELECT Count(*) AS rowcount FROM ', $countQuery); @@ -71,7 +72,7 @@ class Paginate return $retval; } - public function render($template, $data) + public function render(string $template, array $data): void { if ($this->totalRows == 0) { // Shortcut for no content diff --git a/inc/permission.inc.php b/inc/permission.inc.php index abeabb1d..798f9350 100644 --- a/inc/permission.inc.php +++ b/inc/permission.inc.php @@ -9,7 +9,7 @@ class Permission 'translation' => 8, // Can edit translations ); - public static function get($permission) + public static function get(string $permission): int { if (!isset(self::$permissions[$permission])) ErrorHandler::traceError('Invalid permission: ' . $permission); return self::$permissions[$permission]; @@ -17,10 +17,13 @@ class Permission // TODO: Doc/Refactor - public static function addGlobalTags(&$array, $locationid, $disabled, $noneAvailDisabled = null) + public static function addGlobalTags(?array &$array, ?int $locationid, array $disabled, ?string $noneAvailDisabled = null): void { if (Module::get('permissionmanager') === false) return; + if ($array === null) { + $array = []; + } $one = false; foreach ($disabled as $perm) { if (User::hasPermission($perm, $locationid)) { @@ -47,7 +50,7 @@ class Permission } } - public static function moduleHasPermissions($moduleId) + public static function moduleHasPermissions(string $moduleId): bool { if (Module::get('permissionmanager') === false) return true; @@ -58,13 +61,8 @@ class Permission * Takes a list of locations, removes any locations from it where the user doesn't have permission, * and then re-adds locations resulting from the given query. The given query should return only * one column per row, which is a location id. - * @param $passedLocations - * @param $permission - * @param $query - * @param $params - * @return array */ - public static function mergeWithDisallowed($passedLocations, $permission, $query, $params) + public static function mergeWithDisallowed(array $passedLocations, string $permission, string $query, array $params): array { $allowed = User::getAllowedLocations($permission); if (in_array(0, $allowed)) diff --git a/inc/property.inc.php b/inc/property.inc.php index dd72c187..5efcfe3a 100644 --- a/inc/property.inc.php +++ b/inc/property.inc.php @@ -41,7 +41,7 @@ class Property * @param string|null|false $value the value to store for $key * @param int $maxAgeMinutes how long to keep this entry around at least, in minutes. 0 for infinite */ - public static function set(string $key, $value, int $maxAgeMinutes = 0) + public static function set(string $key, $value, int $maxAgeMinutes = 0): void { if ($value === false || $value === null) { Database::exec("DELETE FROM property WHERE name = :key", ['key' => $key]); @@ -82,11 +82,9 @@ class Property } /** - * @param string $key - * @param int $subkey * @return ?string entry from property list */ - public static function getListEntry(string $key, int $subkey) + public static function getListEntry(string $key, int $subkey): ?string { $row = Database::queryFirst("SELECT dateline, `value` FROM property_list WHERE `name` = :key AND subkey = :subkey", ['key' => $key, 'subkey' => $subkey]); @@ -188,12 +186,12 @@ class Property * Legacy getters/setters */ - public static function getServerIp() + public static function getServerIp(): string { - return self::get('server-ip', 'none'); + return self::get('server-ip', 'invalid'); } - public static function setServerIp(string $value, $automatic = false): bool + public static function setServerIp(string $value, bool $automatic = false): bool { if ($value === self::getServerIp()) return false; @@ -203,16 +201,6 @@ class Property return true; } - public static function getBootMenu() - { - return json_decode(self::get('ipxe-menu'), true); - } - - public static function setBootMenu($value) - { - self::set('ipxe-menu', json_encode($value)); - } - public static function getVmStoreConfig() { return json_decode(self::get('vmstore-config'), true); @@ -247,14 +235,14 @@ class Property return self::get('last-warn-event-id', 0); } - public static function setNeedsSetup($value) + public static function setNeedsSetup(bool $value) { - self::set('needs-setup', $value); + self::set('needs-setup', (int)$value); } - public static function getNeedsSetup() + public static function getNeedsSetup(): bool { - return self::get('needs-setup'); + return self::get('needs-setup') != 0; } public static function setPasswordFieldType(string $value) diff --git a/inc/render.inc.php b/inc/render.inc.php index 697646c5..68a0cd19 100644 --- a/inc/render.inc.php +++ b/inc/render.inc.php @@ -14,20 +14,21 @@ class Render { /** - * @var Mustache_Engine + * @var ?Mustache_Engine */ - private static $mustache = false; + private static $mustache = null; private static $body = ''; private static $header = ''; - private static $dashboard = false; + /** @var ?array */ + private static $dashboard = null; private static $footer = ''; private static $title = ''; private static $templateCache = array(); private static $tags = array(); - public static function init() + public static function init(): void { - if (self::$mustache !== false) + if (self::$mustache !== null) ErrorHandler::traceError('Called Render::init() twice!'); $options = array(); $tmp = '/tmp/bwlp-cache'; @@ -41,7 +42,7 @@ class Render self::$mustache = new Mustache_Engine($options); } - private static function cssEsc($str) + private static function cssEsc(string $str): string { return str_replace(array('"', '&', '<', '>'), array('\\000022', '\\000026', '\\00003c', '\\00003e'), $str); } @@ -49,12 +50,10 @@ class Render /** * Output the buffered, generated page */ - public static function output() + public static function output(): void { Header('Content-Type: text/html; charset=utf-8'); - /* @var $modules Module[] */ $modules = array_reverse(Module::getActivated()); - $pageModule = Page::getModule(); $title = Property::get('page-title-prefix', ''); $bgcolor = Property::get('logo-background', ''); if (!empty($bgcolor) || !empty($title)) { @@ -99,7 +98,7 @@ class Render ' </head> <body> ', - (self::$dashboard !== false ? self::parse('main-menu', self::$dashboard, 'main') : ''), + (self::$dashboard !== null ? self::parse('main-menu', self::$dashboard, 'main') : ''), '<div class="main" id="mainpage"><div class="container-fluid"> ', self::$body @@ -128,7 +127,7 @@ class Render /** * Set the page title (title-tag) */ - public static function setTitle($title, $override = true) + public static function setTitle(string $title, bool $override = true): void { if (!$override && !empty(self::$title)) return; @@ -138,7 +137,7 @@ class Render /** * Add raw html data to the header-section of the generated page */ - public static function addHeader($html) + public static function addHeader(string $html): void { self::$header .= $html . "\n"; } @@ -146,7 +145,7 @@ class Render /** * Add raw html data to the footer-section of the generated page (right before the closing body tag) */ - public static function addFooter($html) + public static function addFooter(string $html): void { self::$footer .= $html . "\n"; } @@ -154,7 +153,7 @@ class Render /** * Add the given template to the output, using the given params for placeholders in the template */ - public static function addTemplate($template, $params = false, $module = false) + public static function addTemplate(string $template, array $params = [], ?string $module = null) { self::$body .= self::parse($template, $params, $module); } @@ -167,7 +166,7 @@ class Render * @param string $template template used to fill the dialog body * @param array $params parameters for rendering the body template */ - public static function addDialog($title, $next, $template, $params = false) + public static function addDialog(string $title, bool $next, string $template, array $params = []): void { self::addTemplate('dialog-generic', array( 'title' => $title, @@ -179,7 +178,7 @@ class Render /** * Add error message to page */ - public static function addError($message) + public static function addError($message): void { self::addTemplate('messagebox-error', array('message' => $message)); } @@ -191,9 +190,9 @@ class Render * @param string $module name of module to load template from; defaults to currently active module * @return string Rendered template */ - public static function parse($template, $params = false, $module = false, $lang = false) + public static function parse(string $template, array $params = [], ?string $module = null, ?string $lang = null): string { - if ($module === false && class_exists('Page')) { + if ($module === null && class_exists('Page', false)) { $module = Page::getModule()->getIdentifier(); } // Load html snippet @@ -201,9 +200,6 @@ class Render if ($html === false) { return '<h3>Template ' . htmlspecialchars($template) . '</h3>' . nl2br(htmlspecialchars(print_r($params, true))) . '<hr>'; } - if (!is_array($params)) { - $params = array(); - } // Now find all language tags in this array if (preg_match_all('/{{\s*(lang_.+?)\s*}}/', $html, $out) > 0) { $dictionary = Dictionary::getArray($module, 'template-tags', $lang); @@ -211,14 +207,14 @@ class Render foreach ($out[1] as $tag) { if ($fallback === false && empty($dictionary[$tag])) { $fallback = true; // Fallback to general dictionary of main module - $dictionary = $dictionary + Dictionary::getArray('main', 'global-tags'); + $dictionary += Dictionary::getArray('main', 'global-tags'); } // Add untranslated strings to the dictionary, so their tag is seen in the rendered page if (empty($dictionary[$tag])) { $dictionary[$tag] = '{{' . $tag . '}}'; } } - $params = $params + $dictionary; + $params += $dictionary; } // Always add token to parameter list $params['token'] = Session::get('token'); @@ -244,7 +240,7 @@ class Render */ public static function openTag($tag, $params = false) { - array_push(self::$tags, $tag); + self::$tags[] = $tag; if (!is_array($params)) { self::$body .= '<' . $tag . '>'; } else { @@ -271,8 +267,9 @@ class Render /** * Private helper: Load the given template and return it + * @return false|string */ - private static function getTemplate($template, $module) + private static function getTemplate(string $template, string $module) { $id = "$template/$module"; if (isset(self::$templateCache[$id])) { @@ -287,12 +284,13 @@ class Render /** * Create the dashboard menu */ - public static function setDashboard($params) + public static function setDashboard(array $params): void { self::$dashboard = $params; } - public static function readableColor($hex) { + public static function readableColor(string $hex): string + { if (strlen($hex) <= 4) { $cnt = 1; } else { diff --git a/inc/request.inc.php b/inc/request.inc.php index 7cf4a73f..c499a9d9 100644 --- a/inc/request.inc.php +++ b/inc/request.inc.php @@ -53,7 +53,7 @@ class Request /** * @return true iff the request is a POST request */ - public static function isPost() + public static function isPost(): bool { return $_SERVER['REQUEST_METHOD'] === 'POST'; } @@ -61,7 +61,7 @@ class Request /** * @return true iff the request is a GET request */ - public static function isGet() + public static function isGet(): bool { return $_SERVER['REQUEST_METHOD'] === 'GET'; } diff --git a/inc/session.inc.php b/inc/session.inc.php index 1c20c8a6..622eb320 100644 --- a/inc/session.inc.php +++ b/inc/session.inc.php @@ -10,7 +10,7 @@ class Session private static $userId = 0; private static $updateSessionDateline = false; - private static function generateSessionId(string $salt) + private static function generateSessionId(string $salt): void { if (self::$sid !== false) ErrorHandler::traceError('Error: Asked to generate session id when already set.'); @@ -27,7 +27,7 @@ class Session ); } - public static function create(string $salt, int $userId, bool $fixedAddress) + public static function create(string $salt, int $userId, bool $fixedAddress): void { self::generateSessionId($salt); self::$data = []; @@ -71,7 +71,7 @@ class Session * @param mixed $value data to store for key, false = delete * @param int|false $validMinutes validity in minutes, or false = forever */ - public static function set(string $key, $value, $validMinutes = 60) + public static function set(string $key, $value, $validMinutes = 60): void { if (self::$data === false) ErrorHandler::traceError('Tried to set session data with no active session'); @@ -96,7 +96,7 @@ class Session return true; } - public static function delete() + public static function delete(): void { if (self::$sid === false) return; @@ -112,7 +112,7 @@ class Session * a security measure if the user suspects that a session left open on * another device could be/is being abused. */ - public static function deleteAllButCurrent() + public static function deleteAllButCurrent(): void { if (self::$sid === false) return; @@ -120,7 +120,7 @@ class Session ['sid' => self::$sid, 'uid' => self::$userId]); } - public static function deleteCookie() + public static function deleteCookie(): void { Util::clearCookie('sid'); } @@ -155,7 +155,7 @@ class Session return true; } - private static function setupSessionAccounting(bool $cookie) + private static function setupSessionAccounting(bool $cookie): void { if ($cookie) { self::$updateSessionDateline = true; @@ -169,7 +169,7 @@ class Session }); } - private static function saveOnShutdown() + private static function saveOnShutdown(): void { $now = time(); $args = ['lastip' => $_SERVER['REMOTE_ADDR']]; @@ -182,7 +182,7 @@ class Session self::saveData($args); } - public static function saveExtraData() + public static function saveExtraData(): void { if (!self::$dataChanged) return; @@ -190,7 +190,7 @@ class Session self::$dataChanged = false; } - private static function saveData(array $args) + private static function saveData(array $args): void { $query = "UPDATE session SET " . implode(', ', array_map(function ($key) { return "$key = :$key"; diff --git a/inc/taskmanager.inc.php b/inc/taskmanager.inc.php index 700ea4ad..6c9d63c2 100644 --- a/inc/taskmanager.inc.php +++ b/inc/taskmanager.inc.php @@ -19,7 +19,7 @@ class Taskmanager */ private static $sock = false; - private static function init() + private static function init(): void { if (self::$sock !== false) return; @@ -32,7 +32,7 @@ class Taskmanager self::send(CONFIG_TM_PASSWORD); } - private static function send($message) + private static function send(string $message): bool { $len = strlen($message); $sent = socket_send(self::$sock, pack('N', $len) . $message, $len + 4, 0); @@ -51,7 +51,7 @@ class Taskmanager * the return value is just true (and you won't know if the task could actually be started) * @return array{id: string, statusCode: string, data: array}|bool struct representing the task status (as a result of submit); false on communication error */ - public static function submit($task, $data = false, $async = false) + public static function submit(string $task, array $data = null, bool $async = false) { self::init(); $seq = (string) mt_rand(); @@ -109,7 +109,7 @@ class Taskmanager * @param string|array $taskid a task id or a task array returned by ::status or ::submit * @return boolean true if taskid exists in taskmanager */ - public static function isTask($task) + public static function isTask($task): bool { if ($task === false) return false; @@ -127,7 +127,7 @@ class Taskmanager * @param int $timeout maximum time in ms to wait for completion of task * @return array|false result/status of task, or false if it couldn't be queried */ - public static function waitComplete($task, $timeout = 2500) + public static function waitComplete($task, int $timeout = 2500) { if (is_array($task) && isset($task['id'])) { if ($task['statusCode'] !== Taskmanager::TASK_PROCESSING && $task['statusCode'] !== Taskmanager::TASK_WAITING) { @@ -140,6 +140,7 @@ class Taskmanager return false; $done = false; $deadline = microtime(true) + $timeout / 1000; + $status = false; while (($remaining = $deadline - microtime(true)) > 0) { usleep((int)min(100000, $remaining * 100000)); $status = self::status($task); @@ -163,7 +164,7 @@ class Taskmanager * @param array|false $task struct representing task, obtained by ::status * @return boolean true if task failed, false if finished successfully or still waiting/running */ - public static function isFailed($task) + public static function isFailed($task): bool { if (!is_array($task) || !isset($task['statusCode']) || !isset($task['id'])) return true; @@ -176,10 +177,10 @@ class Taskmanager * Check whether the given task is finished, i.e. either failed or succeeded, * but is not running, still waiting for execution or simply unknown. * - * @param array $task struct representing task, obtained by ::status + * @param mixed $task struct representing task, obtained by ::status * @return boolean true if task failed or finished, false if waiting for execution or currently executing, no valid task, etc. */ - public static function isFinished($task) + public static function isFinished($task): bool { if (!is_array($task) || !isset($task['statusCode']) || !isset($task['id'])) return false; @@ -192,10 +193,10 @@ class Taskmanager * Check whether the given task is running, that is either waiting for execution * or currently executing. * - * @param array $task struct representing task, obtained by ::status + * @param mixed $task struct representing task, obtained by ::status * @return boolean true if task is waiting or executing, false if waiting for execution or currently executing, no valid task, etc. */ - public static function isRunning($task) + public static function isRunning($task): bool { if (!is_array($task) || !isset($task['statusCode']) || !isset($task['id'])) return false; @@ -204,7 +205,7 @@ class Taskmanager return false; } - public static function addErrorMessage($task) + public static function addErrorMessage($task): void { static $failure = false; if ($task === false) { @@ -231,7 +232,7 @@ class Taskmanager * @param string|array $task task to release. can either be its id, or a struct representing the task, as returned * by ::submit() or ::status() */ - public static function release($task) + public static function release($task): void { if (is_array($task) && isset($task['id'])) { $task = $task['id']; @@ -247,7 +248,6 @@ class Taskmanager /** * Read reply from socket for given sequence number. * - * @param string $seq * @return mixed the decoded json data for that message as an array, or false on error */ private static function readReply(string $seq) @@ -324,7 +324,7 @@ class Taskmanager * sending or receiving and the send or receive * buffer might be in an undefined state. */ - private static function reset() + private static function reset(): void { if (self::$sock === false) return; @@ -335,7 +335,7 @@ class Taskmanager /** * @param float $deadline end time */ - private static function updateRecvTimeout($deadline) + private static function updateRecvTimeout(float $deadline): void { $to = $deadline - microtime(true); if ($to <= 0) { diff --git a/inc/taskmanagercallback.inc.php b/inc/taskmanagercallback.inc.php index 7c1e965e..321475ac 100644 --- a/inc/taskmanagercallback.inc.php +++ b/inc/taskmanagercallback.inc.php @@ -13,7 +13,7 @@ class TaskmanagerCallback * @param string|array $task Task or Task ID to define callback for * @param string $callback name of callback function, must be a static method in this class */ - public static function addCallback($task, $callback, $args = NULL) + public static function addCallback($task, string $callback, $args = NULL): void { if (!call_user_func_array('method_exists', array('TaskmanagerCallback', $callback))) { EventLog::warning("addCallback: Invalid callback function: $callback"); @@ -50,7 +50,7 @@ class TaskmanagerCallback * * @return array list of array(taskid => list of callbacks) */ - public static function getPendingCallbacks() + public static function getPendingCallbacks(): array { $res = Database::simpleQuery("SELECT taskid, cbfunction, args FROM callback", array(), true); if ($res === false) @@ -67,9 +67,9 @@ class TaskmanagerCallback * table if appropriate. * * @param array $callback entry from the callback table (cbfunction + taskid + args) - * @param array $status status of the task as returned by the taskmanager. If NULL it will be queried. + * @param ?array $status status of the task as returned by the taskmanager. If NULL it will be queried. */ - public static function handleCallback($callback, $status = NULL) + public static function handleCallback(array $callback, array $status = NULL): void { if (is_null($status)) $status = Taskmanager::status($callback['taskid']); @@ -99,7 +99,7 @@ class TaskmanagerCallback /** * Result of trying to (re)launch ldadp. */ - public static function ldadpStartup($task) + public static function ldadpStartup(array $task) { if (Taskmanager::isFailed($task)) { if (!isset($task['data']['messages'])) { @@ -112,14 +112,14 @@ class TaskmanagerCallback /** * Result of restoring the server configuration */ - public static function dbRestored($task) + public static function dbRestored(array $task) { if (!Taskmanager::isFailed($task)) { EventLog::info('Configuration backup restored.'); } } - public static function adConfigCreate($task) + public static function adConfigCreate(array $task) { if (Taskmanager::isFailed($task)) EventLog::warning("Could not generate Active Directory configuration", $task['data']['error']); @@ -131,7 +131,7 @@ class TaskmanagerCallback * @param array $task task obj * @param array $args has keys 'moduleid' and optionally 'deleteOnError' and 'tmpTgz' */ - public static function cbConfModCreated($task, $args) + public static function cbConfModCreated(array $task, array $args) { $mod = Module::get('sysconfig'); if ($mod === false) @@ -150,7 +150,7 @@ class TaskmanagerCallback * @param array $task task obj * @param array $args has keys 'configid' and optionally 'deleteOnError' */ - public static function cbConfTgzCreated($task, $args) + public static function cbConfTgzCreated(array $task, array $args) { $mod = Module::get('sysconfig'); if ($mod === false) @@ -163,7 +163,7 @@ class TaskmanagerCallback } } - public static function manualMount($task, $args) + public static function manualMount(array $task, $args) { if (!isset($task['data']['exitCode'])) return; @@ -183,7 +183,7 @@ class TaskmanagerCallback } } - public static function mlGotList($task, $args) + public static function mlGotList(array $task, $args) { $mod = Module::get('minilinux'); if ($mod === false) @@ -192,7 +192,7 @@ class TaskmanagerCallback MiniLinux::listDownloadCallback($task, $args); } - public static function mlGotLinux($task, $args) + public static function mlGotLinux(array $task, $args) { $mod = Module::get('minilinux'); if ($mod === false) @@ -201,7 +201,7 @@ class TaskmanagerCallback MiniLinux::linuxDownloadCallback($task, $args); } - public static function rbcConnCheck($task, $args) + public static function rbcConnCheck(array $task, $args) { $mod = Module::get('rebootcontrol'); if ($mod === false) @@ -210,7 +210,7 @@ class TaskmanagerCallback RebootControl::connectionCheckCallback($task, $args); } - public static function ipxeVersionSet($task) + public static function ipxeVersionSet(array $task) { $mod = Module::get('serversetup'); if ($mod === false) @@ -219,7 +219,7 @@ class TaskmanagerCallback IPxeBuilder::setIPxeVersionCallback($task); } - public static function ipxeCompileDone($task) + public static function ipxeCompileDone(array $task) { $mod = Module::get('serversetup'); if ($mod === false) diff --git a/inc/trigger.inc.php b/inc/trigger.inc.php index df06229b..4776855c 100644 --- a/inc/trigger.inc.php +++ b/inc/trigger.inc.php @@ -15,9 +15,9 @@ class Trigger * Compile iPXE pxelinux menu. Needs to be done whenever the server's IP * address changes. * - * @return ?string false if launching task failed, task-id otherwise + * @return ?string null if launching task failed, task-id otherwise */ - public static function ipxe(string $taskId = null) + public static function ipxe(string $taskId = null): ?string { static $lastResult = null; if ($lastResult !== null) @@ -101,18 +101,14 @@ class Trigger * @param bool $ifLocalOnly Only execute task if the storage type is local (used for DNBD3) * @return ?string task id of mount procedure, or false on error */ - public static function mount($vmstore = false, bool $ifLocalOnly = false) + public static function mount($vmstore = false, bool $ifLocalOnly = false): ?string { if ($vmstore === false) { $vmstore = Property::getVmStoreConfig(); } if (!is_array($vmstore)) return null; - if (isset($vmstore['storetype'])) { - $storetype = $vmstore['storetype']; - } else { - $storetype = 'unknown'; - } + $storetype = $vmstore['storetype'] ?? 'unknown'; if ($storetype === 'nfs') { $addr = $vmstore['nfsaddr']; $opts = 'nfsopts'; @@ -126,11 +122,7 @@ class Trigger // Bail out if storage is not local, and we only want to run it in that case if ($ifLocalOnly && $addr !== 'null') return null; - if (isset($vmstore[$opts])) { - $opts = $vmstore[$opts]; - }else { - $opts = null; - } + $opts = $vmstore[$opts] ?? null; $status = Taskmanager::submit('MountVmStore', array( 'address' => $addr, 'type' => 'images', @@ -172,7 +164,7 @@ class Trigger return $tasksLeft; } - private static function triggerDaemons(string $action, $parent, &$taskids) + private static function triggerDaemons(string $action, ?string $parent, array &$taskids): ?string { $task = Taskmanager::submit('Systemctl', array( 'operation' => $action, @@ -200,7 +192,7 @@ class Trigger /** * Stop any daemons that might be sitting on the VMstore, or database. */ - public static function stopDaemons($parent, &$taskids) + public static function stopDaemons(?string $parent, array &$taskids): ?string { $parent = self::triggerDaemons('stop', $parent, $taskids); $task = Taskmanager::submit('LdadpLauncher', array( diff --git a/inc/user.inc.php b/inc/user.inc.php index cf9c38c0..4d278e1b 100644 --- a/inc/user.inc.php +++ b/inc/user.inc.php @@ -1,5 +1,7 @@ <?php +use JetBrains\PhpStorm\NoReturn; + require_once('inc/session.inc.php'); class User @@ -26,7 +28,7 @@ class User return self::$user['fullname']; } - public static function hasPermission($permission, $locationid = NULL) + public static function hasPermission(string $permission, ?int $locationid = NULL): bool { if (!self::isLoggedIn()) return false; @@ -54,11 +56,12 @@ class User /** * Confirm current user has the given permission, stop execution and show error message * otherwise. + * * @param string $permission Permission to check for * @param null|int $locationid location this permission has to apply to, NULL if any location is sufficient * @param null|string $redirect page to redirect to if permission is not given, NULL defaults to main page */ - public static function assertPermission($permission, $locationid = NULL, $redirect = NULL) + public static function assertPermission(string $permission, ?int $locationid = NULL, ?string $redirect = NULL): void { if (User::hasPermission($permission, $locationid)) return; @@ -108,7 +111,7 @@ class User return []; } - public static function load() + public static function load(): bool { if (self::isLoggedIn()) return true; @@ -128,7 +131,7 @@ class User return false; } - public static function testPassword($userid, $password) + public static function testPassword(string $userid, string $password): bool { $ret = Database::queryFirst('SELECT passwd FROM user WHERE userid = :userid LIMIT 1', compact('userid')); if ($ret === false) @@ -136,7 +139,7 @@ class User return Crypto::verify($password, $ret['passwd']); } - public static function updatePassword($password) + public static function updatePassword(string $password): bool { if (!self::isLoggedIn()) return false; @@ -145,7 +148,7 @@ class User return Database::exec('UPDATE user SET passwd = :passwd WHERE userid = :userid LIMIT 1', compact('userid', 'passwd')) > 0; } - public static function login(string $user, string $pass, bool $fixedIp) + public static function login(string $user, string $pass, bool $fixedIp): bool { $ret = Database::queryFirst('SELECT userid, passwd FROM user WHERE login = :user LIMIT 1', array(':user' => $user)); if ($ret === false) @@ -157,14 +160,15 @@ class User return true; } - public static function logout() + #[NoReturn] + public static function logout(): void { Session::delete(); Header('Location: ?do=Main&fromlogout'); exit(0); } - public static function setLastSeenEvent($eventid) + public static function setLastSeenEvent(int $eventid): void { if (!self::isLoggedIn()) return; @@ -182,7 +186,7 @@ class User return self::$user['lasteventid']; } - private static function generateToken($salt = '') + private static function generateToken($salt = ''): void { Session::set('token', md5($salt . ',' . rand() . ',' diff --git a/inc/util.inc.php b/inc/util.inc.php index 8bd48dd3..0c402a6a 100644 --- a/inc/util.inc.php +++ b/inc/util.inc.php @@ -1,5 +1,7 @@ <?php +use JetBrains\PhpStorm\NoReturn; + class Util { private static $redirectParams = array(); @@ -12,7 +14,8 @@ class Util * @param string|false $location Location to redirect to. "false" to redirect to same URL (useful after POSTs) * @param bool $preferRedirectPost if true, use the value from $_POST['redirect'] instead of $location */ - public static function redirect($location = false, bool $preferRedirectPost = false) + #[NoReturn] + public static function redirect($location = false, bool $preferRedirectPost = false): void { if ($location === false) { $location = preg_replace('/([&?])message\[\]=[^&]*/', '\1', $_SERVER['REQUEST_URI']); @@ -48,7 +51,7 @@ class Util exit(0); } - public static function addRedirectParam(string $key, string $value) + public static function addRedirectParam(string $key, string $value): void { self::$redirectParams[] = $key . '=' . urlencode($value); } @@ -108,7 +111,7 @@ class Util if ($factor === 0) { $decimals = 0; } else { - $bytes = $bytes / pow(1024, $factor); + $bytes /= 1024 ** $factor; if ($decimals === -1) { $decimals = 2 - floor(strlen((int)$bytes) - 1); } @@ -116,7 +119,7 @@ class Util return Dictionary::number($bytes, $decimals) . "\xe2\x80\x89" . ($sz[$factor + $shift] ?? '#>PiB#'); } - public static function sanitizeFilename(string $name) + public static function sanitizeFilename(string $name): string { return preg_replace('/[^a-zA-Z0-9_\-]+/', '_', $name); } @@ -130,7 +133,7 @@ class Util * @param string $prefix required prefix of $path * @return false|string */ - public static function safePath(string $path, string $prefix = '') + public static function safePath(string $path, string $prefix = ''): string { if (empty($path)) return false; @@ -253,9 +256,9 @@ class Util * * @param int $length number of bytes to return * @param bool $secure true = only use strong random sources - * @return string|bool string of requested length, false on error + * @return ?string string of requested length, false on error */ - public static function randomBytes(int $length, bool $secure = true) + public static function randomBytes(int $length, bool $secure = true): ?string { if (function_exists('random_bytes')) { try { @@ -292,7 +295,7 @@ class Util } } if ($secure) { - return false; + return null; } $bytes = ''; while ($length > 0) { @@ -306,7 +309,7 @@ class Util */ public static function randomUuid(): string { - $b = unpack('h8a/h4b/h12c', self::randomBytes(12)); + $b = unpack('h8a/h4b/h12c', self::randomBytes(12, false)); return sprintf('%08s-%04s-%04x-%04x-%012s', // 32 bits for "time_low" @@ -334,7 +337,7 @@ class Util * The format depends on how far the timestamp lies in the past. * * @param int $ts unix timestamp - * @return string human readable representation + * @return string human-readable representation */ public static function prettyTime(int $ts): string { @@ -366,8 +369,8 @@ class Util public static function boolToString(bool $bool): string { if ($bool) - return Dictionary::translate('lang_yes', true); - return Dictionary::translate('lang_no', true); + return Dictionary::translate('lang_yes'); + return Dictionary::translate('lang_no'); } /** @@ -375,7 +378,6 @@ class Util * * @param int $seconds The number to format * @param bool $showSecs whether to show seconds, or rather cut after minutes - * @return string */ public static function formatDuration(int $seconds, bool $showSecs = true): string { @@ -408,7 +410,7 @@ class Util * * @param string $name cookie name */ - public static function clearCookie(string $name) + public static function clearCookie(string $name): void { $parts = explode('/', $_SERVER['SCRIPT_NAME']); $path = ''; @@ -455,14 +457,21 @@ class Util /** * Clamp given value into [min, max] range. + * @param mixed $value value to clamp. This should be a number. + * @param int $min lower bound + * @param int $max upper bound + * @param bool $toInt if true, variable type of $value will be set to int in addition to clamping */ - public static function clamp(int &$value, int $min, int $max) + public static function clamp(&$value, int $min, int $max, bool $toInt = true): void { - if ($value < $min) { + if (!is_numeric($value) || $value < $min) { $value = $min; } elseif ($value > $max) { $value = $max; } + if ($toInt) { + settype($value, 'int'); + } } } @@ -48,7 +48,7 @@ abstract class Page public static function render() { $pageTitle = self::$module->getPageTitle(); - if ($pageTitle !== false) { + if (!empty($pageTitle)) { Render::setTitle($pageTitle, false); } self::$instance->doRender(); @@ -155,9 +155,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (!Util::verifyToken()) { if (AJAX) { die('CSRF/XSS? Missing token in POST request!'); - } else { - Util::redirect('?do=Main'); } + Util::redirect('?do=Main'); } } @@ -190,7 +189,7 @@ if (defined('CONFIG_DEBUG') && CONFIG_DEBUG) { * @param int $code Error code to map * @return string Readable error type */ - function mapErrorCode($code) + function mapErrorCode(int $code): string { switch ($code) { case E_PARSE: diff --git a/install.php b/install.php index d411d834..530298b1 100644 --- a/install.php +++ b/install.php @@ -19,6 +19,8 @@ * they might depend on some tables that do not exist yet. ;) */ +use JetBrains\PhpStorm\NoReturn; + /** * Report back the update status to the browser/client and terminate execution. * This has to be called by an update module at some point to signal the result @@ -27,7 +29,8 @@ * @param string $status one of the UPDATE_* status codes * @param string $message Human readable description of the status (optional) */ -function finalResponse($status, $message = '') +#[NoReturn] +function finalResponse(string $status, string $message = '') { if (!DIRECT_MODE && AJAX) { echo json_encode(array('status' => $status, 'message' => $message)); @@ -58,7 +61,7 @@ function handleUpdateResult($res) * Helper functions for dealing with the database */ -function tableHasColumn($table, $column) +function tableHasColumn(string $table, string $column): bool { return tableColumnType($table, $column) !== false; } @@ -66,7 +69,7 @@ function tableHasColumn($table, $column) /** * Get type of column, as reported by DESCRIBE <table>; */ -function tableColumnType($table, $column) +function tableColumnType(string $table, string $column) { return tableGetDescribeColumn($table, $column, 'Type'); } @@ -78,8 +81,10 @@ function tableColumnKeyType($table, $column) /** * For internal use + * @param string|string[] $column + * @return string|false */ -function tableGetDescribeColumn($table, $column, $what) +function tableGetDescribeColumn(string $table, $column, string $what) { $table = preg_replace('/\W/', '', $table); $res = Database::simpleQuery("DESCRIBE `$table`", array(), true); @@ -92,33 +97,37 @@ function tableGetDescribeColumn($table, $column, $what) return false; } -function tableGetIndex($table, $index) +/** + * Return name of index that spans all the columns given, in the same order. + * Returns false if not found + * + * @param string[] $columns + * @return false|string + */ +function tableGetIndex(string $table, array $columns) { $table = preg_replace('/\W/', '', $table); - if (!is_array($index)) { - $index = [$index]; - } $res = Database::simpleQuery("SHOW INDEX FROM `$table`", array(), true); if ($res !== false) { $matches = []; foreach ($res as $row) { $i = $row['Seq_in_index'] - 1; - if (isset($index[$i]) && $index[$i] === $row['Column_name']) { + if (isset($columns[$i]) && $columns[$i] === $row['Column_name']) { if (!isset($matches[$row['Key_name']])) { $matches[$row['Key_name']] = 0; } $matches[$row['Key_name']]++; } } - } - foreach ($matches as $key => $m) { - if ($m === count($index)) - return $key; + foreach ($matches as $key => $m) { + if ($m === count($columns)) + return $key; + } } return false; } -function tableDropColumn($table, $column) +function tableDropColumn(string $table, string $column): void { $table = preg_replace('/\W/', '', $table); $column = preg_replace('/\W/', '', $column); @@ -131,7 +140,7 @@ function tableDropColumn($table, $column) } } -function tableExists($table) +function tableExists(string $table): bool { $res = Database::simpleQuery("SHOW TABLES", array(), true); while ($row = $res->fetch(PDO::FETCH_NUM)) { @@ -141,8 +150,9 @@ function tableExists($table) return false; } -function tableRename($old, $new) { - return Database::simpleQuery("RENAME TABLE $old TO $new", []); +function tableRename(string $old, string $new): bool +{ + return Database::simpleQuery("RENAME TABLE $old TO $new", []) !== false; } @@ -155,7 +165,7 @@ function tableRename($old, $new) { * @param string $refColumn referenced column * @return false|string[] false == doesn't exist, assoc array otherwise */ -function tableGetConstraints($table, $column, $refTable, $refColumn) +function tableGetConstraints(string $table, string $column, string $refTable, string $refColumn) { $db = 'openslx'; if (defined('CONFIG_SQL_DB')) { @@ -188,21 +198,22 @@ function tableGetConstraints($table, $column, $refTable, $refColumn) * @param string $actions "ON xxx ON yyy" string * @return string UPDATE_* result code */ -function tableAddConstraint($table, $column, $refTable, $refColumn, $actions, $ignoreError = false, $name = '') +function tableAddConstraint(string $table, string $column, string $refTable, string $refColumn, string $actions, + bool $ignoreError = false, $name = ''): string { $test = tableExists($refTable) && tableHasColumn($refTable, $refColumn); if ($test === false) { - // Most likely, destination table does not exist yet or isn't up to date + // Most likely, destination table does not exist yet or isn't up-to-date return UPDATE_RETRY; } // TODO: Refactor function, make this two args $update = 'RESTRICT'; $delete = 'RESTRICT'; - if (preg_match('/on\s+update\s+(RESTRICT|SET\s+NULL|CASCADE)/ims', $actions, $out)) { - $update = preg_replace('/\s+/ms', ' ', strtoupper($out[1])); + if (preg_match('/on\s+update\s+(RESTRICT|SET\s+NULL|CASCADE)/im', $actions, $out)) { + $update = preg_replace('/\s+/m', ' ', strtoupper($out[1])); } - if (preg_match('/on\s+delete\s+(RESTRICT|SET\s+NULL|CASCADE)/ims', $actions, $out)) { - $delete = preg_replace('/\s+/ms', ' ', strtoupper($out[1])); + if (preg_match('/on\s+delete\s+(RESTRICT|SET\s+NULL|CASCADE)/im', $actions, $out)) { + $delete = preg_replace('/\s+/m', ' ', strtoupper($out[1])); } $test = tableGetConstraints($table, $column, $refTable, $refColumn); if ($test !== false) { @@ -239,9 +250,8 @@ function tableAddConstraint($table, $column, $refTable, $refColumn, $actions, $i if ($ret === false) { if ($ignoreError) { return UPDATE_FAILED; - } else { - finalResponse(UPDATE_FAILED, "Cannot add constraint $table.$column -> $refTable.$refColumn: " . Database::lastError()); } + finalResponse(UPDATE_FAILED, "Cannot add constraint $table.$column -> $refTable.$refColumn: " . Database::lastError()); } return UPDATE_DONE; } @@ -253,12 +263,12 @@ function tableAddConstraint($table, $column, $refTable, $refColumn, $actions, $i * @param string $constraint constraint name * @return bool success indicator */ -function tableDeleteConstraint($table, $constraint) +function tableDeleteConstraint(string $table, string $constraint): bool { return Database::exec("ALTER TABLE `$table` DROP FOREIGN KEY `$constraint`") !== false; } -function tableCreate($table, $structure, $fatalOnError = true) +function tableCreate(string $table, string $structure, bool $fatalOnError = true): string { if (tableExists($table)) { return UPDATE_NOOP; @@ -273,7 +283,8 @@ function tableCreate($table, $structure, $fatalOnError = true) return UPDATE_FAILED; } -function responseFromArray($array) +#[NoReturn] +function responseFromArray(array $array) { if (in_array(UPDATE_FAILED, $array)) { finalResponse(UPDATE_FAILED, 'Update failed!'); @@ -286,7 +297,6 @@ function responseFromArray($array) } finalResponse(UPDATE_NOOP, 'Everything already up to date'); - } /* @@ -329,19 +339,12 @@ if (!Database::init(true)) { // Good to go so far -/** - * @param \Module $module - * @return bool - */ -function hasUpdateScript($module) +function hasUpdateScript(Module $module): bool { return is_readable($module->getDir() . '/install.inc.php'); } -/** - * @param Module $module - */ -function runUpdateScript($module) +function runUpdateScript(Module $module): void { require_once $module->getDir() . '/install.inc.php'; } diff --git a/modules-available/adduser/page.inc.php b/modules-available/adduser/page.inc.php index 499436ff..0ef28a3e 100644 --- a/modules-available/adduser/page.inc.php +++ b/modules-available/adduser/page.inc.php @@ -215,13 +215,13 @@ class Page_AddUser extends Page } } - private function showRoles($userid = false) + private function showRoles(int $userid = null): void { if (!Module::isAvailable('permissionmanager')) return; if (!User::hasPermission('.permissionmanager.users.edit-roles')) return; - $data = ['roles' => PermissionUtil::getRoles($userid, false)]; + $data = ['roles' => PermissionUtil::getRoles($userid)]; Render::addTemplate('user-permissions', $data); } diff --git a/modules-available/baseconfig/inc/baseconfig.inc.php b/modules-available/baseconfig/inc/baseconfig.inc.php index 2e8efeda..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,7 +80,7 @@ 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, ]; }); @@ -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 ee883895..be71c3df 100644 --- a/modules-available/baseconfig/inc/validator.inc.php +++ b/modules-available/baseconfig/inc/validator.inc.php @@ -38,7 +38,6 @@ class Validator default: ErrorHandler::traceError('Unknown validation method: ' . $data[0]); } - return false; // make code inspector happy - doesn't know traceError doesn't return } @@ -64,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) === '\\\\') @@ -89,7 +88,7 @@ class Validator return $displayValue; return false; } - private static function validateMultiList(string $list, string &$displayValue): string + private static function validateMultiList(string $list, array &$displayValue): string { $allowedValues = explode('|', $list); $values = []; diff --git a/modules-available/baseconfig/page.inc.php b/modules-available/baseconfig/page.inc.php index 8a9a7534..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) ); } } @@ -153,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( @@ -165,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); @@ -260,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; @@ -280,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); diff --git a/modules-available/baseconfig_bwidm/hooks/translation.inc.php b/modules-available/baseconfig_bwidm/hooks/translation.inc.php index a53500fc..da7c70af 100644 --- a/modules-available/baseconfig_bwidm/hooks/translation.inc.php +++ b/modules-available/baseconfig_bwidm/hooks/translation.inc.php @@ -16,10 +16,8 @@ $HANDLER['subsections'] = array( /** * Configuration categories. - * @param \Module $module - * @return array */ -$HANDLER['grep_config-variable-categories'] = function($module) { +$HANDLER['grep_config-variable-categories'] = function (Module $module): array { if (!$module->activate(1, false)) return array(); $want = BaseConfigUtil::getCategories($module); @@ -31,10 +29,8 @@ $HANDLER['grep_config-variable-categories'] = function($module) { /** * Configuration variables. - * @param \Module $module - * @return array */ -$HANDLER['grep_config-variables'] = function($module) { +$HANDLER['grep_config-variables'] = function (Module $module): array { if (!$module->activate(1, false)) return array(); $want = BaseConfigUtil::getVariables($module); diff --git a/modules-available/baseconfig_bwlp/hooks/translation.inc.php b/modules-available/baseconfig_bwlp/hooks/translation.inc.php index a53500fc..da7c70af 100644 --- a/modules-available/baseconfig_bwlp/hooks/translation.inc.php +++ b/modules-available/baseconfig_bwlp/hooks/translation.inc.php @@ -16,10 +16,8 @@ $HANDLER['subsections'] = array( /** * Configuration categories. - * @param \Module $module - * @return array */ -$HANDLER['grep_config-variable-categories'] = function($module) { +$HANDLER['grep_config-variable-categories'] = function (Module $module): array { if (!$module->activate(1, false)) return array(); $want = BaseConfigUtil::getCategories($module); @@ -31,10 +29,8 @@ $HANDLER['grep_config-variable-categories'] = function($module) { /** * Configuration variables. - * @param \Module $module - * @return array */ -$HANDLER['grep_config-variables'] = function($module) { +$HANDLER['grep_config-variables'] = function (Module $module): array { if (!$module->activate(1, false)) return array(); $want = BaseConfigUtil::getVariables($module); diff --git a/modules-available/dnbd3/baseconfig/getconfig.inc.php b/modules-available/dnbd3/baseconfig/getconfig.inc.php index eecb4642..eff821fc 100644 --- a/modules-available/dnbd3/baseconfig/getconfig.inc.php +++ b/modules-available/dnbd3/baseconfig/getconfig.inc.php @@ -1,5 +1,8 @@ <?php +/** @var ?string $uuid */ +/** @var ?string $ip */ + if (Dnbd3::isEnabled()) { if (!Dnbd3::hasNfsFallback()) { ConfigHolder::add("SLX_VM_NFS", false, 1000); @@ -12,7 +15,7 @@ if (Dnbd3::isEnabled()) { // Locations from closest to furthest (order) $locations = ConfigHolder::get('SLX_LOCATIONS'); -if ($locations === false) { +if ($locations === null) { $locationIds = [0]; } else { $locationIds = explode(' ', $locations); @@ -50,7 +53,7 @@ foreach ($res as $row) { $row['locationid'] = $serverLoc; } } - $old = isset($servers[$ip]) ? $servers[$ip] : PHP_INT_MAX; + $old = $servers[$ip] ?? PHP_INT_MAX; if (is_null($row['locationid']) || !isset($locationsAssoc[$row['locationid']])) { $servers[$ip] = min($defPrio . '.' . mt_rand(), $old); } else { diff --git a/modules-available/dnbd3/hooks/translation.inc.php b/modules-available/dnbd3/hooks/translation.inc.php index cb1854b4..9ff593cf 100644 --- a/modules-available/dnbd3/hooks/translation.inc.php +++ b/modules-available/dnbd3/hooks/translation.inc.php @@ -16,10 +16,8 @@ $HANDLER['subsections'] = array( /** * Configuration variables. - * @param \Module $module - * @return array */ -$HANDLER['grep_config-variables'] = function($module) { +$HANDLER['grep_config-variables'] = function(Module $module): array { if (!$module->activate(1, false) || !Module::isAvailable('baseconfig')) return array(); $want = BaseConfigUtil::getVariables($module); diff --git a/modules-available/dnbd3/inc/dnbd3rpc.inc.php b/modules-available/dnbd3/inc/dnbd3rpc.inc.php index a26ae4fd..f6bbf0ca 100644 --- a/modules-available/dnbd3/inc/dnbd3rpc.inc.php +++ b/modules-available/dnbd3/inc/dnbd3rpc.inc.php @@ -18,17 +18,9 @@ class Dnbd3Rpc { // Special case - local server if ($server === '<self>') { $server = '127.0.0.1:5003'; - } elseif (($out = Dnbd3Util::matchAddress($server))) { - if (isset($out['v4'])) { - $server = $out['v4']; - } else { - $server = '[' . $out['v6'] . ']'; - } - if (isset($out['port'])) { - $server .= $out['port']; - } else { - $server .= ':5003'; - } + } elseif (($out = Dnbd3Util::matchAddress($server)) !== false) { + $server = $out['v4'] ?? '[' . $out['v6'] . ']'; + $server .= $out['port'] ?? ':5003'; } return $server; } @@ -72,7 +64,6 @@ class Dnbd3Rpc { /** * Get statistics for multiple servers at once. * @param string[] $servers - * @return array */ public static function getStatsMulti(array $servers, array $queryOptions = [], int $timeout = 2): array { @@ -91,7 +82,7 @@ class Dnbd3Rpc { $url = 'http://' . self::translateServer($server) . '/query?q=version' . $extra; $res = curl_init($url); if ($res === false) { - error_log("curl_init($url) failed with $res"); + error_log("curl_init($url) failed"); continue; } curl_setopt_array($res, [ diff --git a/modules-available/dnbd3/inc/dnbd3util.inc.php b/modules-available/dnbd3/inc/dnbd3util.inc.php index 90940e8a..47d7a4ea 100644 --- a/modules-available/dnbd3/inc/dnbd3util.inc.php +++ b/modules-available/dnbd3/inc/dnbd3util.inc.php @@ -108,11 +108,9 @@ class Dnbd3Util { /** * A client is booting that has runmode dnbd3 proxy - set config vars accordingly. * - * @param string $machineUuid * @param string $mode always 'proxy' - * @param string $modeData */ - public static function runmodeConfigHook($machineUuid, $mode, $modeData) + public static function runmodeConfigHook(string $machineUuid, string $mode, string $modeData) { $self = Property::getServerIp(); // Get all directly assigned locations @@ -125,7 +123,7 @@ class Dnbd3Util { $assignedLocs[] = $row['locationid']; } $modeData = (array)json_decode($modeData, true) + self::defaultRunmodeConfig(); - if (!empty($assignedLocs) && isset($modeData['firewall']) && $modeData['firewall']) { + if (!empty($assignedLocs) && ($modeData['firewall'] ?? false)) { // Get all sub-locations too $recursiveLocs = $assignedLocs; $locations = Location::getLocationsAssoc(); @@ -215,10 +213,10 @@ class Dnbd3Util { * @param int $end end address * @return string CIDR notation */ - private static function range2Cidr($start, $end) + private static function range2Cidr(int $start, int $end): string { if (PHP_INT_SIZE > 4) { - $bin = decbin((int)$start ^ (int)$end); + $bin = decbin($start ^ $end); } else { $bin = decbin((int)(float)$start ^ (int)(float)$end); } @@ -258,12 +256,15 @@ class Dnbd3Util { $ranges[] = $row; } - public static function defaultRunmodeConfig() + /** + * @return array{bgr: bool, firewall: bool} + */ + public static function defaultRunmodeConfig(): array { - return array( + return [ 'bgr' => true, 'firewall' => false - ); + ]; } public static function matchAddress($server) diff --git a/modules-available/dnbd3/page.inc.php b/modules-available/dnbd3/page.inc.php index 35f03199..ffaa995e 100644 --- a/modules-available/dnbd3/page.inc.php +++ b/modules-available/dnbd3/page.inc.php @@ -361,6 +361,7 @@ class Page_Dnbd3 extends Page $loc['clientCount'] = 0; $loc['recCount'] = 0; } + unset($loc); $showLocs = false; foreach ($res as $row) { settype($row['locationid'], 'int'); diff --git a/modules-available/dozmod/api.inc.php b/modules-available/dozmod/api.inc.php index 90e663aa..afc53853 100644 --- a/modules-available/dozmod/api.inc.php +++ b/modules-available/dozmod/api.inc.php @@ -10,6 +10,8 @@ **/ +use JetBrains\PhpStorm\NoReturn; + if (!Module::isAvailable('locations')) { die('require locations module'); } @@ -21,17 +23,17 @@ $availableRessources = ['list', 'netrules', 'metadata', 'imagemeta']; /* BEGIN: A simple caching mechanism ---------------------------- */ -function cache_hash($obj) +function cache_hash($obj): string { return md5(serialize($obj)); } -function cache_key_to_filename($key) +function cache_key_to_filename(string $key): string { return "/tmp/bwlp-slxadmin-cache-$key"; } -function cache_put($key, $value) +function cache_put(string $key, string $value): void { $filename = cache_key_to_filename($key); // Try to avoid another client concurrently accessing the cache seeing an empty file @@ -40,7 +42,7 @@ function cache_put($key, $value) rename($tmp, $filename); } -function cache_has($key) +function cache_has(string $key): bool { $filename = cache_key_to_filename($key); $mtime = @filemtime($filename); @@ -49,21 +51,18 @@ function cache_has($key) return false; // cache miss } $now = time(); - if ($now < $mtime || $now - $mtime > CONFIG_DOZMOD_EXPIRE) { - return false; - } else { - return true; - } + return $now >= $mtime && $now - $mtime <= CONFIG_DOZMOD_EXPIRE; } -function cache_get($key) +function cache_get(string $key): string { $filename = cache_key_to_filename($key); return file_get_contents($filename); } /* good for large binary files */ -function cache_get_passthru($key) +#[NoReturn] +function cache_get_passthru(string $key): void { $filename = cache_key_to_filename($key); $fp = fopen($filename, "r"); @@ -88,11 +87,16 @@ function cache_get_passthru($key) * Takes raw lecture list xml, returns array of uuids. * * @param string $responseXML XML from dozmod server - * @return array list of UUIDs, false on error + * @return array list of UUIDs */ -function xmlToLectureIds($responseXML) +function xmlToLectureIds(string $responseXML): array { - $xml = new SimpleXMLElement($responseXML); + try { + $xml = new SimpleXMLElement($responseXML); + } catch (Exception $e) { + EventLog::warning('Error parsing XML response data from DMSD: ' . $e->getMessage(), $responseXML); + return []; + } if (!isset($xml->eintrag)) return []; @@ -105,7 +109,8 @@ function xmlToLectureIds($responseXML) return $uuids; } -function sendExamModeMismatch() +#[NoReturn] +function sendExamModeMismatch(): void { Header('Content-Type: text/xml; charset=utf-8'); echo @@ -145,7 +150,7 @@ BLA; } /** Caching wrapper around _getLecturesForLocations() */ -function getListForLocations($locationIds, $raw) +function getListForLocations(array $locationIds, bool $raw) { /* if in any of the locations there is an exam active, consider the client to be in "exam-mode" and only offer him exams (no lectures) */ @@ -199,20 +204,20 @@ function getListForLocations($locationIds, $raw) return $list; } -function getLectureUuidsForLocations($locationIds) +function getLectureUuidsForLocations(array $locationIds) { return getListForLocations($locationIds, false); } -function outputLectureXmlForLocation($locationIds) +function outputLectureXmlForLocation(array $locationIds) { return getListForLocations($locationIds, true); } -function _getVmData($lecture_uuid, $subResource = false) +function _getVmData(string $lecture_uuid, string $subResource = null) { $url = VMX_URL . '/' . $lecture_uuid; - if ($subResource !== false) { + if ($subResource !== null) { $url .= '/' . $subResource; } $t = microtime(true); @@ -229,7 +234,7 @@ function _getVmData($lecture_uuid, $subResource = false) } /** Caching wrapper around _getVmData() **/ -function outputResource($lecture_uuid, $resource) +function outputResource(string $lecture_uuid, string $resource): void { if ($resource === 'metadata') { // HACK: config.tgz is compressed, don't use gzip output handler @@ -250,7 +255,7 @@ function outputResource($lecture_uuid, $resource) } else { $value = _getVmData($lecture_uuid, $resource); if ($value === false) - return false; + return; if (is_int($value)) { http_response_code($value); exit; @@ -258,16 +263,16 @@ function outputResource($lecture_uuid, $resource) cache_put($key, $value); die($value); } - return false; } +#[NoReturn] function fatalDozmodUnreachable() { Header('HTTP/1.1 504 Gateway Timeout'); die('DMSD currently not available'); } -function readLectureParam($locationIds) +function readLectureParam(array $locationIds): string { $lecture = Request::get('lecture', false, 'string'); if ($lecture === false) { @@ -290,7 +295,7 @@ function readLectureParam($locationIds) // in this context the lecture param is an image id (container), // just read and check if valid. // TODO do we need to check if this is allowed? -function readImageParam() +function readImageParam(): string { $image = Request::get('lecture', false, 'string'); @@ -335,6 +340,3 @@ if ($resource === 'list') { outputResource($lecture, $resource); } fatalDozmodUnreachable(); - -Header('HTTP/1.1 400 Bad Request'); -die("I don't know how to give you that resource"); diff --git a/modules-available/dozmod/page.inc.php b/modules-available/dozmod/page.inc.php index bf2a6fa4..4a43d881 100644 --- a/modules-available/dozmod/page.inc.php +++ b/modules-available/dozmod/page.inc.php @@ -68,7 +68,7 @@ class Page_DozMod extends Page /* add sub-menus */ foreach ($this->validSections as $section) { if ($section !== 'special' && User::hasPermission($section . '.*')) { - Dashboard::addSubmenu('?do=dozmod§ion=' . $section, Dictionary::translate('submenu_' . $section, true)); + Dashboard::addSubmenu('?do=dozmod§ion=' . $section, Dictionary::translate('submenu_' . $section)); } } } diff --git a/modules-available/dozmod/pages/actionlog.inc.php b/modules-available/dozmod/pages/actionlog.inc.php index 0b6feb6f..182198c2 100644 --- a/modules-available/dozmod/pages/actionlog.inc.php +++ b/modules-available/dozmod/pages/actionlog.inc.php @@ -92,7 +92,7 @@ class SubPage return $desc; } - private static function addImageHeader() + private static function addImageHeader(): bool { $image = Database::queryFirst('SELECT o.userid AS ouserid, o.firstname AS ofirstname, o.lastname AS olastname, u.userid AS uuserid, u.firstname AS ufirstname, u.lastname AS ulastname, @@ -114,7 +114,7 @@ class SubPage return $image !== false; } - private static function addLectureHeader() + private static function addLectureHeader(): bool { $lecture = Database::queryFirst('SELECT o.userid AS ouserid, o.firstname AS ofirstname, o.lastname AS olastname, u.userid AS uuserid, u.firstname AS ufirstname, u.lastname AS ulastname, diff --git a/modules-available/dozmod/pages/expiredimages.inc.php b/modules-available/dozmod/pages/expiredimages.inc.php index b61b863b..ab563273 100644 --- a/modules-available/dozmod/pages/expiredimages.inc.php +++ b/modules-available/dozmod/pages/expiredimages.inc.php @@ -8,7 +8,7 @@ class SubPage } - private static function loadExpiredImages() + private static function loadExpiredImages(): array { $res = Database::simpleQuery("SELECT b.displayname, own.firstname, own.lastname, own.userid, diff --git a/modules-available/dozmod/pages/mailconfig.inc.php b/modules-available/dozmod/pages/mailconfig.inc.php index 08205f2e..aa03a4d3 100644 --- a/modules-available/dozmod/pages/mailconfig.inc.php +++ b/modules-available/dozmod/pages/mailconfig.inc.php @@ -34,7 +34,7 @@ class SubPage Util::redirect('?do=DozMod§ion=mailconfig'); } - private static function cleanMailArray() + private static function cleanMailArray(): array { $keys = array('host', 'port', 'ssl', 'senderAddress', 'replyTo', 'username', 'password', 'serverName'); $data = array(); diff --git a/modules-available/dozmod/pages/templates.inc.php b/modules-available/dozmod/pages/templates.inc.php index b857115f..b916e14c 100644 --- a/modules-available/dozmod/pages/templates.inc.php +++ b/modules-available/dozmod/pages/templates.inc.php @@ -69,7 +69,7 @@ class SubPage ]); } - private static function forcmp($string) + private static function forcmp(string $string): string { return trim(str_replace("\r\n", "\n", $string)); } diff --git a/modules-available/dozmod/pages/users.inc.php b/modules-available/dozmod/pages/users.inc.php index cdf22b9d..fe00a71b 100644 --- a/modules-available/dozmod/pages/users.inc.php +++ b/modules-available/dozmod/pages/users.inc.php @@ -64,13 +64,13 @@ class SubPage . ' ORDER BY displayname ASC'); $rows = array(); foreach ($res as $row) { - $row['canlogin'] = self::checked($row['canlogin']); + $row['canlogin'] = self::checked((bool)$row['canlogin']); $rows[] = $row; } Render::addTemplate('orglist', array('organizations' => $rows)); } - private static function checked($val) + private static function checked(bool $val): string { if ($val) return 'checked="checked"'; diff --git a/modules-available/eventlog/inc/filterruleprocessor.inc.php b/modules-available/eventlog/inc/filterruleprocessor.inc.php index 24b37444..dd0160d7 100644 --- a/modules-available/eventlog/inc/filterruleprocessor.inc.php +++ b/modules-available/eventlog/inc/filterruleprocessor.inc.php @@ -254,7 +254,7 @@ class FilterRuleProcessor * @param array $filter filter struct [op, arg, result] * @return ?array null if op doesn't match, processed result otherwise */ - private static function matches(string $item, array $filter) + private static function matches(string $item, array $filter): ?array { $ok = false; switch ($filter['op']) { @@ -291,7 +291,7 @@ class FilterRuleProcessor if ($filter['op'] !== 'regex') { $out = [1 => $item]; } - return $out; + return $out ?? []; } private static function fillTemplate(string $template, array $values): string diff --git a/modules-available/eventlog/pages/log.inc.php b/modules-available/eventlog/pages/log.inc.php index bfb16d11..66826b08 100644 --- a/modules-available/eventlog/pages/log.inc.php +++ b/modules-available/eventlog/pages/log.inc.php @@ -26,7 +26,7 @@ class SubPage )); } - private static function typeToIcon($type) + private static function typeToIcon(string $type): string { switch ($type) { case 'info': @@ -40,7 +40,7 @@ class SubPage } } - private static function typeToColor($type) + private static function typeToColor(string $type): string { switch ($type) { case 'warning': diff --git a/modules-available/exams/baseconfig/getconfig.inc.php b/modules-available/exams/baseconfig/getconfig.inc.php index 120bdbff..748149ad 100644 --- a/modules-available/exams/baseconfig/getconfig.inc.php +++ b/modules-available/exams/baseconfig/getconfig.inc.php @@ -1,14 +1,17 @@ <?php -$foofoo = function($machineUuid) { +/** @var ?string $uuid */ +/** @var ?string $ip */ + +if ($uuid !== null) { // Leave clients in any runmode alone $res = Database::queryFirst('SELECT machineuuid FROM runmode WHERE machineuuid = :uuid', - array('uuid' => $machineUuid), true); + array('uuid' => $uuid), true); if (is_array($res)) return; // Check if exam mode should apply $locations = ConfigHolder::get('SLX_LOCATIONS'); - if ($locations === false) { + if ($locations === null) { $locationIds = []; } else { $locationIds = explode(' ', $locations); @@ -26,6 +29,4 @@ $foofoo = function($machineUuid) { // No saver ConfigHolder::add('SLX_SCREEN_SAVER_TIMEOUT', '0', 1000); } -}; - -$foofoo($uuid);
\ No newline at end of file +}
\ No newline at end of file diff --git a/modules-available/exams/inc/exams.inc.php b/modules-available/exams/inc/exams.inc.php index da4dec85..86dc6d89 100644 --- a/modules-available/exams/inc/exams.inc.php +++ b/modules-available/exams/inc/exams.inc.php @@ -4,14 +4,11 @@ class Exams { /** - * @param int[] of location ids. must bot be an associative array. - * @return: bool true iff for any of the given location ids an exam is scheduled. + * @param int[] $locationIds of location ids. must be an associative array. + * @return bool true iff for any of the given location ids an exam is scheduled. **/ - public static function isInExamMode($locationIds, &$lectureId = false, &$autoLogin = false) + public static function isInExamMode(array $locationIds, &$lectureId = false, &$autoLogin = false): bool { - if (!is_array($locationIds)) { - $locationIds = array($locationIds); - } if (empty($locationIds)) { $locationIds[] = 0; } diff --git a/modules-available/exams/page.inc.php b/modules-available/exams/page.inc.php index 458ae5b1..d229b883 100644 --- a/modules-available/exams/page.inc.php +++ b/modules-available/exams/page.inc.php @@ -103,7 +103,7 @@ class Page_Exams extends Page } // returns true if user is allowed to edit the exam - protected function userCanEditExam($examid = NULL) + protected function userCanEditExam(string $examid = NULL): bool { if (in_array(0, $this->userEditLocations)) // Trivial case -- don't query if global perms return true; @@ -118,9 +118,12 @@ class Page_Exams extends Page return true; } - // checks if user is allowed to save an exam with all the locations - // needs information if it's add (second para = true) or edit (second para = false) - protected function userCanEditLocation($locationids) { + /** + * checks if user is allowed to save an exam with all the locations + * needs information if it's add (second para = true) or edit (second para = false) + */ + protected function userCanEditLocation(array $locationids): bool + { return empty(array_diff($locationids, $this->userEditLocations)); } @@ -213,7 +216,10 @@ class Page_Exams extends Page return json_encode($out); } - protected function makeExamsForTemplate() + /** + * @return array{exams: array, decollapse: bool} + */ + protected function makeExamsForTemplate(): array { $out = []; $now = time(); @@ -248,7 +254,7 @@ class Page_Exams extends Page return ['exams' => $out, 'decollapse' => $hasCollapsed]; } - protected function makeLectureExamList() + protected function makeLectureExamList(): array { $out = []; $now = time(); @@ -288,7 +294,7 @@ class Page_Exams extends Page ] + $source; } - private function isDateSane($time) + private function isDateSane(int $time): bool { return ($time >= strtotime('-10 years') && $time <= strtotime('+10 years')); } diff --git a/modules-available/locationinfo/api.inc.php b/modules-available/locationinfo/api.inc.php index 14be7718..24919ba1 100644 --- a/modules-available/locationinfo/api.inc.php +++ b/modules-available/locationinfo/api.inc.php @@ -14,7 +14,7 @@ function HandleParameters() $get = Request::get('get', 0, 'string'); $uuid = Request::get('uuid', false, 'string'); - $output = false; + $output = null; if ($get === "timestamp") { $output = array('ts' => getLastChangeTs($uuid)); } elseif ($get === "machines") { @@ -24,7 +24,7 @@ function HandleParameters() $output = array_values($output); } elseif ($get === "config") { $type = InfoPanel::getConfig($uuid, $output); - if ($type === false) { + if ($type === null) { http_response_code(404); die('Panel not found'); } @@ -38,7 +38,7 @@ function HandleParameters() $locationIds = LocationInfo::getLocationsOr404($uuid); $output = LocationInfo::getCalendar($locationIds); } - if ($output !== false) { + if ($output !== null) { Header('Content-Type: application/json; charset=utf-8'); echo json_encode($output); } else { @@ -59,7 +59,7 @@ function HandleParameters() * @param string $paneluuid panels uuid * @return int UNIX_TIMESTAMP */ -function getLastChangeTs($paneluuid) +function getLastChangeTs(string $paneluuid): int { $panel = Database::queryFirst('SELECT lastchange, locationids FROM locationinfo_panel WHERE paneluuid = :paneluuid', compact('paneluuid')); @@ -84,7 +84,7 @@ function getLastChangeTs($paneluuid) * @param int[] $idList list of the location ids. * @return array aggregated PC states */ -function getPcStates($idList, $paneluuid) +function getPcStates(array $idList, string $paneluuid): array { $pcStates = array(); foreach ($idList as $id) { @@ -130,7 +130,7 @@ function getPcStates($idList, $paneluuid) * @param int[] $idList Array list of the locations. * @return array location tree data */ -function getLocationTree($idList) +function getLocationTree(array $idList): array { if (in_array(0, $idList)) { return array_values(Location::getTree()); @@ -140,7 +140,7 @@ function getLocationTree($idList) return findLocations($locations, $idList); } -function findLocations($locations, $idList) +function findLocations(array $locations, array $idList): array { $ret = array(); foreach ($locations as $location) { diff --git a/modules-available/locationinfo/exchange-includes/jamesiarmes/PhpEws/ArrayType/ArrayOfStringsType.php b/modules-available/locationinfo/exchange-includes/jamesiarmes/PhpEws/ArrayType/ArrayOfStringsType.php index 6443d31d..28792929 100644 --- a/modules-available/locationinfo/exchange-includes/jamesiarmes/PhpEws/ArrayType/ArrayOfStringsType.php +++ b/modules-available/locationinfo/exchange-includes/jamesiarmes/PhpEws/ArrayType/ArrayOfStringsType.php @@ -32,6 +32,6 @@ class ArrayOfStringsType extends ArrayType */ public function __toString() { - return $this->String; + return implode(' + ', $this->String); } } diff --git a/modules-available/locationinfo/exchange-includes/jamesiarmes/PhpNtlm/SoapClient.php b/modules-available/locationinfo/exchange-includes/jamesiarmes/PhpNtlm/SoapClient.php index 21c77cbf..98f23dfa 100644 --- a/modules-available/locationinfo/exchange-includes/jamesiarmes/PhpNtlm/SoapClient.php +++ b/modules-available/locationinfo/exchange-includes/jamesiarmes/PhpNtlm/SoapClient.php @@ -26,6 +26,9 @@ class SoapClient extends \SoapClient */ protected $options; + protected $__last_response; + protected $__last_request_headers; + /** * {@inheritdoc} * @@ -68,7 +71,7 @@ class SoapClient extends \SoapClient /** * {@inheritdoc} */ - public function __doRequest($request, $location, $action, $version, $one_way = 0) + public function __doRequest($request, $location, $action, $version, $oneWay = 0) { $headers = $this->buildHeaders($action); $this->__last_request = $request; diff --git a/modules-available/locationinfo/inc/coursebackend.inc.php b/modules-available/locationinfo/inc/coursebackend.inc.php index 04b5aa92..ea1bebac 100644 --- a/modules-available/locationinfo/inc/coursebackend.inc.php +++ b/modules-available/locationinfo/inc/coursebackend.inc.php @@ -152,10 +152,6 @@ abstract class CourseBackend /** * In case you want to sanitize or otherwise mangle a property for your backend, * override this. - * - * @param string $prop - * @param $value - * @return mixed */ public function mangleProperty(string $prop, $value) { @@ -179,9 +175,9 @@ abstract class CourseBackend * Method for fetching the schedule of the given rooms on a server. * * @param array $requestedLocationIds array of room ID to fetch - * @return array|bool array containing the timetables as value and roomid as key as result, or false on error + * @return array array containing the timetables as value and roomid as key as result, or false on error */ - public final function fetchSchedule(array $requestedLocationIds) + public final function fetchSchedule(array $requestedLocationIds): array { if (empty($requestedLocationIds)) return array(); @@ -236,9 +232,6 @@ abstract class CourseBackend ]); } $backendResponse = $this->fetchSchedulesInternal(array_unique($remoteIds)); - if ($backendResponse === false) { - return false; - } // Fetching might have taken a while, get current time again $NOW = time(); diff --git a/modules-available/locationinfo/inc/coursebackend/coursebackend_davinci.inc.php b/modules-available/locationinfo/inc/coursebackend/coursebackend_davinci.inc.php index f03444c2..786ab459 100644 --- a/modules-available/locationinfo/inc/coursebackend/coursebackend_davinci.inc.php +++ b/modules-available/locationinfo/inc/coursebackend/coursebackend_davinci.inc.php @@ -68,7 +68,7 @@ class CourseBackend_Davinci extends CourseBackend * @param string $roomId unique name of the room, as used by davinci * @param \DateTime $startDate start date to fetch * @param \DateTime $endDate end date of range to fetch - * @return array|bool if successful the array representation of the timetable + * @return false|string if successful the array representation of the timetable */ private function fetchRoomRaw(string $roomId, DateTime $startDate, DateTime $endDate) { diff --git a/modules-available/locationinfo/inc/coursebackend/coursebackend_exchange.inc.php b/modules-available/locationinfo/inc/coursebackend/coursebackend_exchange.inc.php index 5920231f..df33dadd 100755 --- a/modules-available/locationinfo/inc/coursebackend/coursebackend_exchange.inc.php +++ b/modules-available/locationinfo/inc/coursebackend/coursebackend_exchange.inc.php @@ -173,8 +173,13 @@ class CourseBackend_Exchange extends CourseBackend // Iterate over the events that were found, printing some data for each. foreach ($items as $item) { - $start = new DateTime($item->Start); - $end = new DateTime($item->End); + try { + $start = new DateTime($item->Start); + $end = new DateTime($item->End); + } catch (Exception $e) { + $this->addError("Invalid date range: '{$item->Start}' -> '{$item->End}'", false); + continue; + } $schedules[$roomId][] = array( 'title' => $item->Subject, diff --git a/modules-available/locationinfo/inc/icalcoursebackend.inc.php b/modules-available/locationinfo/inc/icalcoursebackend.inc.php index 44691bb4..838d18b7 100644 --- a/modules-available/locationinfo/inc/icalcoursebackend.inc.php +++ b/modules-available/locationinfo/inc/icalcoursebackend.inc.php @@ -18,16 +18,6 @@ abstract class ICalCourseBackend extends CourseBackend /** @var bool|resource */ private $curlHandle = false; - /** - * Initialize values - * - * @param string $location - * @param bool $verifyCert - * @param bool $verifyHostname - * @param string $authMethod - * @param string $user - * @param string $pass - */ protected function init( string $location, bool $verifyCert, bool $verifyHostname, string $authMethod = 'NONE', string $user = '', string $pass = '') @@ -52,11 +42,18 @@ abstract class ICalCourseBackend extends CourseBackend { if (!$this->isOK()) return null; + + try { + $ical = new ICalParser(['filterDaysBefore' => 7, 'filterDaysAfter' => 7]); + } catch (Exception $e) { + $this->addError('Error instantiating ICalParser: ' . $e->getMessage(), true); + return null; + } + if ($this->curlHandle === false) { $this->curlHandle = curl_init(); } - $ical = new ICalParser(['filterDaysBefore' => 7, 'filterDaysAfter' => 7]); $options = [ CURLOPT_WRITEFUNCTION => function ($ch, $data) use ($ical) { $ical->feedData($data); @@ -119,8 +116,6 @@ abstract class ICalCourseBackend extends CourseBackend /** * Get a usable title from either SUMMARY or DESCRIPTION - * - * @param ICalEvent $event */ protected function toTitle(ICalEvent $event): string { diff --git a/modules-available/locationinfo/inc/icalevent.inc.php b/modules-available/locationinfo/inc/icalevent.inc.php index 0c234f48..c5aea349 100644 --- a/modules-available/locationinfo/inc/icalevent.inc.php +++ b/modules-available/locationinfo/inc/icalevent.inc.php @@ -153,10 +153,10 @@ class ICalEvent /** * Magic getter method * - * @param string $additionalPropertyName + * @param string $additionalPropertyName * @return mixed */ - public function __get($additionalPropertyName) + public function __get(string $additionalPropertyName) { if (array_key_exists($additionalPropertyName, $this->additionalProperties)) { return $this->additionalProperties[$additionalPropertyName]; @@ -167,11 +167,8 @@ class ICalEvent /** * Magic isset method - * - * @param string $name - * @return boolean */ - public function __isset($name) + public function __isset(string $name): bool { return is_null($this->$name) === false; } diff --git a/modules-available/locationinfo/inc/icalparser.inc.php b/modules-available/locationinfo/inc/icalparser.inc.php index 69ff84d0..c6d94a12 100644 --- a/modules-available/locationinfo/inc/icalparser.inc.php +++ b/modules-available/locationinfo/inc/icalparser.inc.php @@ -989,9 +989,8 @@ class ICalParser } return $matches; - } else { - return null; // Ignore this match } + return null; // Ignore this match } /** @@ -1968,9 +1967,8 @@ class ICalParser { if (empty($event['EXDATE_array'])) { return array(); - } else { - $exdates = $event['EXDATE_array']; } + $exdates = $event['EXDATE_array']; $output = array(); $currentTimeZone = $this->defaultTimeZone; diff --git a/modules-available/locationinfo/inc/infopanel.inc.php b/modules-available/locationinfo/inc/infopanel.inc.php index 14d2d949..c0352c26 100644 --- a/modules-available/locationinfo/inc/infopanel.inc.php +++ b/modules-available/locationinfo/inc/infopanel.inc.php @@ -7,16 +7,16 @@ class InfoPanel * Gets the config of the location. * * @param int $locationID ID of the location - * @param mixed $config the panel config will be returned here - * @return string|bool paneltype, false if not exists + * @param ?array $config the panel config will be returned here + * @return ?string panel type, null if not exists */ - public static function getConfig($paneluuid, &$config) + public static function getConfig(string $paneluuid, ?array &$config): ?string { $panel = Database::queryFirst('SELECT panelname, panelconfig, paneltype, locationids FROM locationinfo_panel WHERE paneluuid = :paneluuid', compact('paneluuid')); if ($panel === false) { - return false; + return null; } $config = LocationInfo::defaultPanelConfig($panel['paneltype']); @@ -87,13 +87,10 @@ class InfoPanel * @param array $array location list to populate with machine data * @param bool $withPosition Defines if coords should be included or not. */ - public static function appendMachineData(&$array, $idList = false, $withPosition = false, $withHostname = false) + public static function appendMachineData(?array &$array, array $idList, bool $withPosition = false, bool $withHostname = false): void { - if (empty($array) && $idList === false) + if (empty($array) || empty($idList)) return; - if ($idList === false) { - $idList = array_keys($array); - } $ignoreList = array(); if (Module::isAvailable('runmode')) { @@ -217,12 +214,12 @@ class InfoPanel * @param int[] $idList location ids * @return int[] more location ids */ - private static function getLocationsWithParents($idList) + private static function getLocationsWithParents(array $idList): array { $locations = Location::getLocationsAssoc(); $allIds = $idList; foreach ($idList as $id) { - if (isset($locations[$id]) && isset($locations[$id]['parents'])) { + if (isset($locations[$id]['parents'])) { $allIds = array_merge($allIds, $locations[$id]['parents']); } } @@ -238,9 +235,9 @@ class InfoPanel * 'HourClose' => hh, 'MinutesClose' => mm } * * @param array $openingtime The opening time in the db saved format. - * @return mixed The opening time in the frontend needed format. + * @return array The opening time in the frontend needed format. */ - private static function formatOpeningtime($openingtime) + private static function formatOpeningtime(array $openingtime): array { $result = array(); foreach ($openingtime as $entry) { diff --git a/modules-available/locationinfo/inc/locationinfo.inc.php b/modules-available/locationinfo/inc/locationinfo.inc.php index 004ef881..42829a18 100644 --- a/modules-available/locationinfo/inc/locationinfo.inc.php +++ b/modules-available/locationinfo/inc/locationinfo.inc.php @@ -7,9 +7,9 @@ class LocationInfo * Gets the pc data and returns it's state. * * @param array $pc The pc data from the db. Array('state' => xx, 'lastseen' => xxx) - * @return int pc state + * @return string pc state */ - public static function getPcState($pc) + public static function getPcState(array $pc): string { $lastseen = (int)$pc['lastseen']; $NOW = time(); @@ -22,11 +22,12 @@ class LocationInfo /** * Return list of locationids associated with given panel. + * * @param string $paneluuid panel * @param bool $recursive if true and paneltype == SUMMARY the result is recursive with all child room ids. * @return int[] locationIds */ - public static function getLocationsOr404($paneluuid, $recursive = true) + public static function getLocationsOr404(string $paneluuid, bool $recursive = true): array { $panel = Database::queryFirst('SELECT paneltype, locationids FROM locationinfo_panel WHERE paneluuid = :paneluuid', compact('paneluuid')); @@ -48,7 +49,7 @@ class LocationInfo * @param int $serverId id of server * @param string|array $message error message to set, array of error message struct, null or false clears error. */ - public static function setServerError($serverId, $message) + public static function setServerError(int $serverId, $message): void { if (is_array($message)) { $fatal = false; @@ -86,7 +87,7 @@ class LocationInfo * * @return array Return a default config. */ - public static function defaultPanelConfig($type) + public static function defaultPanelConfig(string $type): array { if ($type === 'DEFAULT') { return array( diff --git a/modules-available/locationinfo/inc/locationinfohooks.inc.php b/modules-available/locationinfo/inc/locationinfohooks.inc.php index ee46260a..8ec217cc 100644 --- a/modules-available/locationinfo/inc/locationinfohooks.inc.php +++ b/modules-available/locationinfo/inc/locationinfohooks.inc.php @@ -5,9 +5,9 @@ class LocationInfoHooks /** * @param string $uuid panel uuid - * @return bool|string panel name if exists, false otherwise + * @return false|string panel name if exists, false otherwise */ - public static function getPanelName($uuid) + public static function getPanelName(string $uuid) { $ret = Database::queryFirst('SELECT panelname FROM locationinfo_panel WHERE paneluuid = :uuid', compact('uuid')); if ($ret === false) @@ -18,14 +18,11 @@ class LocationInfoHooks /** * Hook called by runmode module where we should modify the client config according to our * needs. Disable standby/logout timeouts, enable autologin, set URL. - * - * @param $machineUuid - * @param $panelUuid */ - public static function configHook($machineUuid, $panelUuid) + public static function configHook(string $machineUuid, string $panelUuid): void { $type = InfoPanel::getConfig($panelUuid, $data); - if ($type === false) + if ($type === null) return; // TODO: Invalid panel - what should we do? if ($type === 'URL') { // Check if we should set the insecure SSL mode (accept invalid/self signed certs etc.) @@ -93,10 +90,8 @@ class LocationInfoHooks /** * Turn multiline list into space separated list, removing any * comments (starting with #) - * @param string $list - * @return string */ - private static function mangleList($list) + private static function mangleList(string $list): string { return preg_replace('/\s*(#[^\n]*)?(\n|$)/', ' ', $list); } diff --git a/modules-available/locationinfo/page.inc.php b/modules-available/locationinfo/page.inc.php index 91de0012..5e5b66f0 100644 --- a/modules-available/locationinfo/page.inc.php +++ b/modules-available/locationinfo/page.inc.php @@ -81,7 +81,7 @@ class Page_LocationInfo extends Page $this->showLocationsTable(); break; case 'backends': - $this->showBackendsTable($backends); + $this->showBackendsTable($backends ?? []); break; case 'edit-panel': $this->showPanelConfig(); @@ -130,11 +130,13 @@ class Page_LocationInfo extends Page } } - private function getTime(string $str): int + private static function getTime(string $str): ?int { $str = explode(':', $str); - if (count($str) !== 2) return false; - if ($str[0] < 0 || $str[0] > 23 || $str[1] < 0 || $str[1] > 59) return false; + if (count($str) !== 2) + return null; + if ($str[0] < 0 || $str[0] > 23 || $str[1] < 0 || $str[1] > 59) + return null; return $str[0] * 60 + $str[1]; } @@ -247,7 +249,7 @@ class Page_LocationInfo extends Page } // Permission - $this->assertPanelPermission($paneluuid, 'panel.edit', $params['locationids']); + $this->assertPanelPermission($paneluuid, 'panel.edit', $params['locationids'] ?? []); if ($paneluuid === 'new') { $paneluuid = Util::randomUuid(); @@ -270,6 +272,9 @@ class Page_LocationInfo extends Page Util::redirect('?do=locationinfo'); } + /** + * @return array{config: array, locationids: array} + */ private function preparePanelConfigDefault(): array { // Check locations @@ -325,6 +330,9 @@ class Page_LocationInfo extends Page return array('config' => $conf, 'locationids' => $locationids); } + /** + * @return array{config: array, locationids: array} + */ private function preparePanelConfigUrl(): array { $bookmarkNames = Request::post('bookmarkNames', [], 'array'); @@ -343,8 +351,8 @@ class Page_LocationInfo extends Page '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]+/ms", "\n", Request::post('whitelist', '', 'string')), - 'blacklist' => preg_replace("/[\r\n]+/ms", "\n", Request::post('blacklist', '', 'string')), + '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', 'slx-browser', 'string'), 'interactive' => Request::post('interactive', '0', 'bool'), @@ -355,6 +363,9 @@ class Page_LocationInfo extends Page return array('config' => $conf, 'locationids' => []); } + /** + * @return array{config: array, locationids: array} + */ private function preparePanelConfigSummary(): array { // Build json structure @@ -687,7 +698,7 @@ class Page_LocationInfo extends Page } else { $cred->initForRender(); } - $cred->title = Dictionary::translateFile('backend-' . $s, $cred->property, true); + $cred->title = Dictionary::translateFile('backend-' . $s, $cred->property); $cred->helptext = Dictionary::translateFile('backend-' . $s, $cred->property . "_helptext"); $cred->credentialsHtml = Render::parse('server-prop-' . $cred->template, (array)$cred); } @@ -776,9 +787,9 @@ class Page_LocationInfo extends Page $DAYLIST = array_flip(['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']); $new = []; foreach ($array as $row) { - $s = $this->getTime($row['openingtime']); - $e = $this->getTime($row['closingtime']); - if ($s === false || $e === false || $e <= $s) + $s = Page_LocationInfo::getTime($row['openingtime']); + $e = Page_LocationInfo::getTime($row['closingtime']); + if ($s === null || $e === null || $e <= $s) continue; foreach ($row['days'] as $day) { $day = $DAYLIST[$day] ?? -1; @@ -833,10 +844,10 @@ class Page_LocationInfo extends Page // Chain $last++; } else { - $string = Dictionary::translate($DAYLIST[$first], true); + $string = Dictionary::translate($DAYLIST[$first]); if ($first !== $last) { $string .= ($first + 1 === $last ? ",\xe2\x80\x89" : "\xe2\x80\x89-\xe2\x80\x89") - . Dictionary::translate($DAYLIST[$last], true); + . Dictionary::translate($DAYLIST[$last]); } $output[] = $string; $first = $last = $day; @@ -1034,7 +1045,7 @@ class Page_LocationInfo extends Page die('Missing parameter uuid'); } $type = InfoPanel::getConfig($uuid, $config); - if ($type === false) { + if ($type === null) { http_response_code(404); die('Panel with given uuid not found'); } @@ -1082,8 +1093,7 @@ class Page_LocationInfo extends Page /** * @param string|array $panelOrUuid UUID of panel, or array with keys paneltype and locationds - * @param string $permission - * @param int[]|null $additionalLocations + * @param int[] $additionalLocations */ private function assertPanelPermission($panelOrUuid, string $permission, array $additionalLocations = null): void { diff --git a/modules-available/locations/baseconfig/getconfig.inc.php b/modules-available/locations/baseconfig/getconfig.inc.php index f2aa2b46..1bed5de7 100644 --- a/modules-available/locations/baseconfig/getconfig.inc.php +++ b/modules-available/locations/baseconfig/getconfig.inc.php @@ -1,5 +1,8 @@ <?php +/** @var ?string $uuid */ +/** @var ?string $ip */ + // Location handling: figure out location $locationId = false; if (BaseConfig::hasOverride('locationid')) { @@ -12,7 +15,7 @@ if (BaseConfig::hasOverride('locationid')) { } if ($locationId === false) { - if (!$ip) // Required at this point, bail out if not given + if ($ip === null) // Required at this point, bail out if not given return; $locationId = Location::getFromIpAndUuid($ip, $uuid); } diff --git a/modules-available/locations/inc/location.inc.php b/modules-available/locations/inc/location.inc.php index f68d6821..59e6d2b6 100644 --- a/modules-available/locations/inc/location.inc.php +++ b/modules-available/locations/inc/location.inc.php @@ -17,7 +17,7 @@ class Location return self::$treeCache; } - public static function queryLocations() + public static function queryLocations(): array { $res = Database::simpleQuery("SELECT locationid, parentlocationid, locationname FROM location"); $rows = array(); @@ -29,10 +29,9 @@ class Location /** * Return row from location table for $locationId. - * @param $locationId * @return array|bool row from DB, false if not found */ - public static function get($locationId) + public static function get(int $locationId) { return Database::queryFirst("SELECT * FROM location WHERE locationid = :locationId", compact('locationId')); } @@ -42,9 +41,8 @@ class Location * @param int $locationId id of location to get name for * @return string|false Name of location, false if locationId doesn't exist */ - public static function getName($locationId) + public static function getName(int $locationId) { - $locationId = (int)$locationId; if (self::$assocLocationCache === false) { self::getLocationsAssoc(); } @@ -56,15 +54,13 @@ class Location /** * Get all the names of the given location and its parents, up * to the root element. Array keys will be locationids, value the names. - * @param int $locationId * @return array|false locations, from furthest to nearest or false if locationId doesn't exist */ - public static function getNameChain($locationId) + public static function getNameChain(int $locationId) { if (self::$assocLocationCache === false) { self::getLocationsAssoc(); } - $locationId = (int)$locationId; if (!isset(self::$assocLocationCache[$locationId])) return false; $ret = array(); @@ -84,7 +80,7 @@ class Location return self::$assocLocationCache; } - private static function flattenTreeAssoc($tree, $parents = array(), $depth = 0) + private static function flattenTreeAssoc($tree, $parents = array(), $depth = 0): array { if ($depth > 20) { ErrorHandler::traceError('Recursive location definition detected at ' . print_r($tree, true)); @@ -121,12 +117,12 @@ class Location /** * @param int|int[] $selected Which locationIDs to mark as selected - * @param int $excludeId Which locationID to explude + * @param int $excludeId Which locationID to exclude * @param bool $addNoParent Add entry for "no location" at the top * @param bool $keepArrayKeys Keep location IDs as array index * @return array Locations */ - public static function getLocations($selected = 0, $excludeId = 0, $addNoParent = false, $keepArrayKeys = false) + public static function getLocations($selected = 0, int $excludeId = 0, bool $addNoParent = false, bool $keepArrayKeys = false): array { if (self::$flatLocationCache === false) { $rows = self::getTree(); @@ -173,7 +169,7 @@ class Location * @param bool $locationTree used in recursive calls, don't pass * @return array list of passed locations plus their children */ - public static function getRecursive($idList, $locationTree = false) + public static function getRecursive($idList, bool $locationTree = false): array { if (!is_array($idList)) { $idList = array($idList); @@ -207,7 +203,7 @@ class Location return $ret; } - public static function buildTree($elements, $parentId = 0) + public static function buildTree(array $elements, int $parentId = 0): array { $branch = array(); $sort = array(); @@ -227,7 +223,7 @@ class Location return $branch; } - private static function flattenTree($tree, $depth = 0) + private static function flattenTree(array $tree, int $depth = 0): array { if ($depth > 20) { ErrorHandler::traceError('Recursive location definition detected at ' . print_r($tree, true)); @@ -249,7 +245,8 @@ class Location return $output; } - public static function isLeaf($locationid) { + public static function isLeaf(int $locationid): bool + { $result = Database::queryFirst('SELECT COUNT(locationid) = 0 AS isleaf ' . 'FROM location ' . 'WHERE parentlocationid = :locationid', ['locationid' => $locationid]); @@ -257,7 +254,7 @@ class Location return (bool)$result; } - public static function extractIds($tree) + public static function extractIds(array $tree): array { $ids = array(); foreach ($tree as $node) { @@ -271,10 +268,11 @@ class Location /** * Get location id for given machine (by uuid) + * * @param string $uuid machine uuid - * @return bool|int locationid, false if no match + * @return false|int locationid, false if no match */ - public static function getFromMachineUuid($uuid) + public static function getFromMachineUuid(string $uuid) { // Only if we have the statistics module which supplies the machine table if (Module::get('statistics') === false) @@ -291,9 +289,9 @@ class Location * * @param string $ip IP address of client * @param bool $honorRoomPlanner consider a fixed location assigned manually by roomplanner - * @return bool|int locationid, or false if no match + * @return false|int locationid, or false if no match */ - public static function getFromIp($ip, $honorRoomPlanner = false) + public static function getFromIp(string $ip, bool $honorRoomPlanner = false) { if (Module::get('statistics') !== false) { // Shortcut - try to use subnetlocationid in machine table @@ -322,17 +320,17 @@ class Location * client, so if it seems too fishy, the UUID will be ignored. * * @param string $ip IP address of client - * @param string $uuid System-UUID of client - * @return int|bool location id, or false if none matches + * @param ?string $uuid System-UUID of client + * @return int|false location id, or false if none matches */ - public static function getFromIpAndUuid($ip, $uuid) + public static function getFromIpAndUuid(string $ip, ?string $uuid) { $locationId = false; $ipLoc = self::getFromIp($ip); if ($ipLoc !== false) { // Set locationId to ipLoc for now, it will be overwritten later if another case applies. $locationId = $ipLoc; - if ($uuid !== false) { + if ($uuid !== null) { // Machine ip maps to a location, and we have a client supplied uuid (which might not be known if the client boots for the first time) $uuidLoc = self::getFromMachineUuid($uuid); if (self::isFixedLocationValid($uuidLoc, $ipLoc)) { @@ -343,7 +341,7 @@ class Location return $locationId; } - public static function isFixedLocationValid($uuidLoc, $ipLoc) + public static function isFixedLocationValid($uuidLoc, $ipLoc): bool { if ($uuidLoc === false) return false; @@ -366,12 +364,10 @@ class Location /** * Get all location IDs from the given location up to the root. * - * @param int $locationId * @return int[] location ids, including $locationId */ - public static function getLocationRootChain($locationId) + public static function getLocationRootChain(int $locationId): array { - $locationId = (int)$locationId; if (self::$assocLocationCache === false) { self::getLocationsAssoc(); } @@ -385,7 +381,7 @@ class Location /** * @return array list of subnets as numeric array */ - public static function getSubnets() + public static function getSubnets(): array { $res = Database::simpleQuery("SELECT startaddr, endaddr, locationid FROM subnet"); $subnets = array(); @@ -397,9 +393,9 @@ class Location } /** - * @return array|bool assoc array mapping from locationid to subnets + * @return array assoc array mapping from locationid to subnets */ - public static function getSubnetsByLocation($recursive = false) + public static function getSubnetsByLocation($recursive = false): array { $locs = self::getLocationsAssoc(); $subnets = self::getSubnets(); @@ -433,9 +429,9 @@ class Location * random one will be returned. * * @param string $ip IP to look up - * @return bool|int locationid ip matches, false = no match + * @return false|int locationid ip matches, false = no match */ - public static function mapIpToLocation($ip) + public static function mapIpToLocation(string $ip) { if (self::$subnetMapCache === false) { self::$subnetMapCache = self::getSubnetsByLocation(); @@ -464,7 +460,10 @@ class Location return (int)$best; } - public static function updateMapIpToLocation($uuid, $ip) + /** + * @return false|int newly determined location + */ + public static function updateMapIpToLocation(string $uuid, string $ip) { $loc = self::mapIpToLocation($ip); if ($loc === false) { diff --git a/modules-available/locations/inc/locationhooks.inc.php b/modules-available/locations/inc/locationhooks.inc.php index 5ce3bbfe..fca85575 100644 --- a/modules-available/locations/inc/locationhooks.inc.php +++ b/modules-available/locations/inc/locationhooks.inc.php @@ -6,7 +6,7 @@ class LocationHooks /** * Resolve baseconfig id to locationid -- noop in this case */ - public static function baseconfigLocationResolver($id) + public static function baseconfigLocationResolver(int $id): int { return $id; } @@ -15,7 +15,7 @@ class LocationHooks * Hook to get inheritance tree for all config vars * @param int $id Locationid currently being edited */ - public static function baseconfigInheritance($id) + public static function baseconfigInheritance(int $id): array { $locs = Location::getLocationsAssoc(); if ($locs === false || !isset($locs[$id])) diff --git a/modules-available/locations/inc/locationutil.inc.php b/modules-available/locations/inc/locationutil.inc.php index 907bcc99..17608203 100644 --- a/modules-available/locations/inc/locationutil.inc.php +++ b/modules-available/locations/inc/locationutil.inc.php @@ -159,19 +159,17 @@ class LocationUtil } if (empty($return)) return $return; - if ($locationId === 0) { + if ($locationId === 0) return array_values($return); - } else { - return $return[$locationId]; - } + return $return[$locationId]; } - private static function overlap($net1, $net2) + private static function overlap(array $net1, array $net2): bool { return ($net1['startaddr'] <= $net2['endaddr'] && $net1['endaddr'] >= $net2['startaddr']); } - public static function rangeToLongVerbose($start, $end) + public static function rangeToLongVerbose(int $start, int $end): ?array { $result = self::rangeToLong($start, $end); list($startLong, $endLong) = $result; @@ -182,15 +180,15 @@ class LocationUtil Message::addWarning('main.value-invalid', 'end addr', $start); } if ($startLong === false || $endLong === false) - return false; + return null; if ($startLong > $endLong) { Message::addWarning('main.value-invalid', 'range', $start . ' - ' . $end); - return false; + return null; } return $result; } - public static function rangeToLong($start, $end) + public static function rangeToLong(int $start, int $end): array { $startLong = ip2long($start); $endLong = ip2long($end); diff --git a/modules-available/locations/inc/openingtimes.inc.php b/modules-available/locations/inc/openingtimes.inc.php index 18e25063..74dae7c3 100644 --- a/modules-available/locations/inc/openingtimes.inc.php +++ b/modules-available/locations/inc/openingtimes.inc.php @@ -11,9 +11,8 @@ class OpeningTimes * "openingtime": "8:00", * "closingtime": "20:00" * }</pre> - * @return array|null */ - public static function forLocation(int $locationId) + public static function forLocation(int $locationId): ?array { static $openingTimesList = false; if ($openingTimesList === false) { diff --git a/modules-available/locations/pages/cleanup.inc.php b/modules-available/locations/pages/cleanup.inc.php index a7562c50..423d6a6b 100644 --- a/modules-available/locations/pages/cleanup.inc.php +++ b/modules-available/locations/pages/cleanup.inc.php @@ -3,7 +3,7 @@ class SubPage { - public static function doPreprocess($action) + public static function doPreprocess($action): bool { if ($action === 'resetmachines') { self::resetMachines(); @@ -16,7 +16,7 @@ class SubPage return false; } - public static function doRender($action) + public static function doRender($action): bool { $list = self::loadForLocation(); if ($list === false) @@ -29,7 +29,7 @@ class SubPage return true; } - public static function doAjax($action) + public static function doAjax($action): bool { return false; } diff --git a/modules-available/locations/pages/details.inc.php b/modules-available/locations/pages/details.inc.php index e75aaf7d..279eee44 100644 --- a/modules-available/locations/pages/details.inc.php +++ b/modules-available/locations/pages/details.inc.php @@ -3,24 +3,25 @@ class SubPage { - public static function doPreprocess($action) + public static function doPreprocess($action): bool { if ($action === 'updatelocation') { self::updateLocation(); return true; - } else if ($action === 'updateOpeningtimes') { + } + if ($action === 'updateOpeningtimes') { self::updateOpeningTimes(); return true; } return false; } - public static function doRender($action) + public static function doRender($action): bool { return false; } - public static function doAjax($action) + public static function doAjax($action): bool { if ($action === 'showlocation') { self::ajaxShowLocation(); @@ -172,7 +173,7 @@ class SubPage Util::redirect('?do=Locations'); } - private static function updateLocationData($location) + private static function updateLocationData(array $location): bool { $locationId = (int)$location['locationid']; $newParent = Request::post('parentlocationid', false, 'integer'); @@ -216,7 +217,7 @@ class SubPage return $newParent != $location['parentlocationid']; } - private static function updateLocationSubnets() + private static function updateLocationSubnets(): bool { $locationId = Request::post('locationid', false, 'integer'); if (!User::hasPermission('location.edit.subnets', $locationId)) @@ -257,7 +258,7 @@ class SubPage continue; } $range = LocationUtil::rangeToLongVerbose($start, $end); - if ($range === false) + if ($range === null) continue; list($startLong, $endLong) = $range; if ($stmt->execute(array('id' => $subnetid, 'start' => $startLong, 'end' => $endLong))) { @@ -275,7 +276,7 @@ class SubPage return $change; } - private static function addNewLocationSubnets($location) + private static function addNewLocationSubnets(array $location): bool { $locationId = (int)$location['locationid']; if (!User::hasPermission('location.edit.subnets', $locationId)) diff --git a/modules-available/locations/pages/locations.inc.php b/modules-available/locations/pages/locations.inc.php index 8ba4793e..78818328 100644 --- a/modules-available/locations/pages/locations.inc.php +++ b/modules-available/locations/pages/locations.inc.php @@ -3,7 +3,7 @@ class SubPage { - public static function doPreprocess($action) + public static function doPreprocess($action): bool { if ($action === 'addlocations') { self::addLocations(); @@ -12,7 +12,7 @@ class SubPage return false; } - public static function doRender($getAction) + public static function doRender($getAction): bool { if ($getAction === false) { if (User::hasPermission('location.view')) { @@ -32,7 +32,7 @@ class SubPage return false; } - public static function doAjax($action) + public static function doAjax($action): bool { return false; } diff --git a/modules-available/locations/pages/subnets.inc.php b/modules-available/locations/pages/subnets.inc.php index e568c655..7628486b 100644 --- a/modules-available/locations/pages/subnets.inc.php +++ b/modules-available/locations/pages/subnets.inc.php @@ -3,7 +3,7 @@ class SubPage { - public static function doPreprocess($action) + public static function doPreprocess(string $action): bool { if ($action === 'updatesubnets') { self::updateSubnets(); @@ -42,7 +42,7 @@ class SubPage continue; } $range = LocationUtil::rangeToLongVerbose($start, $end); - if ($range === false) + if ($range === null) continue; list($startLong, $endLong) = $range; if ($stmt->execute(compact('startLong', 'endLong', 'loc', 'subnetid'))) { @@ -59,7 +59,7 @@ class SubPage Util::redirect('?do=Locations'); } - public static function doRender($getAction) + public static function doRender($getAction): bool { if ($getAction === false) { User::assertPermission('subnets.edit', NULL, '?do=locations'); @@ -81,7 +81,7 @@ class SubPage return false; } - public static function doAjax($action) + public static function doAjax($action): bool { return false; } diff --git a/modules-available/main/hooks/cron.inc.php b/modules-available/main/hooks/cron.inc.php index 747115c2..5b20b6d0 100644 --- a/modules-available/main/hooks/cron.inc.php +++ b/modules-available/main/hooks/cron.inc.php @@ -10,6 +10,8 @@ case 3: case 4: Database::exec("DELETE FROM callback WHERE (UNIX_TIMESTAMP() - 86400) > dateline"); break; +default: + // Do nothing } Trigger::checkCallbacks(); diff --git a/modules-available/main/hooks/translation.inc.php b/modules-available/main/hooks/translation.inc.php index 7590dcb6..28247374 100644 --- a/modules-available/main/hooks/translation.inc.php +++ b/modules-available/main/hooks/translation.inc.php @@ -18,11 +18,8 @@ $HANDLER['subsections'] = array( * Global tags. * This just returns the union of global tags of all languages, as there is no * way to define a definite set of required global tags. - * - * @param Module $module - * @return array dem tags */ -$HANDLER['grep_global-tags'] = function($module) { +$HANDLER['grep_global-tags'] = function(Module $module): array { $want = array(); foreach (Dictionary::getLanguages() as $lang) { $want += Dictionary::getArray($module->getIdentifier(), 'global-tags', $lang); diff --git a/modules-available/main/page.inc.php b/modules-available/main/page.inc.php index 016a510d..b0d7d125 100644 --- a/modules-available/main/page.inc.php +++ b/modules-available/main/page.inc.php @@ -33,7 +33,7 @@ class Page_Main extends Page } // Update warning state - Property::setNeedsSetup($needSetup ? 1 : 0); + Property::setNeedsSetup($needSetup); } protected function doAjax() diff --git a/modules-available/minilinux/inc/linuxbootentryhook.inc.php b/modules-available/minilinux/inc/linuxbootentryhook.inc.php index 03d7f11f..56b3db69 100644 --- a/modules-available/minilinux/inc/linuxbootentryhook.inc.php +++ b/modules-available/minilinux/inc/linuxbootentryhook.inc.php @@ -10,9 +10,9 @@ class LinuxBootEntryHook extends BootEntryHook { - public function name() + public function name(): string { - return Dictionary::translateFileModule('minilinux', 'module', 'module_name', true); + return Dictionary::translateFileModule('minilinux', 'module', 'module_name'); } public function extraFields(): array @@ -44,7 +44,7 @@ class LinuxBootEntryHook extends BootEntryHook $array = []; $array[] = new HookEntryGroup($this->name(), [ new HookEntry('default', - Dictionary::translateFileModule('minilinux', 'module', 'default_boot_entry', true), + Dictionary::translateFileModule('minilinux', 'module', 'default_boot_entry'), MiniLinux::updateCurrentBootSetting()) ]); $branches = Database::queryAll('SELECT sourceid, branchid, title FROM minilinux_branch ORDER BY title'); @@ -56,7 +56,7 @@ class LinuxBootEntryHook extends BootEntryHook new HookEntry($branch['branchid'], $branch['branchid'] . ' ' . Dictionary::translateFileModule('minilinux', 'module', - 'latest_of_branch', true), + 'latest_of_branch'), true), ]; foreach ($versions[$branch['branchid']] as $version) { @@ -64,7 +64,7 @@ class LinuxBootEntryHook extends BootEntryHook $title = $version['versionid'] . ' ' . $version['title']; if (!$valid) { $title .= ' ' . Dictionary::translateFileModule('minilinux', 'module', - 'not_installed_hint', true); + 'not_installed_hint'); } $group[] = new HookEntry($version['versionid'], $title, $valid); } @@ -75,10 +75,9 @@ class LinuxBootEntryHook extends BootEntryHook } /** - * @param $localData - * @return BootEntry the actual boot entry instance for given entry, false if invalid id + * @return ?BootEntry the actual boot entry instance for given entry, false if invalid id */ - public function getBootEntryInternal($localData): BootEntry + public function getBootEntryInternal(array $localData): ?BootEntry { $id = $localData['id']; if ($id === 'default') { // Special case @@ -183,7 +182,7 @@ class LinuxBootEntryHook extends BootEntryHook return $exec; } - public function isValidId($id) + public function isValidId(string $id): bool { if ($id === 'default') return true; // Meta-version that links to whatever the default is set to diff --git a/modules-available/minilinux/inc/minilinux.inc.php b/modules-available/minilinux/inc/minilinux.inc.php index daae7048..9c1b9011 100644 --- a/modules-available/minilinux/inc/minilinux.inc.php +++ b/modules-available/minilinux/inc/minilinux.inc.php @@ -19,7 +19,7 @@ class MiniLinux * Query all known sources for metadata * @return int number of sources query was just initialized for */ - public static function updateList() + public static function updateList(): int { $stamp = time(); $last = Property::get(self::PROPERTY_KEY_FETCHTIME); @@ -49,10 +49,11 @@ class MiniLinux /** * Called when downloading metadata from a specific update source is finished - * @param mixed $task task structure + * + * @param array $task task structure * @param string $sourceid see minilinux_source table */ - public static function listDownloadCallback($task, $sourceid) + public static function listDownloadCallback(array $task, string $sourceid): void { if (!Taskmanager::isFinished($task)) return; @@ -177,7 +178,7 @@ class MiniLinux ]); } - private static function isValidIdPart($str) + private static function isValidIdPart(string $str): bool { return preg_match('/^[a-z0-9_\-]+$/', $str) > 0; } @@ -186,10 +187,10 @@ class MiniLinux * Download of specific version */ - public static function validateDownloadTask($versionid, $taskid) + public static function validateDownloadTask(string $versionid, ?string $taskid): ?string { if ($taskid === null) - return false; + return null; $task = Taskmanager::status($taskid); if (Taskmanager::isTask($task) && !Taskmanager::isFailed($task) && (is_dir(CONFIG_HTTP_DIR . '/' . $versionid) || !Taskmanager::isFinished($task))) @@ -197,15 +198,13 @@ class MiniLinux Database::exec('UPDATE minilinux_version SET taskid = NULL WHERE versionid = :versionid AND taskid = :taskid', ['versionid' => $versionid, 'taskid' => $taskid]); - return false; + return null; } /** * Download the files for the given version id - * @param $versionid - * @return bool */ - public static function downloadVersion($versionid) + public static function downloadVersion(string $versionid): ?string { $ver = Database::queryFirst('SELECT s.url, s.pubkey, v.versionid, v.taskid, v.data FROM minilinux_version v INNER JOIN minilinux_branch b USING (branchid) @@ -213,17 +212,17 @@ class MiniLinux WHERE versionid = :versionid', ['versionid' => $versionid]); if ($ver === false) - return false; + return null; $taskid = self::validateDownloadTask($versionid, $ver['taskid']); - if ($taskid !== false) + if ($taskid !== null) return $taskid; $data = json_decode($ver['data'], true); if (!is_array($data)) { EventLog::warning("Cannot download Linux '$versionid': Corrupted meta data.", $ver['data']); - return false; + return null; } if (empty($data['files'])) - return false; + return null; $list = []; $legacyDir = preg_replace(',^[^/]*/,', '', $versionid); foreach ($data['files'] as $file) { @@ -242,6 +241,7 @@ class MiniLinux Database::exec('LOCK TABLES minilinux_version WRITE'); $aff = Database::exec('UPDATE minilinux_version SET taskid = :taskid WHERE versionid = :versionid AND taskid IS NULL', ['taskid' => $uuid, 'versionid' => $versionid]); + $task = false; if ($aff > 0) { $task = Taskmanager::submit('DownloadFiles', [ 'id' => $uuid, @@ -252,10 +252,8 @@ class MiniLinux if (Taskmanager::isFailed($task)) { $task = false; } else { - $task = $task['id']; + $task = (string)$task['id']; } - } else { - $task = false; } Database::exec('UNLOCK TABLES'); if ($task !== false) { @@ -269,7 +267,7 @@ class MiniLinux return $task; } - public static function fileToId($versionid, $fileName) + public static function fileToId(string $versionid, string $fileName): string { return 'x' . substr(md5($fileName . $versionid), 0, 8); } @@ -282,7 +280,7 @@ class MiniLinux * Generate messages regarding setup und update availability. * @return bool true if severe problems were found, false otherwise */ - public static function generateUpdateNotice() + public static function generateUpdateNotice(): bool { // Messages in here are with module name, as required by the // main-warning hook. @@ -325,7 +323,7 @@ class MiniLinux * actually installed locally. * @return bool true if installed locally, false otherwise */ - public static function updateCurrentBootSetting() + public static function updateCurrentBootSetting(): bool { $default = Property::get(self::PROPERTY_DEFAULT_BOOT); if ($default === false) @@ -371,7 +369,7 @@ class MiniLinux } } - public static function queryAllVersionsByBranch() + public static function queryAllVersionsByBranch(): array { $list = []; $res = Database::simpleQuery('SELECT branchid, versionid, title, Length(description) AS desclen, @@ -401,11 +399,12 @@ class MiniLinux * Check whether an optionally required stage4 is available. * Return true if there is no stage4, otherwise check filesystem, * or try to request from local dnbd3-server. + * * @param array $data decoded data column from minilinux_version * @param string[] $errors in array of error messages if not available * @return bool true if stage4 is available or none required */ - public static function checkStage4($data, &$errors = false) + public static function checkStage4(array $data, &$errors = false): bool { $errors = []; $image = false; @@ -506,8 +505,6 @@ class MiniLinux if (!isset($data['id'])) continue; $id = self::resolveEntryId($data['id']); - if ($id === false) - continue; $new = [ 'entryids' => [$row['entryid']], 'menus' => explode(',', $row['menus'] ?? ''), @@ -546,7 +543,7 @@ class MiniLinux * Take a configured versionid from a bootentry (serversetup module) and translate * it, in case it's "default" or just a branch name. */ - private static function resolveEntryId($id) + private static function resolveEntryId(string $id): string { if ($id === 'default') { // Special case $id = Property::get(MiniLinux::PROPERTY_DEFAULT_BOOT_EFFECTIVE); diff --git a/modules-available/minilinux/page.inc.php b/modules-available/minilinux/page.inc.php index 2099b8c5..349bbfad 100644 --- a/modules-available/minilinux/page.inc.php +++ b/modules-available/minilinux/page.inc.php @@ -25,8 +25,8 @@ class Page_MiniLinux extends Page } User::assertPermission('view'); - Dashboard::addSubmenu('?do=minilinux', Dictionary::translate('menu-versions', true)); - Dashboard::addSubmenu('?do=minilinux&show=sources', Dictionary::translate('menu-sources', true)); + Dashboard::addSubmenu('?do=minilinux', Dictionary::translate('menu-versions')); + Dashboard::addSubmenu('?do=minilinux&show=sources', Dictionary::translate('menu-sources')); } protected function doRender() @@ -107,7 +107,7 @@ class Page_MiniLinux extends Page } } - private function renderVersionList($versions, $usage) + private function renderVersionList(array $versions, array $usage): string { $def = Property::get(MiniLinux::PROPERTY_DEFAULT_BOOT); //$eff = Property::get(MiniLinux::PROPERTY_DEFAULT_BOOT_EFFECTIVE); @@ -152,7 +152,7 @@ class Page_MiniLinux extends Page } $data['versionid'] = $versionid; $data['dltask'] = MiniLinux::validateDownloadTask($versionid, $ver['taskid']); - $data['verify_button'] = !$verify && $data['dltask'] === false; + $data['verify_button'] = !$verify && $data['dltask'] === null; if (is_array($data['files'])) { $valid = true; $sort = []; @@ -176,7 +176,7 @@ class Page_MiniLinux extends Page if (isset($file['mtime'])) { $file['mtime_s'] = Util::prettyTime($file['mtime']); } - if ($data['dltask']) { + if ($data['dltask'] !== null) { $file['fileid'] = MiniLinux::fileToId($versionid, $file['name']); } } @@ -191,7 +191,7 @@ class Page_MiniLinux extends Page MiniLinux::setInstalledState($versionid, true); } } - if ($data['dltask'] !== false || $ver['installed']) { + if ($data['dltask'] !== null || $ver['installed']) { MiniLinux::checkStage4($data, $data['s4_errors']); } $data['changelog'] = Util::markup($ver['description'] ?? ''); @@ -204,7 +204,7 @@ class Page_MiniLinux extends Page const FILE_CHECKSUM_BAD = 3; const FILE_NOT_READABLE = 4; - private function getFileState($versionid, $file, $verify) + private function getFileState(string $versionid, array $file, bool $verify): int { $path = CONFIG_HTTP_DIR . '/' . $versionid . '/' . $file['name']; if (!is_file($path)) @@ -231,15 +231,15 @@ class Page_MiniLinux extends Page { switch ($state) { case self::FILE_CHECKSUM_BAD: - return Dictionary::translate('file-checksum-bad', true); + return Dictionary::translate('file-checksum-bad'); case self::FILE_SIZE_MISMATCH: - return Dictionary::translate('file-size-mismatch', true); + return Dictionary::translate('file-size-mismatch'); case self::FILE_MISSING: - return Dictionary::translate('file-missing', true); + return Dictionary::translate('file-missing'); case self::FILE_NOT_READABLE: - return Dictionary::translate('file-not-readable', true); + return Dictionary::translate('file-not-readable'); case self::FILE_OK: - return Dictionary::translate('file-ok', true); + return Dictionary::translate('file-ok'); } return '???'; } @@ -252,7 +252,7 @@ class Page_MiniLinux extends Page die('No version'); } $task = MiniLinux::downloadVersion($version); - if ($task === false) { + if ($task === null) { Message::addError('no-such-version', $version); Message::renderList(); } else { diff --git a/modules-available/news/page.inc.php b/modules-available/news/page.inc.php index bb74c711..291f15fc 100644 --- a/modules-available/news/page.inc.php +++ b/modules-available/news/page.inc.php @@ -67,18 +67,18 @@ class Page_News extends Page User::assertPermission('access-page'); /* and also the news (or help) with the given id */ - $newsId = Request::get('newsid', false, 'int'); - $pageType = Request::get('type', false, 'string'); + $newsId = Request::get('newsid', null, 'int'); + $pageType = Request::get('type', null, 'string'); $this->locationId = Request::get('locationid', 0, 'int'); - if ($pageType === false && $newsId === false) { + if ($pageType === null && $newsId === null) { Util::redirect('?do=news&type=news&locationid=' . $this->locationId); } - $this->pageType = $pageType === false ? 'news' : $pageType; - $this->loadNews($newsId, $pageType); + $this->pageType = $pageType ?? 'news'; + $this->loadNews($newsId); foreach (self::TYPES as $type => $entry) { Dashboard::addSubmenu('?do=news&type=' . $type . '&locationid=' . $this->locationId, - Dictionary::translate('type_' . $type, true)); + Dictionary::translate('type_' . $type)); } } else { @@ -103,7 +103,7 @@ class Page_News extends Page } elseif ($action === 'delete') { // delete it User::assertPermission("$pageType.delete", $this->locationId); - $this->delNews(Request::post('newsid', false, 'int'), $pageType); + $this->delNews(Request::post('newsid', Request::REQUIRED, 'int'), $pageType); } else { // unknown action, redirect user Message::addError('invalid-action', $action); @@ -149,7 +149,7 @@ class Page_News extends Page $data = array( 'withTitle' => self::TYPES[$this->pageType]['headline'], - 'newsTypeName' => Dictionary::translate('type_' . $this->pageType, true), + 'newsTypeName' => Dictionary::translate('type_' . $this->pageType), 'dateline_s' => Util::prettyTime($this->newsDateline), 'expires_s' => $this->formatExpires($this->newsExpires), 'currentContent' => $this->newsContent, @@ -189,7 +189,7 @@ class Page_News extends Page Render::addTemplate('page-news', $data); } - private function formatExpires($ts) + private function formatExpires(int $ts): string { if ($ts - 86400 * 365 * 5 > time()) return '-'; @@ -199,13 +199,12 @@ class Page_News extends Page /** * Loads the news with the given ID into the form. * - * @param int $newsId ID of the news to be shown. - * @param string $pageType type if news id is not given. + * @param ?int $newsId ID of the news to be shown, or latest if null */ - private function loadNews($newsId, $pageType) + private function loadNews(?int $newsId): void { // check to see if we need to request a specific newsid - if ($newsId !== false) { + if ($newsId !== null) { $row = Database::queryFirst('SELECT newsid, title, content, dateline, expires, type FROM vmchooser_pages WHERE newsid = :newsid LIMIT 1', [ 'newsid' => $newsId, @@ -217,7 +216,7 @@ class Page_News extends Page $str = $this->locationId === 0 ? 'IS NULL' : ' = ' . $this->locationId; $row = Database::queryFirst("SELECT newsid, title, content, dateline, expires, type FROM vmchooser_pages WHERE type = :type AND locationid $str AND expires > UNIX_TIMESTAMP() ORDER BY dateline DESC LIMIT 1", [ - 'type' => $pageType, + 'type' => $this->pageType, ]); } if ($row === false) @@ -235,7 +234,7 @@ class Page_News extends Page /** * Save the given $newsTitle and $newsContent as POST'ed into the database. */ - private function saveNews($pageType) + private function saveNews(string $pageType): bool { // check if news content were set by the user $newsTitle = Request::post('news-title', '', 'string'); @@ -290,18 +289,12 @@ class Page_News extends Page * @param int $newsId ID of the entry to be deleted. * @param string $pageType type of news to be deleted. Must match the ID, otherwise do nothing. */ - private function delNews($newsId, $pageType) + private function delNews(int $newsId, string $pageType): void { - // sanity check: is newsId even numeric? - if (!is_numeric($newsId)) { - Message::addError('main.value-invalid', 'newsid', $newsId); - } else { - // check passed - do delete - Database::exec('DELETE FROM vmchooser_pages WHERE newsid = :newsid AND type = :type LIMIT 1', array( - 'newsid' => $newsId, - 'type' => $pageType, - )); - Message::addSuccess('news-del-success'); - } + Database::exec('DELETE FROM vmchooser_pages WHERE newsid = :newsid AND type = :type LIMIT 1', array( + 'newsid' => $newsId, + 'type' => $pageType, + )); + Message::addSuccess('news-del-success'); } } diff --git a/modules-available/permissionmanager/hooks/translation-global.inc.php b/modules-available/permissionmanager/hooks/translation-global.inc.php index 4810a719..cf2166bc 100644 --- a/modules-available/permissionmanager/hooks/translation-global.inc.php +++ b/modules-available/permissionmanager/hooks/translation-global.inc.php @@ -18,11 +18,8 @@ if (file_exists('modules/' . $moduleName . '/permissions/permissions.json')) { /** * Configuration categories. - * - * @param \Module $module - * @return array */ - $HANDLER['grep_permissions'] = function ($module) { + $HANDLER['grep_permissions'] = function (Module $module): array { $file = 'modules/' . $module->getIdentifier() . '/permissions/permissions.json'; if (!file_exists($file)) return []; diff --git a/modules-available/permissionmanager/inc/getpermissiondata.inc.php b/modules-available/permissionmanager/inc/getpermissiondata.inc.php index ead1e020..a51619e0 100644 --- a/modules-available/permissionmanager/inc/getpermissiondata.inc.php +++ b/modules-available/permissionmanager/inc/getpermissiondata.inc.php @@ -11,7 +11,7 @@ class GetPermissionData * * @return array array of users (each with userid, username and roles (each with roleid and rolename)) */ - public static function getUserData() + public static function getUserData(): array { $res = Database::simpleQuery("SELECT user.userid AS userid, user.login AS login, role.rolename AS rolename, role.roleid AS roleid FROM user @@ -42,7 +42,7 @@ class GetPermissionData * * @return array array of locations (each including the roles that have permissions for them) */ - public static function getLocationData() + public static function getLocationData(): array { $res = Database::simpleQuery("SELECT role.roleid AS roleid, rolename, GROUP_CONCAT(COALESCE(locationid, 0)) AS locationids FROM role INNER JOIN role_x_location ON role.roleid = role_x_location.roleid GROUP BY roleid ORDER BY rolename ASC"); @@ -70,7 +70,7 @@ class GetPermissionData * @param int $flags Bitmask specifying additional data to fetch (WITH_* constants of this class) * @return array array roles (each with roleid and rolename) */ - public static function getRoles($flags = 0) + public static function getRoles(int $flags = 0): array { $cols = $joins = ''; if ($flags & self::WITH_USER_COUNT) { @@ -93,15 +93,15 @@ class GetPermissionData * Get permissions and locations for a given role. * * @param string $roleid id of the role - * @return array|false array containing an array of permissions and an array of locations, false if not found + * @return ?array array containing an array of permissions and an array of locations, null if not found */ - public static function getRoleData($roleid) + public static function getRoleData(string $roleid): ?array { $data = self::getRole($roleid); $res = Database::simpleQuery("SELECT roleid, locationid FROM role_x_location WHERE roleid = :roleid", array("roleid" => $roleid)); if ($res === false) - return false; + return null; $data["locations"] = array(); foreach ($res as $row) { $data["locations"][] = $row['locationid']; diff --git a/modules-available/permissionmanager/inc/permissiondbupdate.inc.php b/modules-available/permissionmanager/inc/permissiondbupdate.inc.php index 0cd89b3a..49988420 100644 --- a/modules-available/permissionmanager/inc/permissiondbupdate.inc.php +++ b/modules-available/permissionmanager/inc/permissiondbupdate.inc.php @@ -9,14 +9,14 @@ class PermissionDbUpdate * @param int[] $users userids * @param int[] $roles roleids */ - public static function addRoleToUser($users, $roles) + public static function addRoleToUser(array $users, array $roles): int { if (empty($users) || empty($roles)) return 0; - $arg = array(); + $arg = []; foreach ($users AS $userid) { foreach ($roles AS $roleid) { - $arg[] = compact('userid', 'roleid'); + $arg[] = ['userid' => $userid, 'roleid' => $roleid]; } } return Database::exec("INSERT IGNORE INTO role_x_user (userid, roleid) VALUES :arg", @@ -29,12 +29,12 @@ class PermissionDbUpdate * @param int[] $users userids * @param int[] $roles roleids */ - public static function removeRoleFromUser($users, $roles) + public static function removeRoleFromUser(array $users, array $roles): int { if (empty($users) || empty($roles)) return 0; $query = "DELETE FROM role_x_user WHERE userid IN (:users) AND roleid IN (:roles)"; - return Database::exec($query, array("users" => $users, "roles" => $roles)); + return Database::exec($query, ["users" => $users, "roles" => $roles]); } /** @@ -44,7 +44,7 @@ class PermissionDbUpdate * @param int[] $users list of user ids * @param int[] $roles list of role ids */ - public static function setRolesForUser($users, $roles) + public static function setRolesForUser(array $users, array $roles): int { $count = Database::exec("DELETE FROM role_x_user WHERE userid in (:users) AND roleid NOT IN (:roles)", compact('users', 'roles')); @@ -56,7 +56,7 @@ class PermissionDbUpdate * * @param int $roleid roleid */ - public static function deleteRole($roleid) + public static function deleteRole(int $roleid): int { return Database::exec("DELETE FROM role WHERE roleid = :roleid", array("roleid" => $roleid)); } @@ -69,7 +69,8 @@ class PermissionDbUpdate * @param string[] $permissions array of permissions * @param int|null $roleId roleid or null if the role does not exist yet */ - public static function saveRole($roleName, $roleDescription, $locations, $permissions, $roleId = null) + public static function saveRole(string $roleName, string $roleDescription, array $locations, array $permissions, + ?int $roleId = null): void { foreach ($permissions as &$permission) { $permission = strtolower($permission); @@ -92,14 +93,14 @@ class PermissionDbUpdate if (!empty($locations)) { $arg = array_map(function ($loc) use ($roleId) { - return compact('roleId', 'loc'); + return ['roleId' => $roleId, 'loc' => $loc]; }, $locations); Database::exec("INSERT IGNORE INTO role_x_location (roleid, locationid) VALUES :arg", ['arg' => $arg]); } if (!empty($permissions)) { $arg = array_map(function ($perm) use ($roleId) { - return compact('roleId', 'perm'); + return ['roleId' => $roleId, 'perm' => $perm]; }, $permissions); Database::exec("INSERT IGNORE INTO role_x_permission (roleid, permissionid) VALUES :arg", ['arg' => $arg]); } diff --git a/modules-available/permissionmanager/inc/permissionutil.inc.php b/modules-available/permissionmanager/inc/permissionutil.inc.php index d3f20b4f..170fd699 100644 --- a/modules-available/permissionmanager/inc/permissionutil.inc.php +++ b/modules-available/permissionmanager/inc/permissionutil.inc.php @@ -14,7 +14,7 @@ class PermissionUtil * @param string|false $wildcard if $permission is a wildcard string this returns the matching variant * @param int|false $wclen if $permission is a wildcard string, this is the length of the matching variant */ - private static function makeComparisonVariants($permission, &$compare, &$wildcard, &$wclen) + private static function makeComparisonVariants($permission, ?array &$compare, &$wildcard, &$wclen): void { if (!is_array($permission)) { $permission = explode('.', $permission); @@ -46,12 +46,12 @@ class PermissionUtil /** * Check if the user has the given permission (for the given location). * - * @param string $userid userid to check + * @param int $userid userid to check * @param string $permissionid permissionid to check * @param int|null $locationid locationid to check or null if the location should be disregarded * @return bool true if user has permission, false if not */ - public static function userHasPermission($userid, $permissionid, $locationid) + public static function userHasPermission(int $userid, string $permissionid, ?int $locationid): bool { $permissionid = strtolower($permissionid); self::validatePermission($permissionid); @@ -121,6 +121,8 @@ class PermissionUtil // Compare to database result if ($cacheAll) { $allLocs = Location::getLocationsAssoc(); + } else { + $allLocs = []; } self::makeComparisonVariants($parts, $compare, $wildcard, $wclen); $retval = false; @@ -152,11 +154,11 @@ class PermissionUtil /** * Get all locations where the user has the given permission. * - * @param string $userid userid to check + * @param int $userid userid to check * @param string $permissionid permissionid to check * @return array array of locationids where the user has the given permission */ - public static function getAllowedLocations($userid, $permissionid) + public static function getAllowedLocations(int $userid, string $permissionid): array { $permissionid = strtolower($permissionid); self::validatePermission($permissionid); @@ -199,10 +201,10 @@ class PermissionUtil * Extend an array of locations by adding all sublocations. * * @param array $tree tree of all locations (structured like Location::getTree()) - * @param array $allowedLocations the array of locationids to extend + * @param int[] $allowedLocations the array of locationids to extend * @return array extended array of locationids */ - public static function getSublocations($tree, $allowedLocations) + public static function getSublocations(array $tree, array $allowedLocations): array { $result = $allowedLocations; foreach ($tree as $location) { @@ -224,7 +226,7 @@ class PermissionUtil * * @param string $permissionId permission to check */ - private static function validatePermission($permissionId) + private static function validatePermission(string $permissionId): void { if (!CONFIG_DEBUG || $permissionId === '*') return; @@ -253,7 +255,7 @@ class PermissionUtil * * @return array permission tree as a multidimensional array */ - public static function getPermissions() + public static function getPermissions(): array { $permissions = array(); foreach (glob("modules/*/permissions/permissions.json", GLOB_NOSORT) as $file) { @@ -291,18 +293,17 @@ class PermissionUtil /** * Get all existing roles. * - * @param int|false $userid Which user to consider, false = none - * @param bool $onlyMatching true = filter roles the user doesn't have + * @param ?int $userid Which user to consider, false = none (list all) * @return array list of roles */ - public static function getRoles($userid = false, $onlyMatching = true) + public static function getRoles(?int $userid = null): array { if ($userid === false) { return Database::queryAll('SELECT roleid, rolename FROM role ORDER BY rolename ASC'); } $ret = Database::queryAll('SELECT r.roleid, r.rolename, u.userid AS hasRole FROM role r LEFT JOIN role_x_user u ON (r.roleid = u.roleid AND u.userid = :userid) - GROUP BY r.roleid + GROUP BY r.roleid, r.rolename ORDER BY rolename ASC', ['userid' => $userid]); foreach ($ret as &$role) { settype($role['hasRole'], 'bool'); @@ -318,7 +319,7 @@ class PermissionUtil * @param string $description the description of the permission * @param array $tree the permission tree to modify */ - private static function putInPermissionTree($permission, $locationAware, $description, &$tree) + private static function putInPermissionTree(string $permission, bool $locationAware, string $description, array &$tree): void { $subPermissions = explode('.', $permission); foreach ($subPermissions as $subPermission) { diff --git a/modules-available/permissionmanager/page.inc.php b/modules-available/permissionmanager/page.inc.php index b431d9c9..7e9f17e4 100644 --- a/modules-available/permissionmanager/page.inc.php +++ b/modules-available/permissionmanager/page.inc.php @@ -18,13 +18,13 @@ class Page_PermissionManager extends Page $action = Request::any('action', 'show', 'string'); if ($action === 'addRoleToUser') { User::assertPermission('users.edit-roles'); - $users = Request::post('users', ''); - $roles = Request::post('roles', ''); + $users = Request::post('users', [], 'array'); + $roles = Request::post('roles', [], 'array'); PermissionDbUpdate::addRoleToUser($users, $roles); } elseif ($action === 'removeRoleFromUser') { User::assertPermission('users.edit-roles'); - $users = Request::post('users', ''); - $roles = Request::post('roles', ''); + $users = Request::post('users', [], 'array'); + $roles = Request::post('roles', [], 'array'); PermissionDbUpdate::removeRoleFromUser($users, $roles); } elseif ($action === 'deleteRole') { User::assertPermission('roles.edit'); @@ -115,7 +115,7 @@ class Page_PermissionManager extends Page $roleid = Request::get("roleid", false, 'int'); if ($roleid !== false) { $role = GetPermissionData::getRoleData($roleid); - if ($role === false) { + if ($role === null) { Message::addError('invalid-role-id', $roleid); Util::redirect('?do=permissionmanager'); } @@ -147,7 +147,8 @@ class Page_PermissionManager extends Page * @param string $permString the prefix permission string with which all permissions in the permission tree should start * @return string generated html code */ - private static function generatePermissionHTML($permissions, $selectedPermissions = array(), $selectAll = false, $permString = "", $tags = []) + private static function generatePermissionHTML(array $permissions, array $selectedPermissions = [], + bool $selectAll = false, string $permString = "", array $tags = []): string { $res = ""; $toplevel = $permString == ""; @@ -203,11 +204,12 @@ class Page_PermissionManager extends Page * * @param array $locations the location tree * @param array $selectedLocations locations that should be preselected - * @param array $selectAll true if all locations should be preselected, false if only those in $selectedLocations - * @param array $toplevel true if the location tree are the children of the root location, false if not + * @param bool $selectAll true if all locations should be preselected, false if only those in $selectedLocations + * @param bool $toplevel true if the location tree are the children of the root location, false if not * @return string generated html code */ - private static function generateLocationHTML($locations, $selectedLocations = array(), $selectAll = false, $toplevel = true, $tags = []) + private static function generateLocationHTML(array $locations, array $selectedLocations = [], + bool $selectAll = false, bool $toplevel = true, array $tags = []): string { $res = ""; if ($toplevel && in_array(0, $selectedLocations)) { @@ -242,7 +244,7 @@ class Page_PermissionManager extends Page * @param array $locations the locationid array * @return array the locationid array without redundant locationids */ - private static function processLocations($locations) + private static function processLocations(array $locations): array { if (in_array(0, $locations)) return array(null); @@ -267,7 +269,7 @@ class Page_PermissionManager extends Page * @param array $permissions the permissionid array * @return array the permissionid array without redundant permissionids */ - private static function processPermissions($permissions) + private static function processPermissions(array $permissions): array { if (in_array("*", $permissions)) return array("*"); @@ -287,7 +289,7 @@ class Page_PermissionManager extends Page * @param array $permissions multidimensional array of permissionids * @return array flat array of permissionids */ - private static function extractPermissions($permissions) + private static function extractPermissions(array $permissions): array { $result = array(); foreach ($permissions as $permission => $a) { @@ -306,7 +308,7 @@ class Page_PermissionManager extends Page return $result; } - private function denyActionIfBuiltin($roleID) + private function denyActionIfBuiltin(string $roleID): void { if ($roleID) { $existing = GetPermissionData::getRole($roleID); diff --git a/modules-available/rebootcontrol/hooks/client-update.inc.php b/modules-available/rebootcontrol/hooks/client-update.inc.php index 006a5e11..e934988d 100644 --- a/modules-available/rebootcontrol/hooks/client-update.inc.php +++ b/modules-available/rebootcontrol/hooks/client-update.inc.php @@ -7,7 +7,7 @@ if ($type === '~poweron') { && $subnet[0] === $ip && $subnet[1] >= 8 && $subnet[1] < 32) { $start = ip2long($ip); if ($start !== false) { - $maskHost = (int)(pow(2, 32 - $subnet[1]) - 1); + $maskHost = (int)(2 ** (32 - $subnet[1]) - 1); $maskNet = ~$maskHost & 0xffffffff; $end = $start | $maskHost; $start &= $maskNet; diff --git a/modules-available/rebootcontrol/hooks/config-tgz.inc.php b/modules-available/rebootcontrol/hooks/config-tgz.inc.php index 90e32e8a..c9ce1255 100644 --- a/modules-available/rebootcontrol/hooks/config-tgz.inc.php +++ b/modules-available/rebootcontrol/hooks/config-tgz.inc.php @@ -8,8 +8,10 @@ if (!is_file($tmpfile) || !is_readable($tmpfile) || filemtime($tmpfile) + 86400 } try { $a = new PharData($tmpfile); - $a["/etc/ssh/mgmt/authorized_keys"] = $pubkey; - $a["/etc/ssh/mgmt/authorized_keys"]->chmod(0600); + $a->addFromString("/etc/ssh/mgmt/authorized_keys", $pubkey); + $fi = $a->offsetGet("/etc/ssh/mgmt/authorized_keys"); + /** @var PharFileInfo $fi */ + $fi->chmod(0600); $file = $tmpfile; } catch (Exception $e) { EventLog::failure('Could not include ssh key for reboot-control in config.tgz', (string)$e); diff --git a/modules-available/rebootcontrol/hooks/cron.inc.php b/modules-available/rebootcontrol/hooks/cron.inc.php index cdecc31b..289426c7 100644 --- a/modules-available/rebootcontrol/hooks/cron.inc.php +++ b/modules-available/rebootcontrol/hooks/cron.inc.php @@ -24,7 +24,7 @@ class Stuff public static $subnets; } -function destSawPw($destTask, $destMachine, $passwd) +function destSawPw(array $destTask, array $destMachine, string $passwd): bool { return strpos($destTask['data']['result'][$destMachine['machineuuid']]['stdout'], "passwd=$passwd") !== false; } diff --git a/modules-available/rebootcontrol/inc/rebootcontrol.inc.php b/modules-available/rebootcontrol/inc/rebootcontrol.inc.php index a37b070c..ab308084 100644 --- a/modules-available/rebootcontrol/inc/rebootcontrol.inc.php +++ b/modules-available/rebootcontrol/inc/rebootcontrol.inc.php @@ -61,13 +61,8 @@ class RebootControl /** * Add wake task metadata to database, so we can display job details on the summary page. - * @param string $taskId - * @param string $type - * @param array $clients - * @param ?array $other - * @return void */ - private static function addTask(string $taskId, string $type, array $clients, array $other = null) + private static function addTask(string $taskId, string $type, array $clients, array $other = null): void { $lids = ArrayUtil::flattenByKey($clients, 'locationid'); $lids = array_unique($lids); @@ -220,12 +215,10 @@ class RebootControl } /** - * @param string|string[] $macs - * @param ?string $bcast - * @param ?string $passwd - * @return string + * Wake clients given by MAC address(es) via jawol util. + * Multiple MAC addresses can be passed as a space separated list. */ - private static function buildClientWakeCommand($macs, string $bcast = null, string $passwd = null): string + private static function buildClientWakeCommand(string $macs, string $bcast = null, string $passwd = null): string { $command = 'jawol'; if (!empty($bcast)) { @@ -236,21 +229,18 @@ class RebootControl if (!empty($passwd)) { $command .= " -p '$passwd'"; } - if (is_array($macs)) { - $macs = implode(" ", $macs); - } $command .= " $macs"; return $command; } /** * @param array $sourceMachines list of source machines. array of [clientip, machineuuid] entries - * @param string|string[] $macaddr destination mac address(es) - * @param ?string $bcast directed broadcast address to send to - * @param ?string $passwd optional WOL password, mac address or ipv4 notation + * @param string $macaddr destination mac address(es) + * @param string $bcast directed broadcast address to send to + * @param string $passwd optional WOL password, mac address or ipv4 notation * @return array|false task struct, false on error */ - public static function wakeViaClient($sourceMachines, $macaddr, string $bcast = null, string $passwd = null) + public static function wakeViaClient(array $sourceMachines, string $macaddr, string $bcast = null, string $passwd = null) { $command = self::buildClientWakeCommand($macaddr, $bcast, $passwd); // Yes there is one zero "missing" from the usleep -- that's the whole point: we prefer 100ms sleeps @@ -320,7 +310,7 @@ class RebootControl * @param ?array $failed list of failed clients from $clientList * @return ?string taskid of this job */ - public static function wakeMachines(array $clientList, array &$failed = null) + public static function wakeMachines(array $clientList, array &$failed = null): ?string { $errors = ''; $sent = $unknown = $unreachable = $failed = []; diff --git a/modules-available/rebootcontrol/inc/rebootutils.inc.php b/modules-available/rebootcontrol/inc/rebootutils.inc.php index f6843150..e05d90dc 100644 --- a/modules-available/rebootcontrol/inc/rebootutils.inc.php +++ b/modules-available/rebootcontrol/inc/rebootutils.inc.php @@ -8,13 +8,12 @@ class RebootUtils * @param string[] $list list of system UUIDs * @return array list of machines with machineuuid, hostname, clientip, state and locationid */ - public static function getMachinesByUuid($list, $assoc = false, $columns = ['machineuuid', 'hostname', 'clientip', 'state', 'locationid']) + public static function getMachinesByUuid(array $list, bool $assoc = false, + array $columns = ['machineuuid', 'hostname', 'clientip', 'state', 'locationid']): array { if (empty($list)) return array(); - if (is_array($columns)) { - $columns = implode(',', $columns); - } + $columns = implode(',', $columns); $res = Database::simpleQuery("SELECT $columns FROM machine WHERE machineuuid IN (:list)", compact('list')); if (!$assoc) @@ -31,7 +30,7 @@ class RebootUtils * Requires the array elements to have key "state" from machine table. * @param array $clients list of clients */ - public static function sortRunningFirst(&$clients) + public static function sortRunningFirst(array &$clients): void { usort($clients, function($a, $b) { $a = ($a['state'] === 'IDLE' || $a['state'] === 'OCCUPIED'); @@ -49,7 +48,7 @@ class RebootUtils * @param string $permission name of location-aware permission to check * @return array|false List of clients the user has access to. */ - public static function getFilteredMachineList($requestedClients, $permission) + public static function getFilteredMachineList(array $requestedClients, string $permission) { $actualClients = RebootUtils::getMachinesByUuid($requestedClients); if (count($actualClients) !== count($requestedClients)) { diff --git a/modules-available/rebootcontrol/inc/scheduler.inc.php b/modules-available/rebootcontrol/inc/scheduler.inc.php index 937cc000..19a01beb 100644 --- a/modules-available/rebootcontrol/inc/scheduler.inc.php +++ b/modules-available/rebootcontrol/inc/scheduler.inc.php @@ -199,8 +199,7 @@ class Scheduler } /** - * Get current settings for given location, or false if none. - * @param int $id + * Get current settings for given location. */ public static function getLocationOptions(int $id): array { @@ -216,7 +215,6 @@ class Scheduler /** * Write new WOL/Shutdown options for given location. - * @param int $locationId * @param array $options 'wol' 'sd' 'wol-offset' 'sd-offset' 'ra-mode' */ public static function setLocationOptions(int $locationId, array $options) diff --git a/modules-available/rebootcontrol/inc/sshkey.inc.php b/modules-available/rebootcontrol/inc/sshkey.inc.php index cce9b3dc..e0954415 100644 --- a/modules-available/rebootcontrol/inc/sshkey.inc.php +++ b/modules-available/rebootcontrol/inc/sshkey.inc.php @@ -3,13 +3,17 @@ class SSHKey { - public static function getPrivateKey(&$regen = false) { + public static function getPrivateKey(?bool &$regen = false): ?string + { $privKey = Property::get("rebootcontrol-private-key"); if (!$privKey) { - $rsaKey = openssl_pkey_new(array( + $rsaKey = openssl_pkey_new([ 'private_key_bits' => 2048, - 'private_key_type' => OPENSSL_KEYTYPE_RSA)); - openssl_pkey_export( openssl_pkey_get_private($rsaKey), $privKey); + 'private_key_type' => OPENSSL_KEYTYPE_RSA]); + if (!openssl_pkey_export( openssl_pkey_get_private($rsaKey), $privKey)) { + $regen = false; + return null; + } Property::set("rebootcontrol-private-key", $privKey); if (Module::isAvailable('sysconfig')) { ConfigTgz::rebuildAllConfigs(); @@ -19,21 +23,30 @@ class SSHKey return $privKey; } - public static function getPublicKey() { + public static function getPublicKey(): ?string + { $pkImport = openssl_pkey_get_private(self::getPrivateKey()); + if ($pkImport === false) + return null; return self::sshEncodePublicKey($pkImport); } - private static function sshEncodePublicKey($privKey) { + private static function sshEncodePublicKey($privKey): ?string + { $keyInfo = openssl_pkey_get_details($privKey); + if ($keyInfo === false) + return null; $buffer = pack("N", 7) . "ssh-rsa" . self::sshEncodeBuffer($keyInfo['rsa']['e']) . self::sshEncodeBuffer($keyInfo['rsa']['n']); return "ssh-rsa " . base64_encode($buffer); } - private static function sshEncodeBuffer($buffer) { + private static function sshEncodeBuffer(string $buffer): string + { $len = strlen($buffer); + // Prefix with extra null byte if the MSB is set, to ensure + // nobody will ever interpret this as a negative number if (ord($buffer[0]) & 0x80) { $len++; $buffer = "\x00" . $buffer; diff --git a/modules-available/rebootcontrol/page.inc.php b/modules-available/rebootcontrol/page.inc.php index c189e1fc..80eff842 100644 --- a/modules-available/rebootcontrol/page.inc.php +++ b/modules-available/rebootcontrol/page.inc.php @@ -21,10 +21,10 @@ class Page_RebootControl extends Page } if (User::hasPermission('jumphost.*')) { - Dashboard::addSubmenu('?do=rebootcontrol&show=jumphost', Dictionary::translate('jumphosts', true)); + Dashboard::addSubmenu('?do=rebootcontrol&show=jumphost', Dictionary::translate('jumphosts')); } if (User::hasPermission('subnet.*')) { - Dashboard::addSubmenu('?do=rebootcontrol&show=subnet', Dictionary::translate('subnets', true)); + Dashboard::addSubmenu('?do=rebootcontrol&show=subnet', Dictionary::translate('subnets')); } $section = Request::any('show', false, 'string'); diff --git a/modules-available/rebootcontrol/pages/subnet.inc.php b/modules-available/rebootcontrol/pages/subnet.inc.php index c1631cbd..3e593505 100644 --- a/modules-available/rebootcontrol/pages/subnet.inc.php +++ b/modules-available/rebootcontrol/pages/subnet.inc.php @@ -24,7 +24,7 @@ class SubPage User::assertPermission('subnet.edit'); $cidr = Request::post('cidr', Request::REQUIRED, 'string'); $range = IpUtil::parseCidr($cidr); - if ($range === false) { + if ($range === null) { Message::addError('invalid-cidr', $cidr); return; } diff --git a/modules-available/rebootcontrol/pages/task.inc.php b/modules-available/rebootcontrol/pages/task.inc.php index dc50bfff..7e1f6fbf 100644 --- a/modules-available/rebootcontrol/pages/task.inc.php +++ b/modules-available/rebootcontrol/pages/task.inc.php @@ -145,14 +145,3 @@ class SubPage } } - - -// Remove when we require >= 7.3.0 -if (!function_exists('array_key_first')) { - function array_key_first(array $arr) { - foreach($arr as $key => $unused) { - return $key; - } - return NULL; - } -} diff --git a/modules-available/remoteaccess/api.inc.php b/modules-available/remoteaccess/api.inc.php index ec5fe7ad..ca04eec4 100644 --- a/modules-available/remoteaccess/api.inc.php +++ b/modules-available/remoteaccess/api.inc.php @@ -21,7 +21,7 @@ if ($password !== false) { } $range = IpUtil::parseCidr(Property::get(RemoteAccess::PROP_ALLOWED_VNC_NET)); -if ($range === false) { +if ($range === null) { die('No allowed IP defined'); } $iplong = ip2long($ip); diff --git a/modules-available/remoteaccess/baseconfig/getconfig.inc.php b/modules-available/remoteaccess/baseconfig/getconfig.inc.php index 6403538d..182daef1 100644 --- a/modules-available/remoteaccess/baseconfig/getconfig.inc.php +++ b/modules-available/remoteaccess/baseconfig/getconfig.inc.php @@ -1,15 +1,18 @@ <?php -(function ($machineUuid) { +/** @var ?string $uuid */ +/** @var ?string $ip */ + +if ($uuid !== null) { // Leave clients in any runmode alone $res = Database::queryFirst('SELECT machineuuid FROM runmode WHERE machineuuid = :uuid', - ['uuid' => $machineUuid], true); + ['uuid' => $uuid], true); if (is_array($res)) return; // Locations from closest to furthest (order) $locationId = ConfigHolder::get('SLX_LOCATIONS'); - if ($locationId === false) + if ($locationId === null) return; $locationId = (int)$locationId; $ret = Database::queryFirst("SELECT l.locationid FROM remoteaccess_x_location l @@ -44,4 +47,4 @@ ConfigHolder::add('SLX_SCREEN_SAVER_GRACE_TIME', '86400', 1000); // Autologin will never work as the machine is immediately in use and will never get assigned ConfigHolder::add('SLX_AUTOLOGIN', 'OFF', 10000); -})($uuid); +} diff --git a/modules-available/remoteaccess/inc/remoteaccess.inc.php b/modules-available/remoteaccess/inc/remoteaccess.inc.php index 7bd0e966..95ca3821 100644 --- a/modules-available/remoteaccess/inc/remoteaccess.inc.php +++ b/modules-available/remoteaccess/inc/remoteaccess.inc.php @@ -93,7 +93,7 @@ class RemoteAccess $NOW = time(); while ($num > 0) { $list = []; - for ($i = 0; $i < $num && $row = $res->fetch(); ++$i) { + for ($i = 0; $i < $num && ($row = $res->fetch()); ++$i) { $list[] = $row; Database::exec("INSERT INTO remoteaccess_machine (machineuuid, password, woltime) VALUES (:uuid, NULL, :now) diff --git a/modules-available/remoteaccess/page.inc.php b/modules-available/remoteaccess/page.inc.php index ee9305dc..ba248b4d 100644 --- a/modules-available/remoteaccess/page.inc.php +++ b/modules-available/remoteaccess/page.inc.php @@ -127,7 +127,7 @@ class Page_RemoteAccess extends Page $last['groups'][] = [ 'groupid' => $row['groupid'], 'groupname' => $row['groupname'], - 'gclass' => $row['active'] ?: 'slx-strike', + 'gclass' => $row['active'] ? '' : 'slx-strike', ]; if ($row['active']) { $last['lclass'] = ''; diff --git a/modules-available/roomplanner/inc/composedroom.inc.php b/modules-available/roomplanner/inc/composedroom.inc.php index cdd50984..3ee892db 100644 --- a/modules-available/roomplanner/inc/composedroom.inc.php +++ b/modules-available/roomplanner/inc/composedroom.inc.php @@ -98,7 +98,7 @@ class ComposedRoom extends Room return $this->orientation; } - public function subLocationIds() + public function subLocationIds(): array { return $this->list; } @@ -108,7 +108,7 @@ class ComposedRoom extends Room return $this->controlRoom; } - public function machineCount() + public function machineCount(): int { $sum = 0; foreach ($this->list as $lid) { @@ -117,10 +117,9 @@ class ComposedRoom extends Room return $sum; } - public function getSize(&$width, &$height) + public function getSize(?int &$width, ?int &$height) { $horz = ($this->orientation == 'horizontal'); - $width = $height = 0; foreach ($this->list as $locId) { self::$rooms[$locId]->getSize($w, $h); $width = $horz ? $width + $w : max($width, $w); @@ -128,7 +127,7 @@ class ComposedRoom extends Room } } - public function getIniClientSection(&$i, $offX = 0, $offY = 0) + public function getIniClientSection(int &$i, int $offX = 0, int $offY = 0) { if (!$this->enabled) return false; @@ -154,10 +153,10 @@ class ComposedRoom extends Room return $out; } - public function getShiftedArray($offX = 0, $offY = 0) + public function getShiftedArray(int $offX = 0, int $offY = 0): ?array { if (!$this->enabled) - return false; + return null; if ($this->orientation == 'horizontal') { $x = 1; $y = 0; @@ -168,7 +167,7 @@ class ComposedRoom extends Room $ret = []; foreach ($this->list as $locId) { $new = self::$rooms[$locId]->getShiftedArray($offX, $offY); - if ($new !== false) { + if ($new !== null) { $ret = array_merge($ret, $new); self::$rooms[$locId]->getSize($w, $h); $offX += $w * $x; @@ -176,7 +175,7 @@ class ComposedRoom extends Room } } if (empty($ret)) - return false; + return null; return $ret; } @@ -194,12 +193,12 @@ class ComposedRoom extends Room return false; } - public function isLeaf() + public function isLeaf(): bool { return false; } - public function shouldSkip() + public function shouldSkip(): bool { return !$this->enabled; } diff --git a/modules-available/roomplanner/inc/pvsgenerator.inc.php b/modules-available/roomplanner/inc/pvsgenerator.inc.php index f23dcb20..f3c5c838 100644 --- a/modules-available/roomplanner/inc/pvsgenerator.inc.php +++ b/modules-available/roomplanner/inc/pvsgenerator.inc.php @@ -3,7 +3,7 @@ class PvsGenerator { - public static function generate() + public static function generate(): string { /* collect names and build room blocks - filter empty rooms while at it */ $roomNames = array(); @@ -36,7 +36,7 @@ class PvsGenerator * @param Room $room room/location data as fetched from db * @return string|false .ini section for room, or false if room is empty */ - private static function generateRoomBlock($room) + private static function generateRoomBlock(Room $room) { $room->getSize($sizeX, $sizeY); if ($sizeX === 0 || $sizeY === 0) @@ -91,13 +91,13 @@ class PvsGenerator } // Load room $room = Room::get($locationId); - if ($room === false) + if ($room === null) return false; $room->getSize($sizeX, $sizeY); if ($sizeX === 0 || $sizeY === 0) return false; // Empty - $machines = $room->getShiftedArray(); + $machines = $room->getShiftedArray() ?? []; $ORIENTATION = ['north' => 2, 'east' => 3, 'south' => 0, 'west' => 1]; if (is_string($highlightUuid)) { $highlightUuid = strtoupper($highlightUuid); @@ -176,14 +176,12 @@ class PvsGenerator /** * Get display name for manager of given locationId. * Hook for "runmode" module to resolve mode name. - * @param $locationId - * @return bool|string */ - public static function getManagerName($locationId) + public static function getManagerName(int $locationId): ?string { $names = Location::getNameChain($locationId); if ($names === false) - return false; + return null; return implode(' / ', $names); } diff --git a/modules-available/roomplanner/inc/room.inc.php b/modules-available/roomplanner/inc/room.inc.php index 1a7a80ae..880cb6d0 100644 --- a/modules-available/roomplanner/inc/room.inc.php +++ b/modules-available/roomplanner/inc/room.inc.php @@ -29,10 +29,10 @@ abstract class Room FROM location_roomplan lr LEFT JOIN machine m ON (lr.tutoruuid = m.machineuuid)'); foreach ($ret as $row) { - $row = self::loadSingleRoom($row); - if ($row === false) + $room = self::loadSingleRoom($row); + if ($room === null) continue; - self::$rooms[$row->locationId] = $row; + self::$rooms[$room->locationId] = $room; } foreach (self::$rooms as $room) { $room->sanitize(); @@ -42,14 +42,14 @@ abstract class Room /** * Instantiate ComposedRoom or MachineGroup depending on contents of $row * @param array $row DB row from location_roomplan. - * @return Room|false Room instance, false on error + * @return ?Room Room instance, null on error */ - private static function loadSingleRoom($row) + private static function loadSingleRoom(array $row): ?Room { $locations = Location::getLocationsAssoc(); settype($row['locationid'], 'int'); if (!isset($locations[$row['locationid']])) - return false; + return null; if ($locations[$row['locationid']]['isleaf']) return new SimpleRoom($row); return new ComposedRoom($row, false); @@ -59,7 +59,7 @@ abstract class Room * Get array of all rooms with room plan * @return Room[] */ - public static function getAll() + public static function getAll(): array { self::init(); return self::$rooms; @@ -68,9 +68,9 @@ abstract class Room /** * Get room instance for given location * @param int $locationId room to get - * @return Room|false requested room, false if not configured or not found + * @return ?Room requested room, false if not configured or not found */ - public static function get($locationId) + public static function get(int $locationId): ?Room { if (self::$rooms === null) { $room = Database::queryFirst( @@ -79,8 +79,10 @@ abstract class Room LEFT JOIN machine m ON (lr.tutoruuid = m.machineuuid) WHERE lr.locationid = :lid', ['lid' => $locationId]); if ($room === false) - return false; + return null; $room = self::loadSingleRoom($room); + if ($room === null) + return null; // If it's a leaf room we probably don't need any other rooms, return it if ($room->isLeaf()) return $room; @@ -89,7 +91,7 @@ abstract class Room } if (isset(self::$rooms[$locationId])) return self::$rooms[$locationId]; - return false; + return null; } public function __construct($row) @@ -102,35 +104,34 @@ abstract class Room /** * @return int number of machines in this room */ - abstract public function machineCount(); + abstract public function machineCount(): int; /** * Size of this room, returned by reference. - * @param int $width OUT width of room - * @param int $height OUT height of room + * + * @param int|null $width OUT width of room + * @param int|null $height OUT height of room */ - abstract public function getSize(&$width, &$height); + abstract public function getSize(?int &$width, ?int &$height); /** * Get clients in this room in .ini format for PVS. * Adjusted so the top/left client is at (0|0), which * is further adjustable with $offX and $offY. + * * @param int $i offset for indexing clients * @param int $offX positional X offset for clients * @param int $offY positional Y offset for clients * @return string|false */ - abstract public function getIniClientSection(&$i, $offX = 0, $offY = 0); + abstract public function getIniClientSection(int &$i, int $offX = 0, int $offY = 0); /** * Get clients in this room as array. * Adjusted so the top/left client is at (0|0), which *is further adjustable with $offX and $offY. - * @param int $offX - * @param int $offY - * @return array */ - abstract public function getShiftedArray($offX = 0, $offY = 0); + abstract public function getShiftedArray(int $offX = 0, int $offY = 0): ?array; /** * @return string|false IP address of manager. @@ -145,12 +146,12 @@ abstract class Room /** * @return bool true if this is a simple/leaf room, false for composed rooms. */ - abstract public function isLeaf(); + abstract public function isLeaf(): bool; /** * @return bool should this room be skipped from output? true for empty SimpleRoom or disabled ComposedRoom. */ - abstract public function shouldSkip(); + abstract public function shouldSkip(): bool; /** * Sanitize this room's data. @@ -160,7 +161,7 @@ abstract class Room /** * @return string get room's name. */ - public function locationName() + public function locationName(): string { return $this->locationName; } @@ -168,7 +169,7 @@ abstract class Room /** * @return int get room's id. */ - public function locationId() + public function locationId(): int { return $this->locationId; } diff --git a/modules-available/roomplanner/inc/simpleroom.inc.php b/modules-available/roomplanner/inc/simpleroom.inc.php index 43ae43ca..b4d3e744 100644 --- a/modules-available/roomplanner/inc/simpleroom.inc.php +++ b/modules-available/roomplanner/inc/simpleroom.inc.php @@ -11,6 +11,7 @@ class SimpleRoom extends Room private $tutorIp = false; + /** @var ?string */ private $managerIp = false; public function __construct($row) @@ -55,27 +56,29 @@ class SimpleRoom extends Room } } - public function machineCount() + public function machineCount(): int { return count($this->machines); } - public function getSize(&$width, &$height) + public function getSize(?int &$width, ?int &$height) { if (empty($this->machines)) { $width = $height = 0; return; } + $minX = $minY = $maxX = $maxY = 0; $this->boundingBox($minX, $minY, $maxX, $maxY); // client's size that cannot be configured as of today $width = max($maxX - $minX + self::CLIENT_SIZE, 1); $height = max($maxY - $minY + self::CLIENT_SIZE, 1); } - public function getIniClientSection(&$i, $offX = 0, $offY = 0) + public function getIniClientSection(int &$i, int $offX = 0, int $offY = 0): string { /* output individual client positions, shift coordinates to requested position */ $out = ''; + $minX = $minY = $maxX = $maxY = 0; $this->boundingBox($minX, $minY, $maxX, $maxY); foreach ($this->machines as $pos) { $i++; @@ -86,10 +89,11 @@ class SimpleRoom extends Room return $out; } - public function getShiftedArray($offX = 0, $offY = 0) + public function getShiftedArray(int $offX = 0, int $offY = 0): ?array { /* output individual client positions, shift coordinates to requested position */ $ret = []; + $minX = $minY = $maxX = $maxY = 0; $this->boundingBox($minX, $minY, $maxX, $maxY); foreach ($this->machines as $pos) { $pos['gridCol'] += $offX - $minX; @@ -100,7 +104,7 @@ class SimpleRoom extends Room return $ret; } - private function boundingBox(&$minX, &$minY, &$maxX, &$maxY) + private function boundingBox(int &$minX, int &$minY, int &$maxX, int &$maxY): void { if ($this->bb !== false) { $minX = $this->bb[0]; @@ -130,12 +134,12 @@ class SimpleRoom extends Room return $this->tutorIp; } - public function isLeaf() + public function isLeaf(): bool { return true; } - public function shouldSkip() + public function shouldSkip(): bool { return empty($this->machines); } diff --git a/modules-available/roomplanner/page.inc.php b/modules-available/roomplanner/page.inc.php index 7ac6890d..53e8bf0b 100644 --- a/modules-available/roomplanner/page.inc.php +++ b/modules-available/roomplanner/page.inc.php @@ -82,22 +82,17 @@ class Page_Roomplanner extends Page $config = Database::queryFirst('SELECT roomplan, managerip, tutoruuid FROM location_roomplan WHERE locationid = :locationid', ['locationid' => $this->locationid]); + if ($config === false) { + $config = ['dedicatedmgr' => false, 'managerip' => '']; + } $runmode = RunMode::getForMode(Page::getModule(), $this->locationid, true); - if (empty($runmode)) { - $config['dedicatedmgr'] = false; - } else { + if (!empty($runmode)) { $runmode = array_pop($runmode); $config['managerip'] = $runmode['clientip']; $config['manageruuid'] = $runmode['machineuuid']; $data = json_decode($runmode['modedata'], true); $config['dedicatedmgr'] = (isset($data['dedicatedmgr']) && $data['dedicatedmgr']); } - if ($config !== false) { - $managerIp = $config['managerip'] ?? ''; - $dediMgr = $config['dedicatedmgr'] ? 'checked' : ''; - } else { - $dediMgr = $managerIp = ''; - } $furniture = $this->getFurniture($config); $subnetMachines = $this->getPotentialMachines(); $machinesOnPlan = $this->getMachinesOnPlan($config['tutoruuid'] ?? ''); @@ -105,8 +100,8 @@ class Page_Roomplanner extends Page $canEdit = User::hasPermission('edit', $this->locationid); $params = [ 'location' => $this->location, - 'managerip' => $managerIp, - 'dediMgrChecked' => $dediMgr, + 'managerip' => $config['managerip'], + 'dediMgrChecked' => $config['dedicatedmgr'] ? 'checked' : '', 'subnetMachines' => json_encode($subnetMachines), 'locationid' => $this->locationid, 'roomConfiguration' => json_encode($roomConfig), @@ -229,11 +224,9 @@ class Page_Roomplanner extends Page if ($leaf !== $this->isLeaf) { if ($isAjax) { die('Leaf mode mismatch. Did you restructure locations while editing this room?'); - } else { - Message::addError('leaf-mode-mismatch'); - Util::redirect("?do=roomplanner&locationid={$this->locationid}&action=show"); } - return; + Message::addError('leaf-mode-mismatch'); + Util::redirect("?do=roomplanner&locationid={$this->locationid}&action=show"); } if ($this->isLeaf) { $this->saveLeafRoom($isAjax); @@ -250,10 +243,9 @@ class Page_Roomplanner extends Page if (!is_array($config) || !isset($config['furniture']) || !isset($config['computers'])) { if ($isAjax) { die('JSON data incomplete'); - } else { - Message::addError('json-data-invalid'); - Util::redirect("?do=roomplanner&locationid={$this->locationid}&action=show"); } + Message::addError('json-data-invalid'); + Util::redirect("?do=roomplanner&locationid={$this->locationid}&action=show"); } $tutorUuid = Request::post('tutoruuid', '', 'string'); if (empty($tutorUuid)) { @@ -263,10 +255,9 @@ class Page_Roomplanner extends Page if ($ret === false) { if ($isAjax) { die('Invalid tutor UUID'); - } else { - Message::addError('invalid-tutor-uuid'); - Util::redirect("?do=roomplanner&locationid={$this->locationid}&action=show"); } + Message::addError('invalid-tutor-uuid'); + Util::redirect("?do=roomplanner&locationid={$this->locationid}&action=show"); } } $this->saveRoomConfig($config['furniture'], $tutorUuid); @@ -282,10 +273,9 @@ class Page_Roomplanner extends Page if ($res === false) { if ($isAjax) { die('Error writing config to DB'); - } else { - Message::addError('db-error'); - Util::redirect("?do=roomplanner&locationid={$this->locationid}&action=show"); } + Message::addError('db-error'); + Util::redirect("?do=roomplanner&locationid={$this->locationid}&action=show"); } } @@ -302,7 +292,7 @@ class Page_Roomplanner extends Page * @param array $computers Deserialized json from browser with all the computers * @param array $oldComputers Deserialized old roomplan from database, used to find removed computers */ - protected function saveComputerConfig($computers, $oldComputers) + protected function saveComputerConfig(array $computers, array $oldComputers) { $oldUuids = []; @@ -323,12 +313,12 @@ class Page_Roomplanner extends Page if (!isset($computer['gridRow'])) { $computer['gridRow'] = 0; } else { - $this->sanitizeNumber($computer['gridRow'], 0, 32 * 4); + Util::clamp($computer['gridRow'], 0, 32 * 4); } if (!isset($computer['gridCol'])) { $computer['gridCol'] = 0; } else { - $this->sanitizeNumber($computer['gridCol'], 0, 32 * 4); + Util::clamp($computer['gridCol'], 0, 32 * 4); } $position = json_encode(['gridRow' => $computer['gridRow'], @@ -374,17 +364,20 @@ class Page_Roomplanner extends Page } } - protected function getFurniture($config) + protected function getFurniture(array $config): array { - if ($config === false) - return array(); - $config = json_decode($config['roomplan'] ?? '', true); + if (empty($config['roomplan'])) + return []; + $config = json_decode($config['roomplan'], true); if (!is_array($config)) - return array(); + return []; return $config; } - protected function getMachinesOnPlan($tutorUuid) + /** + * @return array{computers: array} + */ + protected function getMachinesOnPlan(string $tutorUuid): array { $result = Database::simpleQuery('SELECT machineuuid, macaddr, clientip, hostname, position FROM machine @@ -418,7 +411,7 @@ class Page_Roomplanner extends Page return ['computers' => $machines]; } - protected function getPotentialMachines() + protected function getPotentialMachines(): array { $result = Database::simpleQuery('SELECT m.machineuuid, m.macaddr, m.clientip, m.hostname, l.locationname AS otherroom, m.fixedlocationid FROM machine m diff --git a/modules-available/runmode/baseconfig/getconfig.inc.php b/modules-available/runmode/baseconfig/getconfig.inc.php index 9c36cc75..a5de1053 100644 --- a/modules-available/runmode/baseconfig/getconfig.inc.php +++ b/modules-available/runmode/baseconfig/getconfig.inc.php @@ -1,20 +1,23 @@ <?php -(function($machineUuid) { +/** @var ?string $uuid */ +/** @var ?string $ip */ + +if ($uuid !== null) { $res = Database::queryFirst('SELECT module, modeid, modedata FROM runmode WHERE machineuuid = :uuid', - array('uuid' => $machineUuid)); + array('uuid' => $uuid)); if ($res === false) return; $config = RunMode::getModuleConfig($res['module']); - if ($config === false) + if ($config === null) return; if (!Module::isAvailable($res['module'])) return; // Not really possible because getModuleConfig would have failed but we should make sure if ($config->configHook !== false) { - call_user_func($config->configHook, $machineUuid, $res['modeid'], $res['modedata']); + call_user_func($config->configHook, $uuid, $res['modeid'], $res['modedata']); } if ($config->systemdDefaultTarget !== false) { ConfigHolder::add('SLX_SYSTEMD_TARGET', $config->systemdDefaultTarget, 10000); } ConfigHolder::add('SLX_RUNMODE_MODULE', $res['module']); -})($uuid); +} diff --git a/modules-available/runmode/inc/runmode.inc.php b/modules-available/runmode/inc/runmode.inc.php index 65b444e7..2d676cae 100644 --- a/modules-available/runmode/inc/runmode.inc.php +++ b/modules-available/runmode/inc/runmode.inc.php @@ -12,36 +12,36 @@ class RunMode * Get runmode config for a specific module * * @param string $module name of module - * @return \RunModeModuleConfig|false config, false if moudles doesn't support run modes + * @return ?RunModeModuleConfig config, null if module doesn't support run modes */ - public static function getModuleConfig($module) + public static function getModuleConfig(string $module): ?RunModeModuleConfig { if (isset(self::$moduleConfigs[$module])) return self::$moduleConfigs[$module]; if (Module::get($module) === false) - return false; + return null; $file = 'modules/' . $module . '/hooks/runmode/config.json'; if (!file_exists($file)) - return false; + return null; return (self::$moduleConfigs[$module] = new RunModeModuleConfig($file)); } /** - * @param string $machineuuid * @param string|\Module $moduleId * @param string|null $modeId an ID specific to the module to further specify the run mode, NULL to delete the run mode entry * @param string|null $modeData optional, additional data for the run mode * @param bool|null $isClient whether to count the machine as a client (in statistics etc.) NULL for looking at module's general runmode config * @return bool whether it was set/deleted */ - public static function setRunMode($machineuuid, $moduleId, $modeId, $modeData = null, $isClient = null) + public static function setRunMode(string $machineuuid, $moduleId, ?string $modeId, + ?string $modeData = null, ?bool $isClient = null): bool { if (is_object($moduleId)) { $moduleId = $moduleId->getIdentifier(); } // - Check if machine exists $machine = Statistics::getMachine($machineuuid, Machine::NO_DATA); - if ($machine === false) + if ($machine === null) return false; // - Delete entry if mode is null if ($modeId === null) { @@ -72,25 +72,21 @@ class RunMode * Change the isClient flag for existing client. * @param string $machineUuid existing machine with some runmode * @param string $moduleId module that assigned the current runmode of that client - * @param bool $isClient + * @param bool $isClient should this machine be considered a normal client? */ - public static function updateClientFlag($machineUuid, $moduleId, $isClient) + public static function updateClientFlag(string $machineUuid, string $moduleId, bool $isClient): void { Database::exec('UPDATE runmode SET isclient = :isclient WHERE machineuuid = :uuid AND module = :module', ['uuid' => $machineUuid, 'module' => $moduleId, 'isclient' => ($isClient ? 1 : 0)]); } /** - * @param string $machineuuid * @param int $returnData bitfield of data to return * @return false|array {'machineuuid', 'isclient', 'module', 'modeid', 'modedata', * ('hostname', 'clientip', 'macaddr', 'locationid', 'lastseen'), ('moduleName', 'modeName')} */ - public static function getRunMode($machineuuid, $returnData = self::DATA_MACHINE_DATA) + public static function getRunMode(string $machineuuid, int $returnData = self::DATA_MACHINE_DATA) { - if ($returnData === true) { - $returnData = self::DATA_MACHINE_DATA | self::DATA_DETAILED; - } if ($returnData & self::DATA_MACHINE_DATA) { if ($returnData & self::DATA_DETAILED) { $sel = ', m.hostname, m.clientip, m.macaddr, m.locationid, m.lastseen'; @@ -127,11 +123,11 @@ class RunMode } /** - * @param string|\Module $module - * @param bool true = wrap in array where key is modeid - * @return array key=machineuuid, value={'machineuuid', 'modeid', 'modedata'} + * @param string|Module $module + * @param bool $groupByModeId true = wrap in array where key is modeid + * @return array - format depending on $groupByModeId */ - public static function getForModule($module, $groupByModeId = false) + public static function getForModule($module, bool $groupByModeId = false): array { if (is_object($module)) { $module = $module->getIdentifier(); @@ -153,14 +149,14 @@ class RunMode } /** - * @param string|\Module $module - * @param string $modeId + * @param string|Module $module Module the mode belongs to + * @param string $modeId module-specific runmode identifier * @param bool $detailed whether to return meta data about machine, not just machineuuid * @param bool $assoc use machineuuid as array key * @return array <key=machineuuid>, value={'machineuuid', 'modedata', * <'hostname', 'clientip', 'macaddr', 'locationid', 'lastseen'>} */ - public static function getForMode($module, $modeId, $detailed = false, $assoc = false) + public static function getForMode($module, string $modeId, bool $detailed = false, bool $assoc = false): array { if (is_object($module)) { $module = $module->getIdentifier(); @@ -192,11 +188,12 @@ class RunMode /** * Return assoc array of all configured clients. + * * @param bool $withData also return data field? - * @param bool $isClient true = return clients only, false = return non-clients only, null = return both + * @param bool|null $isClient true = return clients only, false = return non-clients only, null = return both * @return array all the entries from the table */ - public static function getAllClients($withData = false, $isClient = null) + public static function getAllClients(bool $withData = false, bool $isClient = null): array { $xtra = ''; if ($withData) { @@ -218,11 +215,11 @@ class RunMode * that method is passed through. getModeName by contract should return false if * the module doesn't think the given modeId exists. * - * @param string|\Module $module - * @param string $modeId - * @return string|bool mode name if known, modeId as fallback, or false if mode is not known by module + * @param string|Module $module module the runmode belongs to + * @param string $modeId module-specific runmode identifier + * @return string|false mode name if known, modeId as fallback, or false if mode is not known by module */ - public static function getModeName($module, $modeId) + public static function getModeName($module, string $modeId) { if (is_object($module)) { $module = $module->getIdentifier(); @@ -236,10 +233,10 @@ class RunMode /** * Delete given runmode. * - * @param string|\Module $module Module runmode belongs to + * @param string|Module $module Module runmode belongs to * @param string $modeId run mode id */ - public static function deleteMode($module, $modeId) + public static function deleteMode($module, string $modeId): void { if (is_object($module)) { $module = $module->getIdentifier(); @@ -317,7 +314,7 @@ class RunModeModuleConfig { if (!isset($data[$key])) return; - if (is_string($type) && gettype($data[$key]) !== $type) + if (gettype($data[$key]) !== $type) return; $this->{$key} = $data[$key]; } diff --git a/modules-available/runmode/page.inc.php b/modules-available/runmode/page.inc.php index cceefae8..5654456a 100644 --- a/modules-available/runmode/page.inc.php +++ b/modules-available/runmode/page.inc.php @@ -30,7 +30,7 @@ class Page_RunMode extends Page $module = Request::post('module', false, 'string'); $modeId = Request::post('modeid', false, 'string'); $modConfig = RunMode::getModuleConfig($module); - if ($modConfig === false) { + if ($modConfig === null) { Message::addError('runmode.module-hasnt-runmode', $module); return; } @@ -70,7 +70,7 @@ class Page_RunMode extends Page if ($oldMachineMode !== false) { $machineLocation = $oldMachineMode['locationid']; $oldModule = RunMode::getModuleConfig($oldMachineMode['module']); - if ($oldModule !== false) { + if ($oldModule !== null) { if ($oldMachineMode['module'] !== $module || $oldMachineMode['modeid'] !== $modeId) { if (!$oldModule->allowGenericEditor || $oldModule->deleteUrlSnippet !== false) { Message::addError('runmode.machine-still-assigned', $machine, $oldMachineMode['module']); @@ -87,7 +87,7 @@ class Page_RunMode extends Page } else { // Not existing, no old mode - query machine to get location, so we can do a perm-check for new loc $m = Statistics::getMachine($machine, Machine::NO_DATA); - if ($m !== false) { + if ($m !== null) { $machineLocation = $m->locationid; } } @@ -134,7 +134,7 @@ class Page_RunMode extends Page return; } $modConfig = RunMode::getModuleConfig($mode['module']); - if ($modConfig === false) { + if ($modConfig === null) { Message::addError('module-hasnt-runmode', $mode['moduleName']); return; } @@ -172,7 +172,7 @@ class Page_RunMode extends Page } $module->activate(1, false); $config = RunMode::getModuleConfig($moduleId); - if ($config === false) { + if ($config === null) { Message::addError('module-hasnt-runmode', $moduleId); Util::redirect('?do=runmode'); } @@ -187,7 +187,6 @@ class Page_RunMode extends Page if (!$config->userHasPermission(null) && !User::hasPermission('list-all')) { Message::addError('main.no-permission'); Util::redirect('?do=runmode'); - return; } // Show list of machines with assigned mode for this module $this->renderClientList($moduleId); @@ -212,7 +211,10 @@ class Page_RunMode extends Page if (!isset($modules[$row['module']])) { if (!Module::isAvailable($row['module'])) continue; - $modules[$row['module']] = array('config' => RunMode::getModuleConfig($row['module']), 'list' => array()); + $config = RunMode::getModuleConfig($row['module']); + if ($config === null) + continue; + $modules[$row['module']] = array('config' => $config, 'list' => array()); } if (empty($row['hostname'])) { $row['hostname'] = $row['clientip']; @@ -244,7 +246,7 @@ class Page_RunMode extends Page 'list' => $rows['list'], 'modulename' => $module->getDisplayName(), 'module' => $moduleId, - 'canedit' => $config !== false && $config->allowGenericEditor && $config->deleteUrlSnippet === false, + 'canedit' => $config !== null && $config->allowGenericEditor && $config->deleteUrlSnippet === false, 'deleteUrl' => $config->deleteUrlSnippet, 'disabled' => $disabled, )); @@ -254,12 +256,7 @@ class Page_RunMode extends Page } } - /** - * @param \Module $module - * @param string $modeId - * @param \RunModeModuleConfig $config - */ - private function renderModuleMode($module, $modeId, $config) + private function renderModuleMode(Module $module, string $modeId, RunModeModuleConfig $config) { $moduleId = $module->getIdentifier(); $modeName = RunMode::getModeName($moduleId, $modeId); @@ -283,7 +280,6 @@ class Page_RunMode extends Page } else { Message::addError('main.no-permission'); Util::redirect('?do=runmode'); - return; } $machines = RunMode::getForMode($module, $modeId, true); if ($config->permission !== false) { @@ -317,7 +313,7 @@ class Page_RunMode extends Page $config = RunMode::getModuleConfig(Request::any('module', '', 'string')); $returnObject = ['machines' => []]; - if ($config !== false) { + if ($config !== null) { $params = ['query' => "%$query%"]; if ($config->permission === false) { // Global diff --git a/modules-available/serversetup-bwlp-ipxe/inc/bootentry.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/bootentry.inc.php index 2abb5153..919861f0 100644 --- a/modules-available/serversetup-bwlp-ipxe/inc/bootentry.inc.php +++ b/modules-available/serversetup-bwlp-ipxe/inc/bootentry.inc.php @@ -22,17 +22,13 @@ abstract class BootEntry $this->internalId = $internalId; } - public abstract function supportsMode($mode); + public abstract function supportsMode(string $mode): bool; - /** - * @param ScriptBuilderBase $builder - * @return string - */ - public abstract function toScript($builder); + public abstract function toScript(ScriptBuilderBase $builder): string; - public abstract function toArray(); + public abstract function toArray(): array; - public abstract function addFormFields(&$array); + public abstract function addFormFields(array &$array): void; public function internalId(): string { @@ -48,14 +44,14 @@ abstract class BootEntry * * @param string $module module this entry belongs to, or special values .script/.exec * @param string $data serialized entry data - * @return BootEntry|null instance representing boot entry, null on error + * @return ?BootEntry instance representing boot entry, null on error */ - public static function fromJson($module, $data) + public static function fromJson(string $module, string $data): ?BootEntry { if ($module[0] !== '.') { // Hook from other module $hook = Hook::loadSingle($module, 'ipxe-bootentry'); - if ($hook === false) { + if ($hook === null) { error_log('Module ' . $module . ' doesnt have an ipxe-bootentry hook'); return null; } @@ -64,9 +60,9 @@ abstract class BootEntry return null; return $ret->getBootEntry($data); } - if (is_string($data)) { - $data = json_decode($data, true); - } + $data = json_decode($data, true); + if (!is_array($data)) + return null; if ($module === '.script') { return new CustomBootEntry($data); } @@ -79,12 +75,12 @@ abstract class BootEntry return null; } - public static function forMenu($menuId) + public static function forMenu(int $menuId): MenuBootEntry { return new MenuBootEntry($menuId); } - public static function newStandardBootEntry($initData, $efi = false, $arch = false, string $internalId = '') + public static function newStandardBootEntry($initData, $efi = false, $arch = false, string $internalId = ''): ?StandardBootEntry { $ret = new StandardBootEntry($initData, $efi, $arch, $internalId); $list = []; @@ -104,7 +100,7 @@ abstract class BootEntry return $ret; } - public static function newCustomBootEntry($initData) + public static function newCustomBootEntry($initData): ?CustomBootEntry { if (!is_array($initData) || empty($initData)) return null; @@ -114,15 +110,14 @@ abstract class BootEntry /** * Return a BootEntry instance from database with the given id. * - * @param string $id - * @return BootEntry|null|false false == unknown id, null = unknown entry type, BootEntry instance on success + * @return ?BootEntry null = unknown entry type, BootEntry instance on success */ - public static function fromDatabaseId($id) + public static function fromDatabaseId(string $id): ?BootEntry { $row = Database::queryFirst("SELECT module, data FROM serversetup_bootentry WHERE entryid = :id LIMIT 1", ['id' => $id]); if ($row === false) - return false; + return null; return self::fromJson($row['module'], $row['data']); } @@ -132,7 +127,7 @@ abstract class BootEntry * * @return BootEntry[] all existing BootEntries */ - public static function getAll() + public static function getAll(): array { $res = Database::simpleQuery("SELECT entryid, module, data FROM serversetup_bootentry"); $ret = []; @@ -158,13 +153,13 @@ class StandardBootEntry extends BootEntry */ protected $efi; /** - * @var string BootEntry Constants above + * @var ?string BootEntry Constants above */ protected $arch; const KEYS = ['executable', 'initRd', 'commandLine', 'replace', 'imageFree', 'autoUnload', 'resetConsole', 'dhcpOptions']; - public function __construct($data, $efi = false, $arch = false, string $internalId = '') + public function __construct($data, $efi = false, ?string $arch = null, string $internalId = '') { parent::__construct($internalId); $this->pcbios = new ExecData(); @@ -239,10 +234,7 @@ class StandardBootEntry extends BootEntry } } - /** - * @param PxeSection $data - */ - private function fromPxeMenu($data) + private function fromPxeMenu(PxeSection $data): void { $bios = $this->pcbios; $bios->executable = $data->kernel; @@ -266,12 +258,12 @@ class StandardBootEntry extends BootEntry $bios->commandLine = trim(preg_replace('/\s+/', ' ', $bios->commandLine)); } - public function arch() + public function arch(): ?string { return $this->arch; } - public function supportsMode($mode) + public function supportsMode(string $mode): bool { if ($mode === $this->arch || $this->arch === BootEntry::AGNOSTIC) return true; @@ -282,7 +274,7 @@ class StandardBootEntry extends BootEntry return false; } - public function toScript($builder) + public function toScript(ScriptBuilderBase $builder): string { if ($this->arch === BootEntry::AGNOSTIC) // Same as below, could construct fall-through but this is more clear return $builder->execDataToScript($this->pcbios, null, null); @@ -291,7 +283,7 @@ class StandardBootEntry extends BootEntry $this->supportsMode(BootEntry::EFI) ? $this->efi : null); } - public function addFormFields(&$array) + public function addFormFields(array &$array): void { $array[$this->arch . '_selected'] = 'selected'; $array['entries'][] = $this->pcbios->toFormFields(BootEntry::BIOS); @@ -299,7 +291,10 @@ class StandardBootEntry extends BootEntry $array['exec_checked'] = 'checked'; } - public function toArray() + /** + * @return array{PCBIOS: array, EFI: array, arch: string} + */ + public function toArray(): array { return [ BootEntry::BIOS => $this->pcbios->toArray(), @@ -314,7 +309,7 @@ class CustomBootEntry extends BootEntry /** * @var string iPXE */ - protected $ipxe; + protected $ipxe = ''; protected $bash; @@ -331,12 +326,12 @@ class CustomBootEntry extends BootEntry } } - public function supportsMode($mode) + public function supportsMode(string $mode): bool { return true; } - public function toScript($builder) + public function toScript(ScriptBuilderBase $builder): string { if ($builder instanceof ScriptBuilderIpxe) return $this->ipxe; @@ -345,7 +340,7 @@ class CustomBootEntry extends BootEntry return ''; } - public function addFormFields(&$array) + public function addFormFields(array &$array): void { $array['entry'] = [ 'script' => $this->ipxe, @@ -353,7 +348,10 @@ class CustomBootEntry extends BootEntry $array['script_checked'] = 'checked'; } - public function toArray() + /** + * @return array{script: string} + */ + public function toArray(): array { return ['script' => $this->ipxe]; } @@ -361,31 +359,32 @@ class CustomBootEntry extends BootEntry class MenuBootEntry extends BootEntry { + /** @var int */ protected $menuId; - public function __construct($menuId) + public function __construct(int $menuId) { parent::__construct('menu-' . $menuId); $this->menuId = $menuId; } - public function supportsMode($mode) + public function supportsMode(string $mode): bool { return true; } - public function toScript($builder) + public function toScript(ScriptBuilderBase $builder): string { - $menu = IPxeMenu::get($this->menuId); + $menu = IPxeMenu::get($this->menuId, true); return $builder->menuToScript($menu); } - public function toArray() + public function toArray(): array { return []; } - public function addFormFields(&$array) + public function addFormFields(array &$array): void { } } @@ -401,21 +400,21 @@ class SpecialBootEntry extends BootEntry parent::__construct('special-' . $this->type); } - public function supportsMode($mode) + public function supportsMode(string $mode): bool { return true; } - public function toScript($builder) + public function toScript(ScriptBuilderBase $builder): string { return $builder->getSpecial($this->type); } - public function toArray() + public function toArray(): array { return []; } - public function addFormFields(&$array) { } + public function addFormFields(array &$array): void { } }
\ No newline at end of file diff --git a/modules-available/serversetup-bwlp-ipxe/inc/bootentryhook.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/bootentryhook.inc.php index 060b3903..ab55c888 100644 --- a/modules-available/serversetup-bwlp-ipxe/inc/bootentryhook.inc.php +++ b/modules-available/serversetup-bwlp-ipxe/inc/bootentryhook.inc.php @@ -6,41 +6,37 @@ abstract class BootEntryHook /** * @var string -- set by ipxe, not module implementing hook */ - public $moduleId; + public $moduleId = ''; /** * @var string -- set by ipxe, not module implementing hook */ - public $checked; + public $checked = ''; - private $selectedId; + private $selectedId = ''; private $data = []; /** * @return string */ - public abstract function name(); + public abstract function name(): string; /** * @return HookExtraField[] */ - public abstract function extraFields(); + public abstract function extraFields(): array; - /** - * @param string $id - * @return bool - */ - public abstract function isValidId($id); + public abstract function isValidId(string $id): bool; /** * @return HookEntryGroup[] */ - protected abstract function groupsInternal(); + protected abstract function groupsInternal(): array; /** * @return HookEntryGroup[] */ - public final function groups() + public final function groups(): array { $groups = $this->groupsInternal(); foreach ($groups as $group) { @@ -54,16 +50,13 @@ abstract class BootEntryHook } /** - * @param $id * @return BootEntry|null the actual boot entry instance for given entry, null if invalid id */ - public abstract function getBootEntryInternal($localData); + public abstract function getBootEntryInternal(array $localData): ?BootEntry; - public final function getBootEntry($data) + public final function getBootEntry(string $jsonString): ?BootEntry { - if (!is_array($data)) { - $data = json_decode($data, true); - } + $data = json_decode($jsonString, true); return $this->getBootEntryInternal($data); } @@ -71,7 +64,7 @@ abstract class BootEntryHook * @param string $mixed either the plain ID if the entry to be marked as selected, or the JSON string representing * the entire entry, which must have a key called 'id' that will be used as the ID then. */ - public function setSelected($mixed) + public function setSelected(string $mixed): void { $json = @json_decode($mixed, true); if (is_array($json)) { @@ -86,12 +79,15 @@ abstract class BootEntryHook /** * @return string ID of entry that was marked as selected by setSelected() */ - public function getSelected() + public function getSelected(): string { return $this->selectedId; } - public function renderExtraFields() + /** + * @return HookExtraField[] + */ + public function renderExtraFields(): array { $list = $this->extraFields(); foreach ($list as $entry) { @@ -144,14 +140,7 @@ class HookEntry */ public $selected; - /** - * HookEntry constructor. - * - * @param string $id - * @param string $name - * @param bool $valid - */ - public function __construct($id, $name, $valid) + public function __construct(string $id, string $name, bool $valid) { $this->id = $id; $this->name = $name; @@ -182,7 +171,7 @@ class HookExtraField */ public $hook; - public function __construct($name, $type, $default) + public function __construct(string $name, string $type, $default) { $this->name = $name; $this->type = $type; @@ -203,10 +192,10 @@ class HookExtraField return $val; } - public function html() + public function html(): string { $fieldId = 'extra-' . $this->hook->moduleId . '-' . $this->name; - $fieldText = htmlspecialchars(Dictionary::translateFileModule($this->hook->moduleId, 'module', 'ipxe-' . $this->name, true)); + $fieldText = htmlspecialchars(Dictionary::translateFileModule($this->hook->moduleId, 'module', 'ipxe-' . $this->name)); if (is_array($this->type)) { $out = '<label for="' . $fieldId . '">' . $fieldText . '</label><select class="form-control" name="' . $fieldId . '" id="' . $fieldId . '">'; foreach ($this->type as $entry) { diff --git a/modules-available/serversetup-bwlp-ipxe/inc/execdata.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/execdata.inc.php index 1f6fa265..e4f7a1d7 100644 --- a/modules-available/serversetup-bwlp-ipxe/inc/execdata.inc.php +++ b/modules-available/serversetup-bwlp-ipxe/inc/execdata.inc.php @@ -108,7 +108,10 @@ class ExecData $this->dhcpOptions = array_values($this->dhcpOptions); } - public function toArray() + /** + * @return array{executable: string, initRd: string[], commandLine: string, imageFree: bool, replace: bool, autoUnload: bool, resetConsole: bool, dhcpOptions: array} + */ + public function toArray(): array { $this->sanitize(); return [ @@ -123,7 +126,7 @@ class ExecData ]; } - public function toFormFields($arch) + public function toFormFields(string $arch): array { $this->sanitize(); $opts = []; diff --git a/modules-available/serversetup-bwlp-ipxe/inc/ipxe.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/ipxe.inc.php index 8731bb7a..5e0531ab 100644 --- a/modules-available/serversetup-bwlp-ipxe/inc/ipxe.inc.php +++ b/modules-available/serversetup-bwlp-ipxe/inc/ipxe.inc.php @@ -12,9 +12,9 @@ class IPxe * Import all IP-Range based pxe menus from the given directory. * * @param string $configPath The pxelinux.cfg path where to look for menu files in hexadecimal IP format. - * @return Number of menus imported + * @return int Number of menus imported */ - public static function importSubnetPxeMenus($configPath) + public static function importSubnetPxeMenus(string $configPath): int { $res = Database::simpleQuery('SELECT menuid, entryid FROM serversetup_menuentry ORDER BY sortval ASC'); $menus = []; @@ -52,6 +52,10 @@ class IPxe $locations[] = $row; } $menu = PxeLinux::parsePxeLinux($content, true); + if ($menu === null) { + error_log("Skipping empty pxelinux menu file $file"); + continue; + } // Insert all entries first, so we can get the list of entry IDs $entries = []; self::importPxeMenuEntries($menu, $entries); @@ -83,10 +87,10 @@ class IPxe } else { error_log('Imported menu ' . $menu->title . ' is NEW, using for ' . count($locations) . ' locations.'); // Insert new menu - $menuId = self::insertMenu($menu, 'Auto Imported', false, 0, [], []); - if ($menuId === false) + $menuId = self::insertMenu($menu, 'Auto Imported', null, 0, [], []); + if ($menuId === null) continue; - $menus[(int)$menuId] = $entries; + $menus[$menuId] = $entries; $importCount++; } foreach ($locations as $loc) { @@ -103,20 +107,20 @@ class IPxe return $importCount; } - public static function importLegacyMenu($force = false) + public static function importLegacyMenu(bool $force = false): bool { // See if anything is there if (!$force && false !== Database::queryFirst("SELECT menuentryid FROM serversetup_menuentry LIMIT 1")) return false; // Already exists // Now create the default entry self::createDefaultEntries(); - $prepend = ['bwlp-default' => false, 'localboot' => false]; + $prepend = ['bwlp-default' => null, 'localboot' => null]; $defaultLabel = 'bwlp-default'; $menuTitle = 'bwLehrpool Bootauswahl'; $pxeConfig = ''; $timeoutSecs = 60; - // Try to import any customization - $oldMenu = Property::getBootMenu(); + // Try to import any customization of the legacy PXELinux menu (despite the property name hinting at iPXE) + $oldMenu = json_decode(Property::get('ipxe-menu'), true); if (is_array($oldMenu)) { // if (isset($oldMenu['timeout'])) { @@ -136,47 +140,45 @@ class IPxe } } $append = [ - '', - 'bwlp-default-dbg' => false, - '', - 'poweroff' => false, + new PxeSection(null), + 'bwlp-default-dbg' => null, + new PxeSection(null), + 'poweroff' => null, ]; - return self::insertMenu(PxeLinux::parsePxeLinux($pxeConfig, false), $menuTitle, $defaultLabel, $timeoutSecs, $prepend, $append); + self::insertMenu(PxeLinux::parsePxeLinux($pxeConfig, false), $menuTitle, $defaultLabel, $timeoutSecs, $prepend, $append); + return !empty($pxeConfig); } /** - * @param PxeMenu $pxeMenu - * @param string $menuTitle - * @param string|false $defaultLabel Fallback for the default label, if PxeMenu doesn't set one + * @param ?string $defaultLabel Fallback for the default label, if PxeMenu doesn't set one * @param int $defaultTimeoutSeconds Default timeout, if PxeMenu doesn't set one - * @param array $prepend - * @param array $append - * @return int|false + * @param (?PxeSection)[] $prepend + * @param (?PxeSection)[] $append + * @return ?int ID of newly created menu, or null on error, e.g. if the menu is empty */ - public static function insertMenu($pxeMenu, $menuTitle, $defaultLabel, $defaultTimeoutSeconds, $prepend, $append) + public static function insertMenu(?PxeMenu $pxeMenu, string $menuTitle, ?string $defaultLabel, int $defaultTimeoutSeconds, + array $prepend, array $append): ?int { $timeoutMs = []; $menuEntries = $prepend; - settype($menuEntries, 'array'); - if (!empty($pxeMenu)) { - $pxe =& $pxeMenu; - if (!empty($pxe->title)) { - $menuTitle = $pxe->title; + if ($pxeMenu !== null) { + if (!empty($pxeMenu->title)) { + $menuTitle = $pxeMenu->title; } - if ($pxe->timeoutLabel !== null && $pxe->hasLabel($pxe->timeoutLabel)) { - $defaultLabel = $pxe->timeoutLabel; - } elseif ($pxe->hasLabel($pxe->default)) { - $defaultLabel = $pxe->default; + if ($pxeMenu->timeoutLabel !== null && $pxeMenu->hasLabel($pxeMenu->timeoutLabel)) { + $defaultLabel = $pxeMenu->timeoutLabel; + } elseif ($pxeMenu->hasLabel($pxeMenu->default)) { + $defaultLabel = $pxeMenu->default; } - $timeoutMs[] = $pxe->timeoutMs; - $timeoutMs[] = $pxe->totalTimeoutMs; - self::importPxeMenuEntries($pxe, $menuEntries); + $timeoutMs[] = $pxeMenu->timeoutMs; + $timeoutMs[] = $pxeMenu->totalTimeoutMs; + self::importPxeMenuEntries($pxeMenu, $menuEntries); } - if (is_array($append)) { + if (!empty($append)) { $menuEntries += $append; } if (empty($menuEntries)) - return false; + return null; // Make menu $timeoutMs = array_filter($timeoutMs, function($x) { return is_int($x) && $x > 0; }); if (empty($timeoutMs)) { @@ -195,25 +197,29 @@ class IPxe // Figure out entryid for default label // Fiddly diddly way of getting the mangled entryid for the wanted pxe menu label $defaultEntryId = false; + $fallbackDefault = false; foreach ($menuEntries as $entryId => $section) { - if ($section instanceof PxeSection) { - if ($section->isDefault) { - $defaultEntryId = $entryId; - break; - } - if ($section->label === $defaultLabel) { - $defaultEntryId = $entryId; - } + if ($section === null) + continue; + if ($section->isDefault) { + $defaultEntryId = $entryId; + break; + } + if ($section->label === $defaultLabel) { + $defaultEntryId = $entryId; + } + if ($fallbackDefault === false && !empty($entryId)) { + $fallbackDefault = $entryId; } } if ($defaultEntryId === false) { - $defaultEntryId = array_keys($menuEntries)[0]; + $defaultEntryId = $fallbackDefault; } // Link boot entries to menu $defaultMenuEntryId = null; $order = 1000; foreach ($menuEntries as $entryId => $entry) { - if (is_string($entry)) { + if ($entry !== null && $entry->isTextOnly()) { // Gap entry Database::exec("INSERT INTO serversetup_menuentry (menuid, entryid, hotkey, title, hidden, sortval, plainpass, md5pass) @@ -221,7 +227,7 @@ class IPxe 'menuid' => $menuId, 'entryid' => null, 'hotkey' => '', - 'title' => self::sanitizeIpxeString($entry), + 'title' => self::sanitizeIpxeString($entry->title), 'hidden' => 0, 'sortval' => $order += 100, ]); @@ -232,7 +238,7 @@ class IPxe continue; $data['pass'] = ''; $data['hidden'] = 0; - if ($entry instanceof PxeSection) { + if ($entry !== null) { $data['hidden'] = (int)$entry->isHidden; // Prefer explicit data from this imported menu over the defaults $title = self::sanitizeIpxeString($entry->title); @@ -243,7 +249,7 @@ class IPxe $data['hotkey'] = $entry->hotkey; } if (!empty($entry->passwd)) { - // Most likely it's a hash so we cannot recover; ask people to reset + // Most likely it's a hash, so we cannot recover; ask people to reset $data['pass'] ='please_reset'; } } @@ -268,36 +274,28 @@ class IPxe /** * Import only the bootentries from the given PXELinux menu - * @param PxeMenu $pxe - * @param array $menuEntries Where to append the generated menu items to + * + * @param PxeSection[] $menuEntries Where to append the generated menu items to */ - public static function importPxeMenuEntries($pxe, &$menuEntries) + public static function importPxeMenuEntries(PxeMenu $pxe, array &$menuEntries): void { if (self::$allEntries === false) { self::$allEntries = BootEntry::getAll(); } foreach ($pxe->sections as $section) { - if ($section->localBoot !== false || preg_match('/chain\.c32$/i', $section->kernel)) { + if ($section->isLocalboot()) { $menuEntries['localboot'] = $section; continue; } - if ($section->label === null) { - if (!$section->isHidden && !empty($section->title)) { - $menuEntries[] = $section->title; - } - continue; - } - if (empty($section->kernel)) { - if (!$section->isHidden && !empty($section->title)) { - $menuEntries[] = $section->title; - } + if ($section->isTextOnly()) { + $menuEntries[] = $section; continue; } $label = self::cleanLabelFixLocal($section); $entry = self::pxe2BootEntry($section); if ($entry === null) continue; // Error? Ignore - if ($label !== false || ($label = array_search($entry, self::$allEntries))) { + if ($label !== false || ($label = array_search($entry, self::$allEntries)) !== false) { // Exact Duplicate, Do Nothing error_log('Ignoring duplicate boot entry ' . $section->label . ' (' . $section->kernel . ')'); } else { @@ -321,7 +319,7 @@ class IPxe Database::exec('INSERT IGNORE INTO serversetup_bootentry (entryid, module, hotkey, title, builtin, data) VALUES (:label, :module, :hotkey, :title, 0, :data)', [ 'label' => $label, - 'module' => ($entry instanceof \StandardBootEntry) ? '.exec' : '.script', + 'module' => ($entry instanceof StandardBootEntry) ? '.exec' : '.script', 'hotkey' => $hotkey, 'title' => $title, 'data' => json_encode($data), @@ -408,10 +406,9 @@ class IPxe * Also it patches the entry if it's referencing the local bwlp install * but with different options. * - * @param PxeSection $section * @return string|false existing label if match, false otherwise */ - private static function cleanLabelFixLocal($section) + private static function cleanLabelFixLocal(PxeSection $section) { $myip = Property::getServerIp(); // Detect our "old" entry types @@ -434,10 +431,9 @@ class IPxe } /** - * @param PxeSection $section * @return BootEntry|null The according boot entry, null if it's unparsable */ - private static function pxe2BootEntry($section) + private static function pxe2BootEntry(PxeSection $section): ?BootEntry { if (preg_match('/(pxechain\.com|pxechn\.c32)$/i', $section->kernel)) { // Chaining -- create script @@ -496,11 +492,8 @@ class IPxe /** * Parse PXELINUX file notion. Basically, turn * server::file into tftp://server/file. - * - * @param string $file - * @return string */ - private static function parseFile($file) + private static function parseFile(string $file): string { if (preg_match(',^([^:/]+)::(.*)$,', $file, $out)) { return 'tftp://' . $out[1] . '/' . $out[2]; @@ -508,12 +501,12 @@ class IPxe return $file; } - public static function sanitizeIpxeString($string) + public static function sanitizeIpxeString(string $string): string { return str_replace(['&', '|', ';', '$', "\r", "\n"], ['+', '/', ':', 'S', ' ', ' '], $string); } - public static function makeMd5Pass($plainpass, $salt) + public static function makeMd5Pass(string $plainpass, string $salt): string { if (empty($plainpass)) return ''; @@ -528,11 +521,12 @@ class IPxe * remove any occurrence of either "option" or "option=something". If the argument starts with a * '+', it will be added to the command line after removing the '+'. If the argument starts with any * other character, it will also be added to the command line. + * * @param string $cmdLine command line to modify - * @param string $modifier modification string of space separated arguments + * @param string $modifier modification string of space separated arguments * @return string the modified command line */ - public static function modifyCommandLine($cmdLine, $modifier) + public static function modifyCommandLine(string $cmdLine, string $modifier): string { $items = preg_split('/\s+/', $modifier, -1, PREG_SPLIT_NO_EMPTY); foreach ($items as $item) { diff --git a/modules-available/serversetup-bwlp-ipxe/inc/ipxebuilder.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/ipxebuilder.inc.php index 3a82b4f7..a2b25f55 100644 --- a/modules-available/serversetup-bwlp-ipxe/inc/ipxebuilder.inc.php +++ b/modules-available/serversetup-bwlp-ipxe/inc/ipxebuilder.inc.php @@ -13,10 +13,9 @@ class IPxeBuilder * Checkout given commit/ref of ipxe repo. Returns the according task-id, or null on error * * @param string $version version ref (commit, tag, ...) - * @param string|null $parent parent task id - * @return ?string + * @param ?string $parent parent task id, if any */ - public static function setIpxeVersion($version, $parent = null) + public static function setIpxeVersion(string $version, ?string $parent = null): ?string { $task = Taskmanager::submit('IpxeVersion', [ 'action' => 'CHECKOUT', @@ -30,10 +29,7 @@ class IPxeBuilder return $task['id']; } - /** - * @return array|false - */ - public static function getVersionTaskResult() + public static function getVersionTaskResult(): ?array { $task = Taskmanager::status(IPxeBuilder::VERSION_LIST_TASK); if (!Taskmanager::isTask($task) || Taskmanager::isFailed($task)) { @@ -44,13 +40,13 @@ class IPxeBuilder if (Taskmanager::isFinished($task) && !Taskmanager::isFailed($task)) { return $task['data']; } - return false; + return null; } /** * Callback when compile Taskmanager job finished */ - public static function compileCompleteCallback($task) + public static function compileCompleteCallback(array $task): void { if (!Taskmanager::isFinished($task) || Taskmanager::isFailed($task)) return; @@ -75,7 +71,7 @@ class IPxeBuilder Property::set(IPxeBuilder::PROP_IPXE_BUILDSTRING, $buildString); } - public static function setIPxeVersionCallback($task) + public static function setIPxeVersionCallback(array $task): void { if (!Taskmanager::isFinished($task) || Taskmanager::isFailed($task) || empty($task['data']['ref'])) return; diff --git a/modules-available/serversetup-bwlp-ipxe/inc/ipxemenu.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/ipxemenu.inc.php index 7d15cd99..ddbce00d 100644 --- a/modules-available/serversetup-bwlp-ipxe/inc/ipxemenu.inc.php +++ b/modules-available/serversetup-bwlp-ipxe/inc/ipxemenu.inc.php @@ -24,10 +24,7 @@ class IPxeMenu */ public $items = []; - /** - * @param int $menuId - */ - public static function get($menuId, $emptyFallback = false) + public static function get(int $menuId, bool $emptyFallback = false): ?IPxeMenu { $menu = Database::queryFirst("SELECT menuid, timeoutms, title, defaultentryid FROM serversetup_menu WHERE menuid = :menuid LIMIT 1", ['menuid' => $menuId]); @@ -43,7 +40,7 @@ class IPxeMenu * * @param array $menu array for according menu row */ - public function __construct($menu) + public function __construct(array $menu) { $this->menuid = (int)$menu['menuid']; $this->timeoutMs = (int)$menu['timeoutms']; @@ -86,7 +83,7 @@ class IPxeMenu /** * @return MenuEntry|null Return preselected menu entry */ - public function defaultEntry() + public function defaultEntry(): ?MenuEntry { foreach ($this->items as $item) { if ($item->menuEntryId() === $this->defaultEntryId) @@ -183,16 +180,18 @@ class IPxeMenu return new IPxeMenu($menu); } - public static function forClient(string $ip, string $uuid): IPxeMenu + public static function forClient(string $ip, ?string $uuid): IPxeMenu { $locationId = 0; if (Module::isAvailable('locations')) { $locationId = Location::getFromIpAndUuid($ip, $uuid); } $menu = self::forLocation($locationId); - // Super specialcase hackery: If this is a dedicated PVS, force the default to - // be bwlp/"minilinux" - $menu->maybeOverrideDefault($uuid); + if ($uuid !== null) { + // Super specialcase hackery: If this is a dedicated PVS, force the default to + // be bwlp/"minilinux" + $menu->maybeOverrideDefault($uuid); + } return $menu; } diff --git a/modules-available/serversetup-bwlp-ipxe/inc/localboot.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/localboot.inc.php index 1261ee29..4d1a56c7 100644 --- a/modules-available/serversetup-bwlp-ipxe/inc/localboot.inc.php +++ b/modules-available/serversetup-bwlp-ipxe/inc/localboot.inc.php @@ -29,6 +29,9 @@ iseq ${i} 10 || goto blubber', ], ]; + /** + * @return array{PCBIOS: string, EFI: string} + */ public static function getDefault(): array { $ret = explode(',', Property::get(self::PROPERTY_KEY, 'SANBOOT,GRUB')); diff --git a/modules-available/serversetup-bwlp-ipxe/inc/menuentry.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/menuentry.inc.php index 3106291e..727c456a 100644 --- a/modules-available/serversetup-bwlp-ipxe/inc/menuentry.inc.php +++ b/modules-available/serversetup-bwlp-ipxe/inc/menuentry.inc.php @@ -35,11 +35,7 @@ class MenuEntry public $md5pass = null; - /** - * @param int $menuEntryId - * @return MenuEntry|null - */ - public static function get($menuEntryId) + public static function get(int $menuEntryId): ?MenuEntry { $row = Database::queryFirst("SELECT e.menuentryid, e.entryid, e.refmenuid, e.hotkey, e.title, e.hidden, e.sortval, e.plainpass, e.md5pass, b.module, b.data AS bootentry, b.title AS betitle @@ -56,44 +52,42 @@ class MenuEntry * * @param array $row row from database */ - public function __construct($row) + public function __construct(array $row) { - if (is_array($row)) { - if (empty($row['title']) && !empty($row['betitle'])) { - $row['title'] = $row['betitle']; - } - foreach ($row as $key => $value) { - if (property_exists($this, $key)) { - $this->{$key} = $value; - } - } - $this->hotkey = self::getKeyCode($row['hotkey'] ?? ''); - if (!empty($row['bootentry'])) { - $this->bootEntry = BootEntry::fromJson($row['module'], $row['bootentry']); - } elseif (isset($row['refmenuid'])) { - $this->bootEntry = BootEntry::forMenu($row['refmenuid']); + if (empty($row['title']) && !empty($row['betitle'])) { + $row['title'] = $row['betitle']; + } + foreach ($row as $key => $value) { + if (property_exists($this, $key)) { + $this->{$key} = $value; } - $this->gap = (array_key_exists('entryid', $row) && $row['entryid'] === null && $row['refmenuid'] === null); } + $this->hotkey = self::getKeyCode($row['hotkey'] ?? ''); + if (!empty($row['bootentry'])) { + $this->bootEntry = BootEntry::fromJson($row['module'], $row['bootentry']); + } elseif (isset($row['refmenuid'])) { + $this->bootEntry = BootEntry::forMenu($row['refmenuid']); + } + $this->gap = (array_key_exists('entryid', $row) && $row['entryid'] === null && $row['refmenuid'] === null); settype($this->hidden, 'bool'); settype($this->gap, 'bool'); settype($this->sortval, 'int'); settype($this->menuentryid, 'int'); } - public function getBootEntryScript($builder) + public function getBootEntryScript(ScriptBuilderBase $builder): string { if ($this->bootEntry === null) return ''; return $this->bootEntry->toScript($builder); } - public function menuEntryId() + public function menuEntryId(): int { return $this->menuentryid; } - public function title() + public function title(): string { return $this->title; } @@ -142,7 +136,7 @@ class MenuEntry * * @return string[] list of known key names */ - public static function getKeyList() + public static function getKeyList(): array { return array_keys(self::getKeyArray()); } @@ -151,10 +145,9 @@ class MenuEntry * Get the key code ipxe expects for the given named * key. Returns false if the key name is unknown. * - * @param string $keyName * @return false|string Key code as hex string, or false if not found */ - public static function getKeyCode($keyName) + public static function getKeyCode(string $keyName) { $data = self::getKeyArray(); if (isset($data[$keyName])) @@ -166,7 +159,7 @@ class MenuEntry * @param string $keyName desired key name * @return string $keyName if it's known, empty string otherwise */ - public static function filterKeyName($keyName) + public static function filterKeyName(string $keyName): string { $data = self::getKeyArray(); if (isset($data[$keyName])) diff --git a/modules-available/serversetup-bwlp-ipxe/inc/pxelinux.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/pxelinux.inc.php index cc4f9756..ba547468 100644 --- a/modules-available/serversetup-bwlp-ipxe/inc/pxelinux.inc.php +++ b/modules-available/serversetup-bwlp-ipxe/inc/pxelinux.inc.php @@ -7,11 +7,14 @@ class PxeLinux /** * Takes a (partial) pxelinux menu and parses it into * a PxeMenu object. + * * @param string $input The pxelinux menu to parse - * @return PxeMenu the parsed menu + * @return ?PxeMenu the parsed menu, or null if input is not a PXELinux menu */ - public static function parsePxeLinux($input, $isCp437) + public static function parsePxeLinux(string $input, bool $isCp437): ?PxeMenu { + if (empty($input)) + return null; if ($isCp437) { $input = iconv('IBM437', 'UTF8//TRANSLIT//IGNORE', $input); } @@ -82,6 +85,8 @@ class PxeLinux if ($section !== null) { $menu->sections[] = $section; } + if (empty($menu->sections)) + return null; // Probably not a PXE menu but random text? foreach ($menu->sections as $section) { $section->mangle(); } @@ -93,13 +98,14 @@ class PxeLinux * to the given object. The map to look up the keyword has to be passed * as well as the object to set the value in. Map and object should * obviously match. + * * @param string $key keyword of parsed line * @param string $val raw value of currently parsed line (empty if not present) * @param array $map Map in which $key is looked up as key - * @param PxeMenu|PxeSection The object to set the parsed and sanitized value in + * @param PxeMenu|PxeSection $object The object to set the parsed and sanitized value in * @return bool true if the value was found in the map (and set in the object), false otherwise */ - private static function handleKeyword($key, $val, $map, $object) + private static function handleKeyword(string $key, string $val, array $map, $object): bool { if (!isset($map[$key])) return false; @@ -169,7 +175,7 @@ class PxeMenu /** * Check if any of the sections has the given label. */ - public function hasLabel($label) + public function hasLabel(string $label): bool { foreach ($this->sections as $section) { if ($section->label === $label) @@ -190,7 +196,7 @@ class PxeSection { /** - * @var string label used internally in PXEMENU definition to address this entry + * @var ?string label used internally in PXEMENU definition to address this entry */ public $label; /** @@ -248,7 +254,7 @@ class PxeSection */ public $hotkey; - public function __construct($label) { $this->label = $label; } + public function __construct(?string $label) { $this->label = $label; } public function mangle() { @@ -278,5 +284,21 @@ class PxeSection } } + /** + * Does this appear to be an entry that triggers localboot? + */ + public function isLocalboot(): bool + { + return $this->localBoot !== false || preg_match('/chain\.c32$/i', $this->kernel); + } + + /** + * Is this (most likely) a separating entry only that cannot be selected? + */ + public function isTextOnly(): bool + { + return ($this->label === null || empty($this->kernel)) && !$this->isHidden && !empty($this->title); + } + } diff --git a/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbase.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbase.inc.php index 84cfd7db..9cd07388 100644 --- a/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbase.inc.php +++ b/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbase.inc.php @@ -9,8 +9,10 @@ abstract class ScriptBuilderBase protected $platform = ''; + /** @var string */ protected $clientIp; + /** @var ?string */ protected $uuid; /** @@ -18,57 +20,57 @@ abstract class ScriptBuilderBase */ protected $hasExtension = false; - public function hasExtensions() + public function hasExtensions(): bool { return $this->hasExtension; } - public function platform() + public function platform(): string { return $this->platform; } - public function uuid() + public function uuid(): ?string { return $this->uuid; } - public function clientIp() + public function clientIp(): string { return $this->clientIp; } - public function getLabel() + public function getLabel(): string { return 'b' . mt_rand(100, 999) . 'x' . (++$this->lblId); } - public function __construct($platform = null, $serverIp = null, $slxExtensions = null) + public function __construct(?string $platform = null, ?string $serverIp = null, ?bool $slxExtensions = null) { - $this->clientIp = $_SERVER['REMOTE_ADDR']; + $this->clientIp = (string)$_SERVER['REMOTE_ADDR']; if (substr($this->clientIp, 0, 7) === '::ffff:') { $this->clientIp = substr($this->clientIp, 7); } $this->serverIp = $serverIp ?? $_SERVER['SERVER_ADDR'] ?? Property::getServerIp(); - $this->platform = $platform ?? Request::any('platform', false, 'string'); - if ($this->platform !== false) { + $this->platform = $platform ?? Request::any('platform', null, 'string'); + if ($this->platform !== null) { $this->platform = strtoupper($this->platform); } if ($this->platform !== 'EFI' && $this->platform !== 'PCBIOS') { $this->platform = ''; } $this->hasExtension = $slxExtensions ?? (bool)Request::any('slx-extensions', false, 'int'); - $this->uuid = Request::any('uuid', false, 'string'); - if (!preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i', $this->uuid)) { - $this->uuid = false; + $uuid = Request::any('uuid', null, 'string'); + if ($uuid !== null + && preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i', $uuid)) { + $this->uuid = (string)$uuid; } } /** * Output given string (script) to client, in a suitable encoding, headers, etc. - * @param string $string */ - public abstract function output($string); + public abstract function output(string $string): void; public abstract function bootstrapLive(); @@ -79,31 +81,22 @@ abstract class ScriptBuilderBase * @param bool $honorPassword Whether we should generate a password dialog if protected, or skip * @return string generated script/code/... */ - public abstract function getMenuEntry($menuEntry, $honorPassword = true); + public abstract function getMenuEntry(?MenuEntry $entry, bool $honorPassword = true): string; /** * @param BootEntry|null|false $bootEntry - * @return string */ - public abstract function getBootEntry($bootEntry); + public abstract function getBootEntry(?BootEntry $entry): string; - public abstract function getSpecial($special); + public abstract function getSpecial(string $special); - /** - * @param IPxeMenu|null $menu - * @return string - */ - public abstract function menuToScript($menu); + public abstract function menuToScript(IPxeMenu $menu): string; /** * Pass EITHER only $agnostic, OR $bios and/or $efi * If $agnostic is given, it should be used unconditionally, * and $bios/$efi should be ignored. - * @param ExecData $agnostic - * @param ExecData $bios - * @param ExecData $efi - * @return string */ - public abstract function execDataToScript($agnostic, $bios, $efi); + public abstract function execDataToScript(?ExecData $agnostic, ?ExecData $bios, ?ExecData $efi): string; }
\ No newline at end of file diff --git a/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbash.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbash.inc.php index 86b2931f..d6b542ec 100644 --- a/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbash.inc.php +++ b/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbash.inc.php @@ -3,39 +3,39 @@ class ScriptBuilderBash extends ScriptBuilderBase { - public function output($string) + public function output(string $string): void { echo $string; } - public function bootstrapLive() { return false; } + public function bootstrapLive(): bool { return false; } - public function getMenu(IPxeMenu $menu, bool $bootstrap) + public function getMenu(IPxeMenu $menu, bool $bootstrap): string { return $this->menuToScript($menu); } - public function getBootEntry($entry) + public function getBootEntry(?BootEntry $entry): string { - if (!$entry) { + if ($entry === null) { return "echo 'Invalid boot entry id'\nread -n1 -r _\n"; } return $entry->toScript($this); } - public function getMenuEntry($entry, $honorPassword = true) + public function getMenuEntry(?MenuEntry $entry, bool $honorPassword = true): string { if ($entry === null) return "echo 'Invalid menu entry id - press any key to continue'\nread -n1 -r _\n"; return $entry->getBootEntryScript($this); } - public function getSpecial($special) + public function getSpecial(string $special): string { return ''; // We can't really do localboot here I guess } - public function menuToScript($menu) + public function menuToScript(IPxeMenu $menu): string { $output = "declare -A items_name items_gap hotkey_item\ndeclare menu_default menu_timeout menu_title\n"; foreach ($menu->items as $entry) { @@ -59,7 +59,7 @@ class ScriptBuilderBash extends ScriptBuilderBase . "\nmenu_title=" . $this->bashString($menu->title) . "\n"; } - public function execDataToScript($agnostic, $bios, $efi) : string + public function execDataToScript(?ExecData $agnostic, ?ExecData $bios, ?ExecData $efi): string { if ($agnostic !== null) return $this->execDataToScriptInternal($agnostic); @@ -86,7 +86,7 @@ class ScriptBuilderBash extends ScriptBuilderBase return $script; } - private function bashString($string) + private function bashString(string $string): string { if (strpos($string, "'") === false) { return "'$string'"; diff --git a/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderipxe.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderipxe.inc.php index 3ca312aa..4896f598 100644 --- a/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderipxe.inc.php +++ b/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderipxe.inc.php @@ -3,7 +3,7 @@ class ScriptBuilderIpxe extends ScriptBuilderBase { - private function getUrlBase() + private function getUrlBase(): string { if (isset($_SERVER['REQUEST_URI'])) { $url = parse_url($_SERVER['REQUEST_URI']); @@ -23,7 +23,7 @@ class ScriptBuilderIpxe extends ScriptBuilderBase } - private function getUrlFull(&$hasExt, $key = null, $value = null) + private function getUrlFull(?bool &$hasExt = null, string $key = null, string $value = null): string { $url = parse_url($_SERVER['REQUEST_URI']); $urlbase = $this->getUrlBase(); @@ -58,7 +58,7 @@ class ScriptBuilderIpxe extends ScriptBuilderBase /** * Redirect to same URL, but add our extended params */ - private function redirect($key = null, $value = null) + private function redirect(string $key = null, string $value = null): string { // Redirect to self with added parameters $urlfull = $this->getUrlFull($hasExt, $key, $value); @@ -102,27 +102,24 @@ HERE; return false; } - public function getBootEntry($entry) + public function getBootEntry(?BootEntry $entry): string { - if (!$entry) { + if ($entry === null) { return "#!ipxe\nprompt --timeout 5000 Invalid boot entry id\n"; } return $entry->toScript($this); } - public function getMenu(IPxeMenu $menu, bool $bootstrap) + public function getMenu(IPxeMenu $menu, bool $bootstrap): string { if ($bootstrap) { return "#!ipxe\nimgfree ||\n" . $this->menuToScript($menu); } - $base = $this->getUrlFull($he); + $base = $this->getUrlFull(); return "#!ipxe\nset self {$base} ||\n" . $this->menuToScript($menu); } - /** - * @param IPxeMenu $menu - */ - public function menuToScript($menu) + public function menuToScript(IPxeMenu $menu): string { if ($this->hasExtension) { $slxConsoleUpdate = '--update'; @@ -186,12 +183,7 @@ HERE; return $output; } - /** - * @param $requestedDefaultId - * @param MenuEntry $entry - * @return string - */ - private function getMenuItemScript($requestedDefaultId, $entry) + private function getMenuItemScript(int $requestedDefaultId, MenuEntry $entry): string { $str = 'item '; if ($entry->gap) { @@ -220,7 +212,7 @@ HERE; return $str . " || prompt Could not create menu item for {$entry->menuentryid}\n"; } - public function getSpecial($special) + public function getSpecial(string $special): string { if ($special === 'localboot') { // Get preferred localboot method, depending on system model @@ -269,11 +261,7 @@ HERE; } } // Convert to actual ipxe code - if (isset($BOOT_METHODS[$localboot])) { - $localboot = $BOOT_METHODS[$localboot]; - } else { - $localboot = 'prompt Localboot not possible'; - } + $localboot = $BOOT_METHODS[$localboot] ?? 'prompt Localboot not possible'; $output = <<<BLA imgfree || console || @@ -287,7 +275,7 @@ BLA; return $output; } - public function output($string) + public function output(string $string): void { // iPXE introduced UTF-8 support at some point in 2022, and now expects all text/script files to be // encoded as such. Since we still offer to use older versions, we need to detect that here and handle @@ -319,10 +307,7 @@ BLA; const PROP_PW_SALT = 'ipxe.salt.'; - /** - * @param MenuEntry $menuEntryId - */ - private function passwordDialog($entry) + private function passwordDialog(MenuEntry $entry): string { if ($this->hasExtension) { $salt = dechex(mt_rand(0x100000, 0xFFFFFF)); @@ -348,7 +333,7 @@ chain -a \${self}&entryid={$entry->menuentryid}##params || goto fail || HERE; } - public function getMenuEntry($entry, $honorPassword = true) + public function getMenuEntry(?MenuEntry $entry, bool $honorPassword = true): string { if ($entry === null) return "#!ipxe\nprompt --timeout 10000 Invalid menu entry id\n"; @@ -402,7 +387,7 @@ HERE; return $output; } - public function execDataToScript($agnostic, $bios, $efi) : string + public function execDataToScript(?ExecData $agnostic, ?ExecData $bios, ?ExecData $efi) : string { if ($agnostic !== null) return $this->execDataToScriptInternal($agnostic) . "\ngoto fail\n"; diff --git a/modules-available/serversetup-bwlp-ipxe/page.inc.php b/modules-available/serversetup-bwlp-ipxe/page.inc.php index 8d4a366f..c9260687 100644 --- a/modules-available/serversetup-bwlp-ipxe/page.inc.php +++ b/modules-available/serversetup-bwlp-ipxe/page.inc.php @@ -123,23 +123,23 @@ class Page_ServerSetup extends Page $addr = false; if (User::hasPermission('ipxe.menu.view')) { - Dashboard::addSubmenu('?do=serversetup&show=menu', Dictionary::translate('submenu_menu', true)); + Dashboard::addSubmenu('?do=serversetup&show=menu', Dictionary::translate('submenu_menu')); } if (User::hasPermission('ipxe.bootentry.view')) { - Dashboard::addSubmenu('?do=serversetup&show=bootentry', Dictionary::translate('submenu_bootentry', true)); + Dashboard::addSubmenu('?do=serversetup&show=bootentry', Dictionary::translate('submenu_bootentry')); } if (User::hasPermission('edit.address')) { - Dashboard::addSubmenu('?do=serversetup&show=address', Dictionary::translate('submenu_address', true)); + Dashboard::addSubmenu('?do=serversetup&show=address', Dictionary::translate('submenu_address')); $addr = true; } if (User::hasPermission('download')) { - Dashboard::addSubmenu('?do=serversetup&show=download', Dictionary::translate('submenu_download', true)); + Dashboard::addSubmenu('?do=serversetup&show=download', Dictionary::translate('submenu_download')); } if (User::hasPermission('ipxe.localboot.*')) { - Dashboard::addSubmenu('?do=serversetup&show=localboot', Dictionary::translate('submenu_localboot', true)); + Dashboard::addSubmenu('?do=serversetup&show=localboot', Dictionary::translate('submenu_localboot')); } if (User::hasPermission('ipxe.bootentry.edit')) { - Dashboard::addSubmenu('?do=serversetup&show=import', Dictionary::translate('submenu_import', true)); + Dashboard::addSubmenu('?do=serversetup&show=import', Dictionary::translate('submenu_import')); } if (Request::get('show') === false) { $subs = Dashboard::getSubmenus(); @@ -219,7 +219,6 @@ class Page_ServerSetup extends Page break; default: Util::redirect('?do=serversetup'); - break; } } @@ -231,17 +230,17 @@ class Page_ServerSetup extends Page }); $files = []; $strings = [ - 'efi' => [Dictionary::translate('dl-efi', true) => 50], - 'pcbios' => [Dictionary::translate('dl-pcbios', true) => 51], - 'usb' => [Dictionary::translate('dl-usb', true) => 80], - 'hd' => [Dictionary::translate('dl-hd', true) => 81], - 'lkrn' => [Dictionary::translate('dl-lkrn', true) => 82], - 'i386' => [Dictionary::translate('dl-i386', true) => 10], - 'x86_64' => [Dictionary::translate('dl-x86_64', true) => 11], - 'ecm' => [Dictionary::translate('dl-usbnic', true) => 60], - 'ncm' => [Dictionary::translate('dl-usbnic', true) => 61], - 'ipxe' => [Dictionary::translate('dl-pcinic', true) => 62], - 'snp' => [Dictionary::translate('dl-snp', true) => 63], + 'efi' => [Dictionary::translate('dl-efi') => 50], + 'pcbios' => [Dictionary::translate('dl-pcbios') => 51], + 'usb' => [Dictionary::translate('dl-usb') => 80], + 'hd' => [Dictionary::translate('dl-hd') => 81], + 'lkrn' => [Dictionary::translate('dl-lkrn') => 82], + 'i386' => [Dictionary::translate('dl-i386') => 10], + 'x86_64' => [Dictionary::translate('dl-x86_64') => 11], + 'ecm' => [Dictionary::translate('dl-usbnic') => 60], + 'ncm' => [Dictionary::translate('dl-usbnic') => 61], + 'ipxe' => [Dictionary::translate('dl-pcinic') => 62], + 'snp' => [Dictionary::translate('dl-snp') => 63], ]; foreach ($list as $file) { if ($file[0] === '.') @@ -267,7 +266,10 @@ class Page_ServerSetup extends Page Render::addTemplate('download', ['files' => $files]); } - private function makeSelectArray($list, $defaults) + /** + * @return array{EFI: array, PCBIOS: array} + */ + private function makeSelectArray(array $list, array $defaults): array { $ret = ['EFI' => [], 'PCBIOS' => []]; foreach (['PCBIOS', 'EFI'] as $m) { @@ -326,7 +328,7 @@ class Page_ServerSetup extends Page GROUP BY be.entryid, be.title"); if (empty($bootentryTable)) { - if (Property::getServerIp() === false || Property::getServerIp() === 'invalid') { + if (Property::getServerIp() === 'invalid') { Message::addError('no-ip-set'); Util::redirect('?do=serversetup&show=address'); } @@ -379,7 +381,7 @@ class Page_ServerSetup extends Page )); } - private function hasMenuPermission($menuid, $permission) + private function hasMenuPermission(int $menuid, string $permission): bool { $allowedEditLocations = User::getAllowedLocations($permission); $allowEdit = in_array(0, $allowedEditLocations); @@ -466,7 +468,7 @@ class Page_ServerSetup extends Page if ($k === 'id') continue; $bootentry['otherFields'][] = [ - 'key' => Dictionary::translateFileModule($bootentry['module'], 'module', 'ipxe-' . $k, true), + 'key' => Dictionary::translateFileModule($bootentry['module'], 'module', 'ipxe-' . $k), 'value' => is_bool($v) ? Util::boolToString($v) : $v, ]; } @@ -483,16 +485,16 @@ class Page_ServerSetup extends Page continue; // Naming and agnostic if ($bootentry['data']['arch'] === BootEntry::BIOS) { - $bootentry['data']['arch'] = Dictionary::translateFile('template-tags','lang_biosOnly', true); + $bootentry['data']['arch'] = Dictionary::translateFile('template-tags','lang_biosOnly'); unset($bootentry['data']['EFI']); } elseif ($bootentry['data']['arch'] === BootEntry::EFI) { - $bootentry['data']['arch'] = Dictionary::translateFile('template-tags','lang_efiOnly', true); + $bootentry['data']['arch'] = Dictionary::translateFile('template-tags','lang_efiOnly'); unset($bootentry['data']['PCBIOS']); } elseif ($bootentry['data']['arch'] === BootEntry::AGNOSTIC) { - $bootentry['data']['arch'] = Dictionary::translateFile('template-tags','lang_archAgnostic', true); + $bootentry['data']['arch'] = Dictionary::translateFile('template-tags','lang_archAgnostic'); unset($bootentry['data']['EFI']); } else { - $bootentry['data']['arch'] = Dictionary::translateFile('template-tags','lang_archBoth', true); + $bootentry['data']['arch'] = Dictionary::translateFile('template-tags','lang_archBoth'); } foreach ($bootentry['data'] as &$e) { if (isset($e['initRd'])) { @@ -537,12 +539,7 @@ class Page_ServerSetup extends Page } if ($row['module'][0] === '.') { // either script or exec entry - $json = json_decode($row['data'], true); - if (!is_array($json)) { - Message::addError('unknown-bootentry-type', $id); - Util::redirect('?do=serversetup&show=bootentry'); - } - $entry = BootEntry::fromJson($row['module'], $json); + $entry = BootEntry::fromJson($row['module'], $row['data']); if ($entry === null) { Message::addError('unknown-bootentry-type', $id); Util::redirect('?do=serversetup&show=bootentry'); @@ -599,7 +596,7 @@ class Page_ServerSetup extends Page { $status = IPxeBuilder::getVersionTaskResult(); $versions = false; - if ($status === false) { + if ($status === null) { $error = 'Taskmanager down'; } elseif (!empty($status['versions'])) { $versions = $status['versions']; @@ -801,7 +798,7 @@ class Page_ServerSetup extends Page || $defaultEntryId === null)) { // if still null, use whatever as fallback, in case user didn't select any $defaultEntryId = $newKey; } - $keepIds[] = (int)$newKey; + $keepIds[] = $newKey; if (!empty($entry['plainpass'])) { Database::exec('UPDATE serversetup_menuentry SET md5pass = :md5pass WHERE menuentryid = :id', [ 'md5pass' => IPxe::makeMd5Pass($entry['plainpass'], $newKey), @@ -894,7 +891,7 @@ class Page_ServerSetup extends Page } else { // Module hook $hook = Hook::loadSingle($type, 'ipxe-bootentry'); - if ($hook === false) { + if ($hook === null) { Message::addError('unknown-bootentry-type', $type); return; } @@ -1073,7 +1070,7 @@ class Page_ServerSetup extends Page Util::redirect('?do=serversetup&show=import'); } $menu = PxeLinux::parsePxeLinux($content, false); - if (empty($menu->sections)) { + if ($menu === null) { Message::addWarning('import-no-entries'); Util::redirect('?do=serversetup&show=import'); } @@ -1082,8 +1079,8 @@ class Page_ServerSetup extends Page IPxe::importPxeMenuEntries($menu, $foo); Util::redirect('?do=serversetup&show=bootentry'); } else { - $id = IPxe::insertMenu($menu, 'Imported Menu', false, 0, [], []); - if ($id === false) { + $id = IPxe::insertMenu($menu, 'Imported Menu', null, 0, [], []); + if ($id === null) { Message::addError('import-error'); Util::redirect('?do=serversetup&show=import'); } else { diff --git a/modules-available/session/page.inc.php b/modules-available/session/page.inc.php index 71f24886..9ced405a 100644 --- a/modules-available/session/page.inc.php +++ b/modules-available/session/page.inc.php @@ -23,7 +23,6 @@ class Page_Session extends Page } elseif ($action === 'logout') { // Log user out (or do nothing if not logged in) User::logout(); - Util::redirect('?do=main'); } elseif ($action === 'changepw') { if (!User::isLoggedIn()) { Util::redirect('?do=main'); @@ -59,7 +58,7 @@ class Page_Session extends Page Util::redirect('?do=session'); } else { // No action, change title to session list - Render::setTitle(Dictionary::translate('page-title-session-list', true)); + Render::setTitle(Dictionary::translate('page-title-session-list')); } } diff --git a/modules-available/statistics/api.inc.php b/modules-available/statistics/api.inc.php index 6875193d..f519380f 100644 --- a/modules-available/statistics/api.inc.php +++ b/modules-available/statistics/api.inc.php @@ -519,7 +519,7 @@ if ($type[0] === '.') { * @param array $old row from DB with client's old data * @param array $new new data to be written */ -function checkHardwareChange($old, $new) +function checkHardwareChange(array $old, array $new): void { if ($new['mbram'] !== 0) { if ($new['mbram'] < 6200) { diff --git a/modules-available/statistics/baseconfig/getconfig.inc.php b/modules-available/statistics/baseconfig/getconfig.inc.php index 7bf25d5d..f90cd49d 100644 --- a/modules-available/statistics/baseconfig/getconfig.inc.php +++ b/modules-available/statistics/baseconfig/getconfig.inc.php @@ -1,14 +1,17 @@ <?php +/** @var ?string $uuid */ +/** @var ?string $ip */ + // Location handling: figure out location if (Request::any('force', 0, 'int') === 1 && Request::any('module', false, 'string') === 'statistics') { // Force location for testing, but require logged in admin if (User::load()) { - $uuid = Request::any('value', '', 'string'); + $uuid = Request::any('value', null, 'string'); } } -if (!$uuid) // Required at this point, bail out if not given +if ($uuid === null) // Required at this point, bail out if not given return; // Query machine specific settings @@ -17,20 +20,22 @@ foreach ($res as $row) { ConfigHolder::add($row['setting'], $row['value'], 500); } +if ($ip !== null) { // Statistics about booted system -ConfigHolder::addPostHook(function() use ($ip, $uuid) { - $type = Request::get('type', 'default', 'string'); - // System - if ($type !== 'default') { - Database::exec("INSERT INTO statistic (dateline, typeid, clientip, machineuuid, username, data) + ConfigHolder::addPostHook(function () use ($ip, $uuid) { + $type = Request::get('type', 'default', 'string'); + // System + if ($type !== 'default') { + Database::exec("INSERT INTO statistic (dateline, typeid, clientip, machineuuid, username, data) VALUES (UNIX_TIMESTAMP(), :type, :ip, :uuid, '', :data)", - ['type' => 'boot-system', 'ip' => $ip, 'uuid' => $uuid, 'data' => $type]); - } - // Runmode - $mode = ConfigHolder::get('SLX_RUNMODE_MODULE'); - if (!empty($mode)) { - Database::exec("INSERT INTO statistic (dateline, typeid, clientip, machineuuid, username, data) + ['type' => 'boot-system', 'ip' => $ip, 'uuid' => $uuid, 'data' => $type]); + } + // Runmode + $mode = ConfigHolder::get('SLX_RUNMODE_MODULE'); + if (!empty($mode)) { + Database::exec("INSERT INTO statistic (dateline, typeid, clientip, machineuuid, username, data) VALUES (UNIX_TIMESTAMP(), :type, :ip, :uuid, '', :data)", - ['type' => 'boot-runmode', 'ip' => $ip, 'uuid' => $uuid, 'data' => $mode]); - } -}); + ['type' => 'boot-runmode', 'ip' => $ip, 'uuid' => $uuid, 'data' => $mode]); + } + }); +}
\ No newline at end of file diff --git a/modules-available/statistics/hooks/translation.inc.php b/modules-available/statistics/hooks/translation.inc.php index 4d09553a..f7a50b0d 100644 --- a/modules-available/statistics/hooks/translation.inc.php +++ b/modules-available/statistics/hooks/translation.inc.php @@ -16,10 +16,8 @@ $HANDLER['subsections'] = array( /** * Configuration categories. - * @param \Module $module - * @return array */ -$HANDLER['grep_filters'] = function($module) { +$HANDLER['grep_filters'] = function (Module $module): array { if (!$module->activate(1, false)) return array(); $want = StatisticsFilter::$columns; diff --git a/modules-available/statistics/inc/hardwareinfo.inc.php b/modules-available/statistics/inc/hardwareinfo.inc.php index 56ea38cd..7e0bdba8 100644 --- a/modules-available/statistics/inc/hardwareinfo.inc.php +++ b/modules-available/statistics/inc/hardwareinfo.inc.php @@ -21,9 +21,8 @@ class HardwareInfo * the resulting machine that has the greatest "lastseen" value will be used. * @param ?string $uuid UUID of machine * @param ?string $mac MAC of machine - * @return string */ - public static function getKclModifications($uuid = null, $mac = null): string + public static function getKclModifications(?string $uuid = null, ?string $mac = null): string { if ($uuid === null && $mac === null) { $uuid = Request::get('uuid', '', 'string'); diff --git a/modules-available/statistics/inc/hardwareparser.inc.php b/modules-available/statistics/inc/hardwareparser.inc.php index 1c549976..428f7d55 100644 --- a/modules-available/statistics/inc/hardwareparser.inc.php +++ b/modules-available/statistics/inc/hardwareparser.inc.php @@ -38,8 +38,6 @@ class HardwareParser /** * Decode JEDEC ID to according manufacturer - * @param string $string - * @return string */ public static function decodeJedec(string $string): string { @@ -79,10 +77,7 @@ class HardwareParser return $string; } - /** - * @return ?string - */ - private static function decodeBankAndId(array $out, bool $bankFirst) + private static function decodeBankAndId(array $out, bool $bankFirst): ?string { // 16bit encoding from DDR3+: lower byte is number of 0x7f bytes, upper byte is id within bank $id = hexdec(str_replace(' ', '', $out[1])); @@ -100,10 +95,7 @@ class HardwareParser return self::lookupJedec($bank, $id); } - /** - * @return ?string - */ - private static function lookupJedec(int $bank, int $id) + private static function lookupJedec(int $bank, int $id): ?string { static $data = false; if ($data === false) { @@ -119,11 +111,9 @@ class HardwareParser * base representation, meant for comparison. For example, Voltages are converted * to Millivolts, Anything measured in [KMGT]Bytes (per second) to bytes, GHz to * Hz, and so on. - * @param string $key - * @param string $value * @return ?int value, or null if not numeric */ - private static function toNumeric(string $key, string $val) + private static function toNumeric(string $key, string $val): ?int { $key = strtolower($key); // Normalize voltage to mV @@ -208,7 +198,7 @@ class HardwareParser * @param int $hwid hw global hw id * @param string $pathId unique identifier for the local instance of this hw, e.q. PCI slot, /dev path, something that handles the case that there are multiple instances of the same hardware in one machine * @param array $props KV-pairs of properties to write for this instance; can be empty - * @return int + * @return int ID of mapping in DB */ private static function writeLocalHardwareData(string $uuid, int $hwid, string $pathId, array $props): int { @@ -330,7 +320,7 @@ class HardwareParser * @param array $data Hardware info, deserialized assoc array. * @return ?array id44mb and id45mb as calculated from given HDD data */ - public static function parseMachine(string $uuid, array $data) + public static function parseMachine(string $uuid, array $data): ?array { $version = $data['version'] ?? 0; if ($version != 2) { @@ -510,12 +500,12 @@ class HardwareParser if (empty($dev['readlink'])) // This is the canonical entry name directly under /dev/, e.g. /dev/sda continue; // Use smartctl as the source of truth, lsblk as fallback if data is missing - if (!isset($dev['smartctl'])) { + if (!isset($dev['smartctl']) || !is_array($dev['smartctl'])) { $smart = []; } else { $smart =& $dev['smartctl']; } - if (!isset($dev['lsblk']['blockdevices'][0])) { + if (!isset($dev['lsblk']['blockdevices'][0]) || !is_array($dev['lsblk']['blockdevices'][0])) { $lsblk = []; } else { $lsblk =& $dev['lsblk']['blockdevices'][0]; @@ -626,7 +616,7 @@ class HardwareParser } $table['unused'] = $size - $used; $table['dev'] = $dev['readlink']; - $table += self::propsFromArray($smart + ($lsblk ?? []), + $table += self::propsFromArray($smart + $lsblk, 'serial_number', 'firmware_version', 'interface_speed//current//string', 'smart_status//passed', 'temperature//current', 'temperature//min', 'temperature//max', diff --git a/modules-available/statistics/inc/hardwareparserlegacy.inc.php b/modules-available/statistics/inc/hardwareparserlegacy.inc.php index 7ee39bce..a6ac6d5e 100644 --- a/modules-available/statistics/inc/hardwareparserlegacy.inc.php +++ b/modules-available/statistics/inc/hardwareparserlegacy.inc.php @@ -243,10 +243,11 @@ class HardwareParserLegacy $ramOk = true; } if ($ramOk && preg_match('/^\s*Number Of Devices:\s+(\d+)\s*$/i', $line, $out)) { - $row['Memory Slot Count'] += $out[1]; + $row['Memory Slot Count'] += (int)$out[1]; } if ($ramOk && preg_match('/^\s*Maximum Capacity:\s+(\d.+)/i', $line, $out)) { - $row['Memory Maximum Capacity'] += HardwareParser::convertSize($out[1], 'G', false); + /** @var array{"Memory Slot Count": int} $row */ + $row['Memory Maximum Capacity'] += (int)HardwareParser::convertSize($out[1], 'G', false); } } elseif ($section === 'Memory Device') { if (preg_match('/^\s*Size:\s*(.*?)\s*$/i', $line, $out)) { diff --git a/modules-available/statistics/inc/hardwarequery.inc.php b/modules-available/statistics/inc/hardwarequery.inc.php index 4f0ec344..6b1b5043 100644 --- a/modules-available/statistics/inc/hardwarequery.inc.php +++ b/modules-available/statistics/inc/hardwarequery.inc.php @@ -45,25 +45,23 @@ class HardwareQuery */ public function addForeignJoin(bool $global, string $prop, string $jTable, string $jColumn, string $condColumn = '', $condVal = null) { - if (isset($this->columns[$jTable])) + if (isset($this->columns["$jTable.$prop"])) return; - if (!isset($this->columns[$prop])) { - if ($global) { - $srcTable = 'shw'; - $table = 'statistic_hw_prop'; - $column = 'hwid'; - } else { - $srcTable = 'mxhw'; - $table = 'machine_x_hw_prop'; - $column = 'machinehwid'; - } - $tid = $this->id(); - $pid = $this->id(); - $this->joins[$prop] = "INNER JOIN $table $tid ON ($srcTable.$column = $tid.$column - AND $tid.prop = :$pid)"; - $this->args[$pid] = $prop; - $this->columns[$prop] = "$tid.`value` AS `$prop`"; + if ($global) { + $srcTable = 'shw'; + $table = 'statistic_hw_prop'; + $column = 'hwid'; + } else { + $srcTable = 'mxhw'; + $table = 'machine_x_hw_prop'; + $column = 'machinehwid'; } + $tid = $this->id(); + $pid = $this->id(); + $this->joins[$prop] = "INNER JOIN $table $tid ON ($srcTable.$column = $tid.$column + AND $tid.prop = :$pid)"; + $this->args[$pid] = $prop; + $this->columns[$prop] = "$tid.`value` AS `$prop`"; $jtid = $this->id(); $cond = ''; if (!empty($condColumn)) { @@ -106,10 +104,8 @@ class HardwareQuery /** * Join the machine table and add the given column from it to the SELECT - * @param string $column - * @return void */ - public function addMachineColumn(string $column) + public function addMachineColumn(string $column): void { if (isset($this->columns[$column])) return; @@ -163,13 +159,11 @@ class HardwareQuery } else { $groupBy = ''; } - $query = 'SELECT ' . implode(', ', $columns) + return 'SELECT ' . implode(', ', $columns) . ' FROM statistic_hw shw ' . implode(' ', $this->joins) . ' WHERE ' . implode(' AND ', $this->where) . $groupBy; - //error_log($query); - return $query; } } diff --git a/modules-available/statistics/inc/statistics.inc.php b/modules-available/statistics/inc/statistics.inc.php index d27c1a6a..2a9ca3c9 100644 --- a/modules-available/statistics/inc/statistics.inc.php +++ b/modules-available/statistics/inc/statistics.inc.php @@ -7,7 +7,7 @@ class Statistics private static $machineFields = false; - private static function initFields($returnData) + private static function initFields(int $returnData): string { if (self::$machineFields === false) { $r = new ReflectionClass('Machine'); @@ -25,17 +25,15 @@ class Statistics } /** - * @param string $machineuuid * @param int $returnData What kind of data to return Machine::NO_DATA, Machine::RAW_DATA, ... - * @return \Machine|false */ - public static function getMachine($machineuuid, $returnData) + public static function getMachine(string $machineuuid, int $returnData): ?Machine { $fields = self::initFields($returnData); $row = Database::queryFirst("SELECT $fields FROM machine WHERE machineuuid = :machineuuid", compact('machineuuid')); if ($row === false) - return false; + return null; $m = new Machine(); foreach ($row as $key => $val) { $m->{$key} = $val; @@ -44,12 +42,11 @@ class Statistics } /** - * @param string $ip * @param int $returnData What kind of data to return Machine::NO_DATA, Machine::RAW_DATA, ... * @param string $sort something like 'lastseen ASC' - not sanitized, don't pass user input! - * @return \Machine[] list of matches + * @return Machine[] list of matches */ - public static function getMachinesByIp($ip, $returnData, $sort = false) + public static function getMachinesByIp(string $ip, int $returnData, bool $sort = false): array { $fields = self::initFields($returnData); @@ -74,7 +71,7 @@ class Statistics const OFFLINE_LENGTH = '~offline-length'; const SUSPEND_LENGTH = '~suspend-length'; - public static function logMachineState($uuid, $ip, $type, $start, $length, $username = '') + public static function logMachineState(string $uuid, string $ip, string $type, int $start, int $length, string $username = ''): int { return Database::exec('INSERT INTO statistic (dateline, typeid, machineuuid, clientip, username, data)' . " VALUES (:start, :type, :uuid, :clientip, :username, :length)", array( diff --git a/modules-available/statistics/inc/statisticsfilter.inc.php b/modules-available/statistics/inc/statisticsfilter.inc.php index cfc724c1..5e6448c7 100644 --- a/modules-available/statistics/inc/statisticsfilter.inc.php +++ b/modules-available/statistics/inc/statisticsfilter.inc.php @@ -94,9 +94,7 @@ abstract class StatisticsFilter /** * Called to get an instance of DatabaseFilter that binds the given $op and $argument to this filter. - * @param string $op * @param string[]|string $argument - * @return DatabaseFilter */ public function bind(string $op, $argument): DatabaseFilter { return new DatabaseFilter($this, $op, $argument); } @@ -109,6 +107,7 @@ abstract class StatisticsFilter if (empty($this->ops)) return; if (!in_array($operator, $this->ops)) { + // Yes keep $this in this call, get_class() !== get_class($this) ErrorHandler::traceError("Invalid op '$operator' for " . get_class($this) . '::' . $this->column); } } @@ -179,10 +178,7 @@ abstract class StatisticsFilter return $filters; } - /** - * @param \StatisticsFilterSet $filterSet - */ - public static function renderFilterBox($show, $filterSet) + public static function renderFilterBox(string $show, StatisticsFilterSet $filterSet): void { // Build location list, with permissions if (Module::isAvailable('locations')) { @@ -194,7 +190,7 @@ abstract class StatisticsFilter foreach (self::$columns as $key => $filter) { $col = [ 'key' => $key, - 'name' => Dictionary::translateFile('filters', $key, true), + 'name' => Dictionary::translateFile('filters', $key), 'placeholder' => $filter->placeholder, ]; $bind = $filterSet->hasFilterKey($key); @@ -207,6 +203,7 @@ abstract class StatisticsFilter $col['inputclass'] = 'is-date'; } elseif ($filter->type() === 'enum') { $col['enum'] = true; + /** @var EnumStatisticsFilter $filter */ $col['values'] = $filter->values; if ($bind !== null) { // Current value from GET @@ -550,15 +547,14 @@ class StateStatisticsFilter extends EnumStatisticsFilter public function whereClause(string $operator, $argument, array &$args, array &$joins): string { $map = [ 'on' => ['IDLE', 'OCCUPIED'], 'off' => ['OFFLINE'], 'idle' => ['IDLE'], 'occupied' => ['OCCUPIED'], 'standby' => ['STANDBY'] ]; - $neg = $operator == '!=' ? 'NOT ' : ''; + $neg = $operator === '!=' ? 'NOT ' : ''; if (array_key_exists($argument, $map)) { $key = StatisticsFilter::getNewKey($this->column); $args[$key] = $map[$argument]; return " m.state $neg IN ( :$key ) "; - } else { - Message::addError('invalid-filter-argument', 'state', $argument); - return ' 1'; } + Message::addError('invalid-filter-argument', 'state', $argument); + return ' 1'; } } @@ -623,7 +619,7 @@ class IpStatisticsFilter extends StatisticsFilter } elseif (strpos($argument, '/') !== false) { // TODO: IPv6 CIDR $range = IpUtil::parseCidr($argument); - if ($range === false) { + if ($range === null) { Message::addError('invalid-cidr-notion', $argument); return '0'; } @@ -838,9 +834,6 @@ class DatabaseFilter /** * Called from StatisticsFilterSet::makeFragments() to build the final query. - * @param array $args - * @param array $joins - * @return string */ public function whereClause(array &$args, array &$joins): string { diff --git a/modules-available/statistics/inc/statisticsfilterset.inc.php b/modules-available/statistics/inc/statisticsfilterset.inc.php index 102cba42..26595e93 100644 --- a/modules-available/statistics/inc/statisticsfilterset.inc.php +++ b/modules-available/statistics/inc/statisticsfilterset.inc.php @@ -9,7 +9,10 @@ class StatisticsFilterSet private $cache = false; - public function __construct($filters) + /** + * @param DatabaseFilter[] $filters + */ + public function __construct(array $filters) { $this->filters = $filters; } @@ -49,9 +52,9 @@ class StatisticsFilterSet /** * @param string $type filter type (class name) - * @return ?DatabaseFilter The filter, false if not found + * @return ?DatabaseFilter The filter, null if not found */ - public function hasFilter(string $type) + public function hasFilter(string $type): ?DatabaseFilter { foreach ($this->filters as $filter) { if ($filter->isClass($type)) { @@ -63,9 +66,9 @@ class StatisticsFilterSet /** * @param string $type filter type key/id - * @return ?DatabaseFilter The filter, false if not found + * @return ?DatabaseFilter The filter, null if not found */ - public function hasFilterKey(string $type) + public function hasFilterKey(string $type): ?DatabaseFilter { if (isset($this->filters[$type])) return $this->filters[$type]; @@ -102,8 +105,8 @@ class StatisticsFilterSet */ public function getAllowedLocations() { - if (isset($this->filters['permissions']->argument) && is_array($this->filters['permissions']->argument)) - return $this->filters['permissions']->argument; + if (isset($this->filters['permissions']) && is_array($this->filters['permissions']->argument)) + return (array)$this->filters['permissions']->argument; return false; } diff --git a/modules-available/statistics/inc/statisticshooks.inc.php b/modules-available/statistics/inc/statisticshooks.inc.php index de20d599..b17cf4a9 100644 --- a/modules-available/statistics/inc/statisticshooks.inc.php +++ b/modules-available/statistics/inc/statisticshooks.inc.php @@ -5,7 +5,7 @@ class StatisticsHooks private static $row = false; - private static function getRow($machineuuid) + private static function getRow(string $machineuuid) { if (self::$row !== false) return; @@ -13,7 +13,7 @@ class StatisticsHooks ['machineuuid' => $machineuuid]); } - public static function getBaseconfigName($machineuuid) + public static function getBaseconfigName(string $machineuuid): string { self::getRow($machineuuid); if (self::$row === false) @@ -21,7 +21,7 @@ class StatisticsHooks return self::$row['hostname'] ?: self::$row['clientip']; } - public static function baseconfigLocationResolver($machineuuid) + public static function baseconfigLocationResolver(string $machineuuid): int { self::getRow($machineuuid); if (self::$row === false) @@ -30,10 +30,11 @@ class StatisticsHooks } /** - * Hook to get inheritance tree for all config vars - * @param int $machineuuid MachineUUID currently being edited + * Hook to get inheritance tree for all config vars. + * + * @param string $machineuuid MachineUUID currently being edited */ - public static function baseconfigInheritance($machineuuid) + public static function baseconfigInheritance(string $machineuuid): array { self::getRow($machineuuid); if (self::$row === false) diff --git a/modules-available/statistics/inc/statisticsstyling.inc.php b/modules-available/statistics/inc/statisticsstyling.inc.php index 1843fe30..0e158026 100644 --- a/modules-available/statistics/inc/statisticsstyling.inc.php +++ b/modules-available/statistics/inc/statisticsstyling.inc.php @@ -3,7 +3,7 @@ class StatisticsStyling { - public static function ramColorClass($mb) + public static function ramColorClass(int $mb): string { if ($mb < 2500) { return 'danger'; @@ -15,7 +15,7 @@ class StatisticsStyling return ''; } - public static function kvmColorClass($state) + public static function kvmColorClass(string $state): string { if ($state === 'DISABLED') { return 'danger'; @@ -27,7 +27,7 @@ class StatisticsStyling return ''; } - public static function hddColorClass($gb) + public static function hddColorClass(int $gb): string { if ($gb < 7) { return 'danger'; diff --git a/modules-available/statistics/page.inc.php b/modules-available/statistics/page.inc.php index 71c9dea3..4f11e835 100644 --- a/modules-available/statistics/page.inc.php +++ b/modules-available/statistics/page.inc.php @@ -29,7 +29,7 @@ class Page_Statistics extends Page foreach (['projectors', 'replace', 'hints'] as $section) { Dashboard::addSubmenu('?do=statistics&show=' . $section, - Dictionary::translate('submenu_' . $section, true)); + Dictionary::translate('submenu_' . $section)); } $this->show = Request::any('show', false, 'string'); diff --git a/modules-available/statistics/pages/list.inc.php b/modules-available/statistics/pages/list.inc.php index 12689e97..b318cc68 100644 --- a/modules-available/statistics/pages/list.inc.php +++ b/modules-available/statistics/pages/list.inc.php @@ -22,10 +22,7 @@ class SubPage } - /** - * @param \StatisticsFilterSet $filterSet - */ - private static function showMachineList(StatisticsFilterSet $filterSet) + private static function showMachineList(StatisticsFilterSet $filterSet): void { Module::isAvailable('js_stupidtable'); $filterSet->makeFragments($where, $join, $args); @@ -160,7 +157,7 @@ class SubPage $roomsvg = null; $side = []; if (!empty($rows) && !empty($colValCount)) { - if (count($colValCount['locationid']) === 1 && ($lid = array_key_first($colValCount['locationid'])) + if (count($colValCount['locationid']) === 1 && ($lid = array_key_first($colValCount['locationid'])) !== null && Module::isAvailable('roomplanner')) { $roomsvg = PvsGenerator::generateSvg($lid, false, 0, 1, true, $colValCount['locationid'][$lid]); } @@ -216,14 +213,4 @@ class SubPage return $ret; } -} - -// Remove when we require >= 7.3.0 -if (!function_exists('array_key_first')) { - function array_key_first(array $arr) { - foreach($arr as $key => $unused) { - return $key; - } - return NULL; - } }
\ No newline at end of file diff --git a/modules-available/statistics/pages/machine.inc.php b/modules-available/statistics/pages/machine.inc.php index 2250c4b9..24bf7c1e 100644 --- a/modules-available/statistics/pages/machine.inc.php +++ b/modules-available/statistics/pages/machine.inc.php @@ -686,9 +686,9 @@ class SubPage } if (!is_array($json) || !isset($json['system'])) return ['error' => 'Malformed JSON, no system key']; - if (isset($json['system'][$system]) && isset($json['system'][$system]['fixes']) && isset($json['system'][$system]['match'])) { + if (isset($json['system'][$system]['fixes']) && isset($json['system'][$system]['match'])) { $match =& $json['system'][$system]; - } elseif (isset($json['mainboard'][$mainboard]) && isset($json['mainboard'][$mainboard]['fixes']) && isset($json['mainboard'][$mainboard]['match'])) { + } elseif (isset($json['mainboard'][$mainboard]['fixes']) && isset($json['mainboard'][$mainboard]['match'])) { $match =& $json['mainboard'][$mainboard]; } else { return ['status' => 0]; diff --git a/modules-available/statistics/pages/summary.inc.php b/modules-available/statistics/pages/summary.inc.php index 8b476f36..d0538b38 100644 --- a/modules-available/statistics/pages/summary.inc.php +++ b/modules-available/statistics/pages/summary.inc.php @@ -43,10 +43,7 @@ class SubPage Render::closeTag('div'); } - /** - * @param \StatisticsFilterSet $filterSet - */ - private static function showSummary(StatisticsFilterSet $filterSet) + private static function showSummary(StatisticsFilterSet $filterSet): void { $filterSet->makeFragments($where, $join, $args); $known = Database::queryFirst("SELECT Count(*) AS val FROM machine m $join WHERE $where", $args); @@ -66,6 +63,10 @@ class SubPage 'badhdd' => $hdd['val'], ]; // Graph + $labels = []; + $points1 = []; + $points2 = []; + $lectures = []; // Get locations if ($filterSet->suitableForUsageGraph()) { $locFilter = $filterSet->hasFilter('LocationStatisticsFilter'); @@ -89,10 +90,6 @@ class SubPage $cutoff = time() - 2 * 86400; $res = Database::simpleQuery("SELECT dateline, data FROM statistic WHERE typeid = '~stats' AND dateline > $cutoff ORDER BY dateline DESC"); - $labels = []; - $points1 = []; - $points2 = []; - $lectures = []; // Get max from 4 consecutive values, which should be 4*5 = 20m $sum = 0; foreach ($res as $row) { @@ -143,10 +140,7 @@ class SubPage Render::addTemplate('summary', $data); } - /** - * @param \StatisticsFilterSet $filterSet - */ - private static function showSystemModels($filterSet) + private static function showSystemModels(StatisticsFilterSet $filterSet): void { $filterSet->makeFragments($where, $join, $args); $res = Database::simpleQuery('SELECT systemmodel, Round(AVG(realcores)) AS cores, Count(*) AS `count` FROM machine m' @@ -186,10 +180,7 @@ class SubPage return $value; } - /** - * @param \StatisticsFilterSet $filterSet - */ - private static function showMemory($filterSet) + private static function showMemory(StatisticsFilterSet $filterSet): void { $filterSet->makeFragments($where, $join, $args); $res = Database::simpleQuery("SELECT mbram, Count(*) AS `count` FROM machine m $join @@ -221,10 +212,7 @@ class SubPage Render::addTemplate('memory', $data); } - /** - * @param \StatisticsFilterSet $filterSet - */ - private static function showKvmState($filterSet) + private static function showKvmState(StatisticsFilterSet $filterSet): void { $filterSet->makeFragments($where, $join, $args); $colors = ['UNKNOWN' => '#666', 'UNSUPPORTED' => '#ea5', 'DISABLED' => '#e55', 'ENABLED' => '#6d6']; @@ -243,10 +231,7 @@ class SubPage Render::addTemplate('kvmstate', array('rows' => $lines, 'json' => json_encode($json))); } - /** - * @param \StatisticsFilterSet $filterSet - */ - private static function showId44($filterSet) + private static function showId44(StatisticsFilterSet $filterSet): void { $filterSet->makeFragments($where, $join, $args); $res = Database::simpleQuery("SELECT id44mb, Count(*) AS `count` FROM machine m $join WHERE $where GROUP BY id44mb", $args); @@ -283,10 +268,7 @@ class SubPage Render::addTemplate('id44', $data); } - /** - * @param \StatisticsFilterSet $filterSet - */ - private static function showLatestMachines(StatisticsFilterSet $filterSet) + private static function showLatestMachines(StatisticsFilterSet $filterSet): void { $filterSet->makeFragments($where, $join, $args); $args['cutoff'] = ceil(time() / 3600) * 3600 - 86400 * 10; @@ -323,7 +305,7 @@ class SubPage - private static function capChart(&$json, &$rows, $cutoff, $minSlice = 0.015) + private static function capChart(array &$json, array &$rows, float $cutoff, float $minSlice = 0.015): void { $total = 0; foreach ($json as $entry) { @@ -358,9 +340,8 @@ class SubPage /** * @param array $json decoded json ~stats data * @param ?int[] $locations - * @param ?string $op */ - private static function mangleStatsJson(array $json, $locations, $op): array + private static function mangleStatsJson(array $json, ?array $locations, ?string $op): array { // Total, On, InUse, Lectures $retval = [0, 0, 0, 0]; diff --git a/modules-available/statistics_reporting/inc/getdata.inc.php b/modules-available/statistics_reporting/inc/getdata.inc.php index 90af0c58..75db119d 100644 --- a/modules-available/statistics_reporting/inc/getdata.inc.php +++ b/modules-available/statistics_reporting/inc/getdata.inc.php @@ -24,7 +24,7 @@ class GetData return $carry . sprintf("%04d", $item); }) . sprintf("%04d", $entry['locationid']); } else { - $entry['locationname'] = Dictionary::translate('notAssigned', true); + $entry['locationname'] = Dictionary::translate('notAssigned'); } if ($anonymize) { unset($entry['locationid']); @@ -56,7 +56,8 @@ class GetData } // total - public static function total($flags = 0) { + public static function total(int $flags = 0): array + { $printable = 0 !== ($flags & GETDATA_PRINTABLE); // total time online, average time online, total number of logins $data = Queries::getOverallStatistics(self::$from, self::$to, self::$lowerTimeBound, self::$upperTimeBound); @@ -70,7 +71,8 @@ class GetData } // per location - public static function perLocation($flags = 0) { + public static function perLocation(int $flags = 0): array + { $anonymize = 0 !== ($flags & GETDATA_ANONYMOUS); $printable = 0 !== ($flags & GETDATA_PRINTABLE); $data = Queries::getLocationStatistics(self::$from, self::$to, self::$lowerTimeBound, self::$upperTimeBound); @@ -85,7 +87,8 @@ class GetData } // per client - public static function perClient($flags = 0, $new = false) { + public static function perClient(int $flags = 0): array + { $anonymize = 0 !== ($flags & GETDATA_ANONYMOUS); $printable = 0 !== ($flags & GETDATA_PRINTABLE); $data = Queries::getClientStatistics(self::$from, self::$to, self::$lowerTimeBound, self::$upperTimeBound); @@ -101,7 +104,8 @@ class GetData } // per user - public static function perUser($flags = 0) { + public static function perUser(int $flags = 0): array + { $anonymize = 0 !== ($flags & GETDATA_ANONYMOUS); $res = Queries::getUserStatistics(self::$from, self::$to, self::$lowerTimeBound, self::$upperTimeBound); $data = array(); @@ -116,7 +120,8 @@ class GetData // per vm - public static function perVM($flags = 0) { + public static function perVM(int $flags = 0): array + { $anonymize = 0 !== ($flags & GETDATA_ANONYMOUS); $res = Queries::getVMStatistics(self::$from, self::$to, self::$lowerTimeBound, self::$upperTimeBound); $data = array(); @@ -130,7 +135,7 @@ class GetData return $data; } - private static function nullToZero(&$row) + private static function nullToZero(array &$row): void { foreach ($row as &$field) { if (is_null($field)) { @@ -140,7 +145,7 @@ class GetData } // Format $seconds into ".d .h .m .s" format (day, hour, minute, second) - private static function formatSeconds($seconds) + private static function formatSeconds(int $seconds): string { return sprintf('%dd, %02d:%02d:%02d', $seconds / (3600*24), ($seconds % (3600*24)) / 3600, ($seconds%3600) / 60, $seconds%60); } diff --git a/modules-available/statistics_reporting/inc/queries.inc.php b/modules-available/statistics_reporting/inc/queries.inc.php index 2465e557..bafe80bc 100644 --- a/modules-available/statistics_reporting/inc/queries.inc.php +++ b/modules-available/statistics_reporting/inc/queries.inc.php @@ -13,7 +13,7 @@ class Queries } } - public static function getClientStatistics(int $from, int $to, $lowerTimeBound = 0, $upperTimeBound = 24) + public static function getClientStatistics(int $from, int $to, int $lowerTimeBound = 0, int $upperTimeBound = 24): array { $fromCutoff = $from - 86400 * 30; $res = Database::simpleQuery("SELECT m.machineuuid, m.hostname, m.clientip, @@ -28,7 +28,7 @@ class Queries return $machines; } - public static function getLocationStatistics(int $from, int $to, $lowerTimeBound = 0, $upperTimeBound = 24) + public static function getLocationStatistics(int $from, int $to, int $lowerTimeBound = 0, int $upperTimeBound = 24): array { $fromCutoff = $from - 86400 * 30; $res = Database::simpleQuery("SELECT m.machineuuid, m.hostname, m.clientip, @@ -37,7 +37,7 @@ class Queries $machines = self::getStats3($res, $from, $to, $lowerTimeBound, $upperTimeBound); $locations = []; $keys = ['locationid', 'totalTime', 'totalOffTime', 'totalSessionTime', 'totalStandbyTime', 'totalIdleTime', 'totalIdleTime', 'longSessions', 'shortSessions', 'sessions']; - while ($machine = array_pop($machines)) { + while (($machine = array_pop($machines)) !== null) { if (!isset($locations[$machine['locationid']])) { self::keepKeys($machine, $keys); $locations[$machine['locationid']] = $machine; @@ -69,7 +69,7 @@ class Queries $machines = self::getStats3($res, $from, $to, $lowerTimeBound, $upperTimeBound); $total = false; $keys = ['totalTime', 'totalOffTime', 'totalSessionTime', 'totalStandbyTime', 'totalIdleTime', 'totalIdleTime', 'longSessions', 'shortSessions', 'sessions']; - while ($machine = array_pop($machines)) { + while (($machine = array_pop($machines)) !== null) { if ($total === false) { self::keepKeys($machine, $keys); $total = $machine; @@ -89,15 +89,7 @@ class Queries return $total; } - /** - * @param \PDOStatement $res - * @param int $from - * @param int $to - * @param int $lowerTimeBound - * @param int $upperTimeBound - * @return array - */ - private static function getStats3($res, $from, $to, $lowerTimeBound, $upperTimeBound) + private static function getStats3(PDOStatement $res, int $from, int $to, int $lowerTimeBound, int $upperTimeBound): array { //$debug = false; if ($lowerTimeBound === 0 && $upperTimeBound === 24 || $upperTimeBound <= $lowerTimeBound) { @@ -228,8 +220,8 @@ class Queries } */ $machine[$row['typeid']] += self::timeDiff($start, $end, $bounds); - $sh = date('G', $start); } + $sh = date('G', $start); if ($row['typeid'] === 'totalSessionTime' && ($bounds === false || ($sh >= $bounds[0] && $sh < $bounds[1]))) { if ($row['data'] >= 60) { $machine['longSessions'] += 1; @@ -307,17 +299,18 @@ class Queries /** * Get median of array. - * @param int[] list of values + * @param int[] $array list of values * @return int The median */ - private static function calcMedian($array) { + private static function calcMedian(array $array): int + { if (empty($array)) return 0; sort($array, SORT_NUMERIC); $count = count($array); //total numbers in array $middleval = (int)floor(($count-1) / 2); // find the middle value, or the lowest middle value if($count % 2 === 1) { // odd number, middle is the median - return (int)$array[$middleval]; + return $array[$middleval]; } // even number, calculate avg of 2 medians $low = $array[$middleval]; @@ -343,7 +336,7 @@ class Queries GROUP BY data"); } - public static function getDozmodStats(int $from, int $to) + public static function getDozmodStats(int $from, int $to): array { if (Module::get('dozmod') === false) return ['disabled' => true]; @@ -364,7 +357,7 @@ class Queries return $return; } - public static function getExamStats(int $from, int $to) + public static function getExamStats(int $from, int $to): array { if (Module::get('exams') === false) return ['disabled' => true]; @@ -395,7 +388,7 @@ class Queries return $return; } - public static function getAggregatedMachineStats($from) + public static function getAggregatedMachineStats(int $from): array { $return = array(); $return['location'] = Database::queryAll("SELECT MD5(CONCAT(locationid, :salt)) AS `location`, Count(*) AS `count` @@ -436,7 +429,7 @@ class Queries * @param int $to end timestamp * @return int count of user active in timespan */ - public static function getUniqueUserCount($from, $to) + public static function getUniqueUserCount(int $from, int $to): int { $res = Database::queryFirst("SELECT Count(DISTINCT username) as `total` FROM statistic diff --git a/modules-available/statistics_reporting/inc/remotereport.inc.php b/modules-available/statistics_reporting/inc/remotereport.inc.php index 7227259a..ebd31046 100644 --- a/modules-available/statistics_reporting/inc/remotereport.inc.php +++ b/modules-available/statistics_reporting/inc/remotereport.inc.php @@ -109,7 +109,7 @@ class RemoteReport $uptime = file_get_contents('/proc/uptime'); $memInfo = file_get_contents('/proc/meminfo'); $osInfo = parse_ini_file('/etc/os-release'); - preg_match_all('/\b(\w+):\s+(\d+)\s/s', $memInfo, $out, PREG_SET_ORDER); + preg_match_all('/\b(\w+):\s+(\d+)\s/', $memInfo, $out, PREG_SET_ORDER); $mem = array(); foreach ($out as $e) { $mem[$e[1]] = $e[2]; diff --git a/modules-available/statistics_reporting/page.inc.php b/modules-available/statistics_reporting/page.inc.php index 36081763..ec4bbf1a 100644 --- a/modules-available/statistics_reporting/page.inc.php +++ b/modules-available/statistics_reporting/page.inc.php @@ -125,14 +125,14 @@ class Page_Statistics_Reporting extends Page foreach ($this->COLUMNS as $column) { $data['columns'][] = array( 'id' => 'col_' . $column, - 'name' => Dictionary::translateFile('template-tags', 'lang_' . $column, true), + 'name' => Dictionary::translateFile('template-tags', 'lang_' . $column), 'checked' => ($forceOn || Request::get('col_' . $column, 'off', 'string') !== 'off') ? 'checked' : '', ); } foreach ($this->TABLES as $table) { $data['tables'][] = array( - 'name' => Dictionary::translate('table_' . $table, true), + 'name' => Dictionary::translate('table_' . $table), 'value' => $table, 'allowed' => User::hasPermission("table.view.$table"), 'selected' => ($this->type === $table) ? 'selected' : '', @@ -185,12 +185,10 @@ class Page_Statistics_Reporting extends Page } Header('Content-Type: application/json; charset=utf-8'); die(json_encode($data)); - } else { - die('No permission.'); } - } else { - echo 'Invalid action.'; + die('No permission.'); } + echo 'Invalid action.'; } private function doExport() @@ -257,7 +255,6 @@ class Page_Statistics_Reporting extends Page } fclose($fh); exit(); - break; case 'xml': $xml_data = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8" ?><data></data>'); $this->array_to_xml($res, $xml_data, 'row'); @@ -273,9 +270,9 @@ class Page_Statistics_Reporting extends Page /** * @param $data array Data to encode - * @param $xml_data \SimpleXMLElement XML Object to append to + * @param $xml_data SimpleXMLElement XML Object to append to */ - private function array_to_xml($data, $xml_data, $parentName = 'row') + private function array_to_xml(array $data, SimpleXMLElement $xml_data, string $parentName = 'row'): void { foreach ($data as $key => $value) { if (is_numeric($key)) { @@ -290,7 +287,7 @@ class Page_Statistics_Reporting extends Page } } - private function fetchData($flags) + private function fetchData(int $flags) { // TODO: Make all modes location-aware, filter while querying, not after switch ($this->type) { @@ -316,7 +313,7 @@ class Page_Statistics_Reporting extends Page // correct indexing of array after deletions return array_values($data); case 'client': - $data = GetData::perClient($flags, Request::any('new', false, 'string')); + $data = GetData::perClient($flags); // only show clients from locations which you have permission for $filterLocs = User::getAllowedLocations("table.view.client"); foreach ($data as $key => $row) { diff --git a/modules-available/sysconfig/addconfig.inc.php b/modules-available/sysconfig/addconfig.inc.php index 8df700f9..27af31e8 100644 --- a/modules-available/sysconfig/addconfig.inc.php +++ b/modules-available/sysconfig/addconfig.inc.php @@ -9,21 +9,17 @@ abstract class AddConfig_Base /** * Holds the instance for the currently executing step - * @var \AddConfig_Base + * @var AddConfig_Base */ - private static $instance = false; + private static $instance = null; /** * Config being edited (if any) - * @var \ConfigTgz + * @var ?ConfigTgz */ - protected $edit = false; + protected $edit = null; - /** - * - * @param string $step - */ - public static function setStep($step) + public static function setStep(string $step) { if (empty($step) || !class_exists($step) || get_parent_class($step) !== 'AddConfig_Base') { Message::addError('invalid-action', $step); @@ -32,18 +28,12 @@ abstract class AddConfig_Base self::$instance = new $step(); if (($editId = Request::any('edit', 0, 'int')) !== 0) { self::$instance->edit = ConfigTgz::get($editId); - if (self::$instance->edit === false) + if (self::$instance->edit === null) ErrorHandler::traceError('Invalid config id for editing'); Util::addRedirectParam('edit', self::$instance->edit->id()); } } - protected function tmError() - { - Message::addError('main.taskmanager-error'); - Util::redirect('?do=SysConfig'); - } - /** * Called before any HTML rendering happens, so you can * prepare stuff, validate input, and optionally redirect @@ -73,7 +63,7 @@ abstract class AddConfig_Base public static function preprocess() { - if (self::$instance === false) { + if (self::$instance === null) { ErrorHandler::traceError('No step instance yet'); } self::$instance->preprocessInternal(); @@ -81,16 +71,16 @@ abstract class AddConfig_Base public static function render() { - if (self::$instance === false) + if (self::$instance === null) ErrorHandler::traceError('No step instance yet'); - if (self::$instance->edit !== false) + if (self::$instance->edit !== null) Message::addInfo('replacing-config', self::$instance->edit->title()); self::$instance->renderInternal(); } public static function ajax() { - if (self::$instance === false) { + if (self::$instance === null) { ErrorHandler::traceError('No step instance yet'); } self::$instance->ajaxInternal(); @@ -110,7 +100,7 @@ class AddConfig_Start extends AddConfig_Base $mods = ConfigModule::getList(); $res = Database::simpleQuery("SELECT moduleid, title, moduletype, filepath FROM configtgz_module" . " ORDER BY title ASC"); // Move to ConfigModule - if ($this->edit === false) { + if ($this->edit === null) { $active = array(); } else { $active = $this->edit->getModuleIds(); @@ -140,7 +130,7 @@ class AddConfig_Start extends AddConfig_Base $row['active'] = in_array($row['moduleid'], $active); $group['modules'][] = $row; } - if ($this->edit !== false) { + if ($this->edit !== null) { $title = $this->edit->title(); } else { $title = Request::any('title', '', 'string'); @@ -162,7 +152,7 @@ class AddConfig_Start extends AddConfig_Base 'step' => 'AddConfig_Finish', 'groups' => array_values($modGroups), 'title' => $title, - 'edit' => ($this->edit !== false ? $this->edit->id() : false) + 'edit' => $this->edit === null ? null : $this->edit->id(), )); } @@ -174,9 +164,9 @@ class AddConfig_Start extends AddConfig_Base class AddConfig_Finish extends AddConfig_Base { /** - * @var ConfigTgz + * @var ?ConfigTgz */ - private $config = false; + private $config = null; protected function preprocessInternal() { @@ -186,13 +176,13 @@ class AddConfig_Finish extends AddConfig_Base Message::addError('missing-file'); Util::redirect('?do=SysConfig&action=addconfig'); } - if ($this->edit === false) { + if ($this->edit === null) { $this->config = ConfigTgz::insert($title, $modules); } else { $this->edit->update($title, $modules); $this->config = $this->edit; } - if ($this->config === false || $this->config->generate(true, 150) === false) { + if ($this->config->generate(true, 150) === false) { Message::addError('unsuccessful-action'); Util::redirect('?do=SysConfig&action=addconfig'); } diff --git a/modules-available/sysconfig/addmodule.inc.php b/modules-available/sysconfig/addmodule.inc.php index c887f432..4564537e 100644 --- a/modules-available/sysconfig/addmodule.inc.php +++ b/modules-available/sysconfig/addmodule.inc.php @@ -9,31 +9,36 @@ abstract class AddModule_Base /** * Holds the instance for the currently executing step - * @var \AddModule_Base + * + * @var AddModule_Base */ private static $instance = false; /** * Instance of ConfigModule we're editing. False if not editing but creating. - * @var \ConfigModule + * + * @var ?ConfigModule */ - protected $edit = false; + protected $edit = null; /** * * @param string $step name of class representing the current step * @param int $editId (optional) overwrite for the request parameter 'edit' */ - public static function setStep($step, $editId = false) + public static function setStep(string $step, int $editId = null): void { if (empty($step) || !class_exists($step) || get_parent_class($step) !== 'AddModule_Base') { Message::addError('invalid-action', $step); Util::redirect('?do=SysConfig'); } self::$instance = new $step(); - if ($editId = $editId ?: Request::any('edit')) { + if ($editId === null) { + $editId = Request::any('edit', 0, 'int'); + } + if ($editId !== 0) { self::$instance->edit = ConfigModule::get($editId); - if (self::$instance->edit === false) + if (self::$instance->edit === null) ErrorHandler::traceError('Invalid module id for editing'); if ($step !== 'AddModule_Assign' && !preg_match('/^' . self::$instance->edit->moduleType() . '_/', $step)) ErrorHandler::traceError('Module to edit is of different type!'); @@ -100,7 +105,7 @@ abstract class AddModule_Base if (self::$instance === false) { ErrorHandler::traceError('No step instance yet'); } - if (get_class(self::$instance) !== 'AddModule_Assign' && self::$instance->edit !== false) { + if (get_class(self::$instance) !== 'AddModule_Assign' && self::$instance->edit !== null) { Message::addInfo('replacing-module', self::$instance->edit->title()); } self::$instance->renderInternal(); @@ -155,7 +160,7 @@ class AddModule_Assign extends AddModule_Base if (ConfigModule::getList()[$moduleType]['unique']) { $moduleIds = []; - foreach (ConfigModule::getAll($moduleType) as $module) { + foreach (ConfigModule::getAll($moduleType) ?? [] as $module) { $moduleIds[] = $module->id(); } @@ -209,41 +214,26 @@ class AddModule_Assign extends AddModule_Base * Helper functions to set/get a batch of vars from/to post variables or a module */ -/** - * - * @param \ConfigModule $module - * @param array $array - * @param array $keys - */ -function moduleToArray($module, &$array, $keys) +function moduleToArray(ConfigModule $module, array &$array, array $keys): void { foreach ($keys as $key) { $array[$key] = $module->getData($key); } } -/** - * - * @param \ConfigModule $module - * @param array $array - * @param array $keys - */ -function arrayToModule($module, $array, $keys) +function arrayToModule(ConfigModule $module, array $array, array $keys): void { foreach ($keys as $key) { $module->setData($key, $array[$key]); } } -/** - * - * @param array $array - * @param array $keys - */ -function postToArray(&$array, $keys, $ignoreMissing = false) + +function postToArray(array &$array, array $keys, $ignoreMissing = false): void { foreach ($keys as $key) { $val = Request::post($key, '--not-in-post'); - if ($ignoreMissing && $val === '--not-in-post') continue; + if ($ignoreMissing && $val === '--not-in-post') + continue; $array[$key] = $val; } } diff --git a/modules-available/sysconfig/addmodule_adauth.inc.php b/modules-available/sysconfig/addmodule_adauth.inc.php index b7e1cca0..2a695ab0 100644 --- a/modules-available/sysconfig/addmodule_adauth.inc.php +++ b/modules-available/sysconfig/addmodule_adauth.inc.php @@ -15,7 +15,7 @@ class AdAuth_Start extends AddModule_Base { $ADAUTH_COMMON_FIELDS = array('title', 'server', 'searchbase', 'binddn', 'bindpw', 'home', 'homeattr', 'ssl', 'genuid', 'certificate', 'mapping', 'nohomewarn'); $data = array(); - if ($this->edit !== false) { + if ($this->edit !== null) { moduleToArray($this->edit, $data, $ADAUTH_COMMON_FIELDS); $data['title'] = $this->edit->title(); $data['edit'] = $this->edit->id(); @@ -35,7 +35,7 @@ class AdAuth_Start extends AddModule_Base } $data['step'] = 'AdAuth_CheckConnection'; $data['map_empty'] = true; - $data['mapping'] = ConfigModuleBaseLdap::getMapping(isset($data['mapping']) ? $data['mapping'] : false, $data['map_empty']); + $data['mapping'] = ConfigModuleBaseLdap::getMapping($data['mapping'] ?? null, $data['map_empty']); Render::addDialog(Dictionary::translateFile('config-module', 'adAuth_title'), false, 'ad-start', $data); } @@ -94,7 +94,7 @@ class AdAuth_CheckConnection extends AddModule_Base protected function renderInternal() { - $mapping = Request::post('mapping', false, 'array'); + $mapping = Request::post('mapping', null, 'array'); $data = array( 'edit' => Request::post('edit'), 'title' => Request::post('title'), @@ -194,7 +194,7 @@ class AdAuth_SelfSearch extends AddModule_Base protected function renderInternal() { - $mapping = Request::post('mapping', false, 'array'); + $mapping = Request::post('mapping', null, 'array'); $data = array( 'edit' => Request::post('edit'), 'title' => Request::post('title'), @@ -287,7 +287,7 @@ class AdAuth_HomeAttrCheck extends AddModule_Base 'certificate' => Request::post('certificate', ''), 'originalbinddn' => Request::post('originalbinddn'), 'tryHomeAttr' => true, - 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', false, 'array')), + 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', null, 'array')), 'prev' => 'AdAuth_Start', 'next' => 'AdAuth_CheckCredentials' )) @@ -358,7 +358,7 @@ class AdAuth_CheckCredentials extends AddModule_Base 'fingerprint' => Request::post('fingerprint'), 'certificate' => Request::post('certificate', ''), 'originalbinddn' => Request::post('originalbinddn'), - 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', false, 'array')), + 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', null, 'array')), 'prev' => 'AdAuth_Start', 'next' => 'AdAuth_HomeDir' )) @@ -422,11 +422,11 @@ class AdAuth_HomeDir extends AddModule_Base 'fingerprint' => Request::post('fingerprint'), 'certificate' => Request::post('certificate', ''), 'originalbinddn' => Request::post('originalbinddn'), - 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', false, 'array')), + 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', null, 'array')), 'prev' => 'AdAuth_Start', 'next' => 'AdAuth_Finish' ); - if ($this->edit !== false) { + if ($this->edit !== null) { foreach (self::getAttributes() as $key) { if ($this->edit->getData($key)) { $data[$key . '_c'] = 'checked="checked"'; @@ -453,7 +453,7 @@ class AdAuth_HomeDir extends AddModule_Base Render::addDialog(Dictionary::translateFile('config-module', 'adAuth_title'), false, 'ad_ldap-homedir', $data); } - public static function getAttributes() + public static function getAttributes(): array { return array('shareRemapMode', 'shareRemapCreate', 'shareDocuments', 'shareDownloads', 'shareDesktop', 'shareMedia', 'shareOther', 'shareHomeDrive', 'shareDomain', 'credentialPassthrough'); @@ -471,10 +471,11 @@ class AdAuth_Finish extends AddModule_Base $title = Request::post('title'); if (empty($title)) $title = 'AD: ' . Request::post('server'); - if ($this->edit === false) + if ($this->edit === null) { $module = ConfigModule::getInstance('AdAuth'); - else + } else { $module = $this->edit; + } $ssl = Request::post('ssl', 'off') === 'on'; foreach (['searchbase', 'binddn', 'server', 'bindpw', 'home', 'nohomewarn', 'homeattr', 'certificate', 'genuid', 'ldapAttrMountOpts', 'shareHomeMountOpts'] as $key) { @@ -498,7 +499,7 @@ class AdAuth_Finish extends AddModule_Base } else { $module->setData('fingerprint', ''); } - if ($this->edit !== false) + if ($this->edit !== null) $ret = $module->update($title); else $ret = $module->insert($title); @@ -506,7 +507,7 @@ class AdAuth_Finish extends AddModule_Base Message::addError('main.value-invalid', 'any', 'any'); $tgz = false; } else { - $tgz = $module->generate($this->edit === false); + $tgz = $module->generate($this->edit === null); } if ($tgz === false) { AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render() @@ -516,7 +517,7 @@ class AdAuth_Finish extends AddModule_Base 'tm-config' => $tgz, ); - if ($this->edit === false) { + if ($this->edit === null) { AddModule_Base::setStep('AddModule_Assign', $module->id()); } diff --git a/modules-available/sysconfig/addmodule_branding.inc.php b/modules-available/sysconfig/addmodule_branding.inc.php index f3a90e58..5d94a489 100644 --- a/modules-available/sysconfig/addmodule_branding.inc.php +++ b/modules-available/sysconfig/addmodule_branding.inc.php @@ -11,7 +11,7 @@ class Branding_Start extends AddModule_Base { Render::addDialog(Dictionary::translateFile('config-module', 'branding_title'), false, 'branding-start', array( 'step' => 'Branding_ProcessFile', - 'edit' => $this->edit ? $this->edit->id() : false + 'edit' => $this->edit == null ? null : $this->edit->id(), )); } @@ -47,7 +47,7 @@ class Branding_ProcessFile extends AddModule_Base if (strpos($url, '://') === false) $url = "http://$url"; $title = false; - if (!$this->downloadSvg($this->svgFile, $url, $title)) + if (!Branding_ProcessFile::downloadSvg($this->svgFile, $url, $title)) Util::redirect('?do=SysConfig&action=addmodule&step=Branding_Start'); Session::set('logo_name', $title); } @@ -73,13 +73,13 @@ class Branding_ProcessFile extends AddModule_Base $png = base64_encode(file_get_contents($this->task['data']['pngFile'])); if (filesize($this->svgFile) < 1000000) $svg = base64_encode(file_get_contents($this->svgFile)); - Render::addDialog(Dictionary::translate('config-module', 'branding_title'), false, 'branding-check', array( + Render::addDialog(Dictionary::translateFile('config-module', 'branding_title'), false, 'branding-check', array( 'png' => $png, 'svg' => $svg, 'error' => $this->task['data']['error'], 'step' => 'Branding_Finish', - 'edit' => $this->edit ? $this->edit->id() : false, - 'title' => $this->edit ? $this->edit->title() : false + 'edit' => $this->edit === null ? null : $this->edit->id(), + 'title' => $this->edit === null ? null : $this->edit->title(), ) ); @unlink($this->svgFile); @@ -94,7 +94,7 @@ class Branding_ProcessFile extends AddModule_Base * @return boolean true of download succeeded, false on download error (also returns true if downloaded file doesn't * seem to be svg!) */ - private function downloadSvg($svgName, $url, &$title) + private static function downloadSvg(string $svgName, string $url, &$title): bool { $title = false; // [wikipedia] Did someone paste a link to a thumbnail of the svg? Let's fix that... @@ -121,7 +121,7 @@ class Branding_ProcessFile extends AddModule_Base foreach ($out[1] as $res) { if (strpos($res, 'action=edit') !== false) continue; - $new = $this->internetCombineUrl($url, html_entity_decode($res, ENT_COMPAT, 'UTF-8')); + $new = Branding_ProcessFile::internetCombineUrl($url, html_entity_decode($res, ENT_COMPAT, 'UTF-8')); if ($new !== $url) break; } @@ -143,7 +143,7 @@ class Branding_ProcessFile extends AddModule_Base * @param string $relative relative url that will be converted to an absolute url * @return string combined absolute url */ - private function internetCombineUrl($absolute, $relative) + private static function internetCombineUrl(string $absolute, string $relative): string { $p = parse_url($relative); if (!empty($p["scheme"])) @@ -206,29 +206,26 @@ class Branding_Finish extends AddModule_Base Message::addError('main.error-read', $tgz); Util::redirect('?do=SysConfig&action=addmodule&step=Branding_Start'); } - if ($this->edit === false) + if ($this->edit === null) { $module = ConfigModule::getInstance('Branding'); - else + } else { $module = $this->edit; - if ($module === false) { - Message::addError('main.error-read', 'branding.inc.php'); - Util::redirect('?do=SysConfig&action=addmodule&step=Branding_Start'); } $module->setData('tmpFile', $tgz); - if ($this->edit !== false) + if ($this->edit !== null) $ret = $module->update($title); else $ret = $module->insert($title); if (!$ret) Util::redirect('?do=SysConfig&action=addmodule&step=Branding_Start'); - elseif ($module->generate($this->edit === false, NULL, 200) === false) + elseif ($module->generate($this->edit === null, NULL, 200) === false) Util::redirect('?do=SysConfig&action=addmodule&step=Branding_Start'); Session::set('logo_tgz', false); Session::set('logo_name', false); // Yay - if ($this->edit !== false) + if ($this->edit !== null) { Message::addSuccess('module-edited'); - else { + } else { Message::addSuccess('module-added'); AddModule_Base::setStep('AddModule_Assign', $module->id()); return; diff --git a/modules-available/sysconfig/addmodule_custommodule.inc.php b/modules-available/sysconfig/addmodule_custommodule.inc.php index 234aed0d..3afdad0a 100644 --- a/modules-available/sysconfig/addmodule_custommodule.inc.php +++ b/modules-available/sysconfig/addmodule_custommodule.inc.php @@ -14,7 +14,7 @@ class CustomModule_Start extends AddModule_Base Session::set('mod_temp', false); Render::addDialog(Dictionary::translateFile('config-module', 'custom_title'), false, 'custom-upload', array( 'step' => 'CustomModule_ProcessUpload', - 'edit' => $this->edit ? $this->edit->id() : false + 'edit' => $this->edit === null ? null : $this->edit->id(), )); } @@ -69,17 +69,17 @@ class CustomModule_ProcessUpload extends AddModule_Base } $list = SysConfig::archiveContentsFromTask($status, $userGroupWarn); - if ($this->edit !== false) { + if ($this->edit !== null) { $title = $this->edit->title(); } else if (isset($_FILES['modulefile']['name'])) { $title = basename($_FILES['modulefile']['name']); } else { $title = ''; } - Render::addDialog(Dictionary::translate('config-module', 'custom_title'), false, 'custom-fileselect', array( + Render::addDialog(Dictionary::translateFile('config-module', 'custom_title'), false, 'custom-fileselect', array( 'step' => 'CustomModule_CompressModule', 'files' => $list, - 'edit' => $this->edit ? $this->edit->id() : false, + 'edit' => $this->edit === null ? null : $this->edit->id(), 'title' => $title, 'userGroupWarn' => $userGroupWarn, )); @@ -116,28 +116,26 @@ class CustomModule_CompressModule extends AddModule_Base $this->taskError($status); } // Seems ok, create entry - if ($this->edit === false) + if ($this->edit === null) { $module = ConfigModule::getInstance('CustomModule'); - else + } else { $module = $this->edit; - if ($module === false) { - Message::addError('main.error-read', 'custommodule.inc.php'); - Util::redirect('?do=SysConfig&action=addmodule&step=CustomModule_Start'); } $module->setData('tmpFile', $destFile); - if ($this->edit !== false) + if ($this->edit !== null) { $ret = $module->update($title); - else + } else { $ret = $module->insert($title); + } if (!$ret) Util::redirect('?do=SysConfig&action=addmodule&step=CustomModule_Start'); - elseif (!$module->generate($this->edit === false, NULL, 200)) + elseif (!$module->generate($this->edit === null, NULL, 200)) Util::redirect('?do=SysConfig&action=addmodule&step=CustomModule_Start'); Session::set('mod_temp', false); // Yay - if ($this->edit !== false) + if ($this->edit !== null) { Message::addSuccess('module-edited'); - else { + } else { Message::addSuccess('module-added'); AddModule_Base::setStep('AddModule_Assign', $module->id()); return; diff --git a/modules-available/sysconfig/addmodule_ldapauth.inc.php b/modules-available/sysconfig/addmodule_ldapauth.inc.php index fe5ff706..6a385d9c 100644 --- a/modules-available/sysconfig/addmodule_ldapauth.inc.php +++ b/modules-available/sysconfig/addmodule_ldapauth.inc.php @@ -11,7 +11,7 @@ class LdapAuth_Start extends AddModule_Base { $LDAPAUTH_COMMON_FIELDS = array('title', 'server', 'searchbase', 'binddn', 'bindpw', 'home', 'homeattr', 'ssl', 'genuid', 'certificate', 'mapping', 'nohomewarn'); $data = array(); - if ($this->edit !== false) { + if ($this->edit !== null) { moduleToArray($this->edit, $data, $LDAPAUTH_COMMON_FIELDS); $data['title'] = $this->edit->title(); $data['edit'] = $this->edit->id(); @@ -27,7 +27,7 @@ class LdapAuth_Start extends AddModule_Base } $data['step'] = 'LdapAuth_CheckConnection'; $data['map_empty'] = true; - $data['mapping'] = ConfigModuleBaseLdap::getMapping(isset($data['mapping']) ? $data['mapping'] : false, $data['map_empty']); + $data['mapping'] = ConfigModuleBaseLdap::getMapping($data['mapping'] ?? null, $data['map_empty']); Render::addDialog(Dictionary::translateFile('config-module', 'ldapAuth_title'), false, 'ldap-start', $data); } @@ -81,7 +81,7 @@ class LdapAuth_CheckConnection extends AddModule_Base 'genuid' => Request::post('genuid'), 'certificate' => Request::post('certificate', ''), 'taskid' => $this->scanTask['id'], - 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', false, 'array')), + 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', null, 'array')), ); $data['prev'] = 'LdapAuth_Start'; $data['next'] = 'LdapAuth_CheckCredentials'; @@ -152,7 +152,7 @@ class LdapAuth_CheckCredentials extends AddModule_Base 'genuid' => Request::post('genuid'), 'fingerprint' => Request::post('fingerprint'), 'certificate' => Request::post('certificate', ''), - 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', false, 'array')), + 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', null, 'array')), 'prev' => 'LdapAuth_Start', 'next' => 'LdapAuth_HomeDir', )) @@ -193,11 +193,11 @@ class LdapAuth_HomeDir extends AddModule_Base 'fingerprint' => Request::post('fingerprint'), 'certificate' => Request::post('certificate', ''), 'originalbinddn' => Request::post('originalbinddn'), - 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', false, 'array')), + 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', null, 'array')), 'prev' => 'LdapAuth_Start', 'next' => 'LdapAuth_Finish', ); - if ($this->edit !== false) { + if ($this->edit !== null) { foreach (self::getAttributes() as $key) { if ($this->edit->getData($key)) { $data[$key . '_c'] = 'checked="checked"'; @@ -224,7 +224,7 @@ class LdapAuth_HomeDir extends AddModule_Base Render::addDialog(Dictionary::translateFile('config-module', 'ldapAuth_title'), false, 'ad_ldap-homedir', $data); } - public static function getAttributes() + public static function getAttributes(): array { return array('shareRemapMode', 'shareRemapCreate', 'shareDocuments', 'shareDownloads', 'shareDesktop', 'shareMedia', 'shareOther', 'shareHomeDrive', 'shareDomain', 'credentialPassthrough'); @@ -242,10 +242,11 @@ class LdapAuth_Finish extends AddModule_Base $title = Request::post('title'); if (empty($title)) $title = 'LDAP: ' . Request::post('server'); - if ($this->edit === false) + if ($this->edit === null) { $module = ConfigModule::getInstance('LdapAuth'); - else + } else { $module = $this->edit; + } $ssl = Request::post('ssl', 'off') === 'on'; foreach (['searchbase', 'binddn', 'server', 'bindpw', 'home', 'nohomewarn', 'certificate', 'genuid', 'ldapAttrMountOpts', 'shareHomeMountOpts'] as $key) { @@ -269,15 +270,16 @@ class LdapAuth_Finish extends AddModule_Base } else { $module->setData('fingerprint', ''); } - if ($this->edit !== false) + if ($this->edit !== null) { $ret = $module->update($title); - else + } else { $ret = $module->insert($title); + } if (!$ret) { Message::addError('main.value-invalid', 'any', 'any'); $tgz = false; } else { - $tgz = $module->generate($this->edit === false); + $tgz = $module->generate($this->edit === null); } if ($tgz === false) { AddModule_Base::setStep('LdapAuth_Start'); // Continues with LdapAuth_Start for render() @@ -287,7 +289,7 @@ class LdapAuth_Finish extends AddModule_Base 'tm-config' => $tgz, ); - if ($this->edit === false) { + if ($this->edit === null) { AddModule_Base::setStep('AddModule_Assign', $module->id()); } } diff --git a/modules-available/sysconfig/addmodule_screensaver.inc.php b/modules-available/sysconfig/addmodule_screensaver.inc.php index 24dfadd0..7b6d0afb 100644 --- a/modules-available/sysconfig/addmodule_screensaver.inc.php +++ b/modules-available/sysconfig/addmodule_screensaver.inc.php @@ -14,7 +14,7 @@ class Screensaver_Start extends AddModule_Base if (Request::get('back', 'false', 'string') !== 'false') /* If coming via the back button, load the session data */ $this->session_data = Session::get('data'); - elseif ($this->edit !== false) { + elseif ($this->edit !== null) { $this->session_data = array( 'title' => $this->edit->title(), 'qss' => $this->edit->getData('qss'), @@ -24,22 +24,22 @@ class Screensaver_Start extends AddModule_Base } else { $this->session_data = array( 'title' => '', - 'qss' => Dictionary::translate('saver_QssDefault', true), + 'qss' => Dictionary::translate('saver_QssDefault'), 'messages' => array( 'General' => array( - 'shutdown' => Dictionary::translate('saver_MessageDefaultShutdown', true), - 'shutdown-locked' => Dictionary::translate('saver_MessageDefaultShutdownLocked', true), - 'idle-kill' => Dictionary::translate('saver_MessageDefaultIdleKill', true), - 'idle-kill-locked' => Dictionary::translate('saver_MessageDefaultIdleKillLocked', true), - 'no-timeout' => Dictionary::translate('saver_MessageDefaultNoTimeout', true), - 'no-timeout-locked' => Dictionary::translate('saver_MessageDefaultNoTimeoutLocked', true), + 'shutdown' => Dictionary::translate('saver_MessageDefaultShutdown'), + 'shutdown-locked' => Dictionary::translate('saver_MessageDefaultShutdownLocked'), + 'idle-kill' => Dictionary::translate('saver_MessageDefaultIdleKill'), + 'idle-kill-locked' => Dictionary::translate('saver_MessageDefaultIdleKillLocked'), + 'no-timeout' => Dictionary::translate('saver_MessageDefaultNoTimeout'), + 'no-timeout-locked' => Dictionary::translate('saver_MessageDefaultNoTimeoutLocked'), ) ), 'texts' => array( - 'text-shutdown' => Dictionary::translate('saver_TextDefaultShutdown', true), + 'text-shutdown' => Dictionary::translate('saver_TextDefaultShutdown'), 'text-shutdown-locked' => '', - 'text-idle-kill' => Dictionary::translate('saver_TextDefaultIdleKill', true), - 'text-idle-kill-locked' => Dictionary::translate('saver_TextDefaultIdleKillLocked', true), + 'text-idle-kill' => Dictionary::translate('saver_TextDefaultIdleKill'), + 'text-idle-kill-locked' => Dictionary::translate('saver_TextDefaultIdleKillLocked'), 'text-no-timeout' => '', 'text-no-timeout-locked' => '', ), @@ -56,7 +56,7 @@ class Screensaver_Start extends AddModule_Base Render::addDialog(Dictionary::translateFile('config-module', 'screensaver_title'), false, 'screensaver-start', array( 'step' => 'Screensaver_Text', 'next' => 'idle-kill', - 'edit' => $this->edit ? $this->edit->id() : 0, + 'edit' => $this->edit !== null ? $this->edit->id() : 0, 'id' => 'start', 'title' => $this->session_data['title'], 'qss' => $this->session_data['qss'], @@ -98,7 +98,7 @@ class Screensaver_Text extends AddModule_Base $next = $this->session_data['next']; $data = array( - 'edit' => $this->edit ? $this->edit->id() : 0, + 'edit' => $this->edit !== null ? $this->edit->id() : 0, ); /* Prepare and translate labels for the frontend */ @@ -114,8 +114,8 @@ class Screensaver_Text extends AddModule_Base * Dictionary::translate('saver_TitleShutdown'); * Dictionary::translate('saver_DescriptionShutdown'); */ - $data['title'] = Dictionary::translate('saver_Title' . $tag, true); - $data['description'] = Dictionary::translate('saver_Description' . $tag, true); + $data['title'] = Dictionary::translate('saver_Title' . $tag); + $data['description'] = Dictionary::translate('saver_Description' . $tag); $data['msg_value'] = $this->session_data['messages']['General'][$next]; $data['msg_locked_value'] = $this->session_data['messages']['General'][$next . '-locked']; $data['text_value'] = $this->session_data['texts']['text-' . $next]; @@ -150,14 +150,14 @@ class Screensaver_Finish extends AddModule_Base if (empty($session_data['title'])) { Message::addError('missing-title'); Util::redirect('?do=SysConfig'); - return; } /* Only create an instance, if it's a new one */ - if ($this->edit !== false) + if ($this->edit !== null) { $module = $this->edit; - else + } else { $module = ConfigModule::getInstance('Screensaver'); + } /* Set all the data to the module instance */ $module->setData('qss', $session_data['qss']); @@ -165,15 +165,16 @@ class Screensaver_Finish extends AddModule_Base $module->setData('texts', $session_data['texts']); /* Insert or update database entries */ - if ($this->edit !== false) + if ($this->edit !== null) { $module->update($session_data['title']); - else + } else { $module->insert($session_data['title']); + } - $task = $module->generate($this->edit === false); + $task = $module->generate($this->edit === null); // Yay - if ($task !== false && $this->edit !== false) + if ($task !== false && $this->edit !== null) Message::addSuccess('module-edited'); elseif ($task !== false) { Message::addSuccess('module-added'); @@ -192,7 +193,6 @@ class Screensaver_Helper if (empty($session_data['title'])) { Message::addError('missing-title'); Util::redirect('?do=SysConfig'); - return; } $session_data['qss'] = Request::post('qss', $session_data['qss'], 'string'); $helperMode = Request::post('helper_mode', 'false', 'string'); diff --git a/modules-available/sysconfig/addmodule_sshconfig.inc.php b/modules-available/sysconfig/addmodule_sshconfig.inc.php index 4a75d77e..2447f9be 100644 --- a/modules-available/sysconfig/addmodule_sshconfig.inc.php +++ b/modules-available/sysconfig/addmodule_sshconfig.inc.php @@ -9,8 +9,8 @@ class SshConfig_Start extends AddModule_Base protected function renderInternal() { - if ($this->edit !== false) { - $data = $this->edit->getData(false) + array( + if ($this->edit !== null) { + $data = $this->edit->getData(null) + array( 'title' => $this->edit->title(), 'edit' => $this->edit->id(), 'PWD_' . strtoupper($this->edit->getData('allowPasswordLogin')) . '_selected' => 'selected', @@ -40,10 +40,11 @@ class SshConfig_Finish extends AddModule_Base return; } // Seems ok, create entry - if ($this->edit === false) + if ($this->edit === null) { $module = ConfigModule::getInstance('SshConfig'); - else + } else { $module = $this->edit; + } if ($module === false) { Message::addError('main.error-read', 'sshconfig.inc.php'); Util::redirect('?do=SysConfig&action=addmodule&step=SshConfig_Start'); @@ -59,18 +60,20 @@ class SshConfig_Finish extends AddModule_Base Util::redirect('?do=SysConfig&action=addmodule&step=SshConfig_Start'); } $module->setData('publicKey', false); - if ($this->edit !== false) + if ($this->edit !== null) { $ret = $module->update($title); - else + } else { $ret = $module->insert($title); - if (!$ret) + } + if (!$ret) { Util::redirect('?do=SysConfig&action=addmodule&step=SshConfig_Start'); - elseif (!$module->generate($this->edit === false, NULL, 200)) + } elseif (!$module->generate($this->edit === null, NULL, 200)) { Util::redirect('?do=SysConfig&action=addmodule&step=SshConfig_Start'); + } // Yay - if ($this->edit !== false) + if ($this->edit !== null) { Message::addSuccess('module-edited'); - else { + } else { Message::addSuccess('module-added'); AddModule_Base::setStep('AddModule_Assign', $module->id()); return; diff --git a/modules-available/sysconfig/addmodule_sshkey.inc.php b/modules-available/sysconfig/addmodule_sshkey.inc.php index b5ab4ad6..9f5bd1d3 100644 --- a/modules-available/sysconfig/addmodule_sshkey.inc.php +++ b/modules-available/sysconfig/addmodule_sshkey.inc.php @@ -9,8 +9,8 @@ class SshKey_Start extends AddModule_Base protected function renderInternal() { - if ($this->edit !== false) { - $data = $this->edit->getData(false) + array( + if ($this->edit !== null) { + $data = $this->edit->getData(null) + array( 'title' => $this->edit->title(), 'edit' => $this->edit->id(), ); @@ -35,7 +35,7 @@ class SshKey_Finish extends AddModule_Base return; } // Seems ok, create entry - if ($this->edit === false) { + if ($this->edit === null) { $module = ConfigModule::getInstance('SshKey'); } else { $module = $this->edit; @@ -48,18 +48,18 @@ class SshKey_Finish extends AddModule_Base Message::addError('main.value-invalid', 'pubkey', Request::post('publicKey')); Util::redirect('?do=SysConfig&action=addmodule&step=SshKey_Start'); } - if ($this->edit !== false) { + if ($this->edit !== null) { $ret = $module->update($title); } else { $ret = $module->insert($title); } if (!$ret) { Util::redirect('?do=SysConfig&action=addmodule&step=SshKey_Start'); - } elseif (!$module->generate($this->edit === false, NULL, 200)) { + } elseif (!$module->generate($this->edit === null, NULL, 200)) { Util::redirect('?do=SysConfig&action=addmodule&step=SshKey_Start'); } // Yay - if ($this->edit !== false) { + if ($this->edit !== null) { Message::addSuccess('module-edited'); } else { Message::addSuccess('module-added'); diff --git a/modules-available/sysconfig/api.inc.php b/modules-available/sysconfig/api.inc.php index c81d37b5..e7be3029 100644 --- a/modules-available/sysconfig/api.inc.php +++ b/modules-available/sysconfig/api.inc.php @@ -11,9 +11,9 @@ 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; } // What we do if we can't supply the requested config diff --git a/modules-available/sysconfig/inc/configmodule.inc.php b/modules-available/sysconfig/inc/configmodule.inc.php index e414a6cf..729cb959 100644 --- a/modules-available/sysconfig/inc/configmodule.inc.php +++ b/modules-available/sysconfig/inc/configmodule.inc.php @@ -7,18 +7,23 @@ abstract class ConfigModule { /** - * @var array list of known module types + * @var ?array{'title': string, + * 'description': string, + * 'group': string, + * 'unique': bool, + * 'sortOrder': int, + * 'moduleClass': string, + * 'wizardClass': string}[] list of known module types */ - private static $moduleTypes = false; + private static $moduleTypes = null; private $moduleId = 0; - private $moduleArchive = false; - private $moduleTitle = false; - private $moduleStatus = false; - /** - * @var int - */ + private $moduleArchive = ''; + private $moduleTitle = ''; + private $moduleStatus = 'MISSING'; + /** @var int */ private $dateline = 0; + /** @var int */ private $currentVersion = 0; /** * @var false|array Data of module, false if not initialized @@ -33,9 +38,9 @@ abstract class ConfigModule */ public static function loadDb() { - if (self::$moduleTypes !== false) + if (self::$moduleTypes !== null) return; - self::$moduleTypes = array(); + self::$moduleTypes = []; Module::isAvailable('sysconfig'); foreach (glob(dirname(__FILE__) . '/configmodule/*.inc.php', GLOB_NOSORT) as $file) { require_once $file; @@ -44,10 +49,16 @@ abstract class ConfigModule /** * Get all known config module types. - * - * @return array list of modules + * @return array{'title': string, + * 'description': string, + * 'group': string, + * 'unique': bool, + * 'sortOrder': int, + * 'moduleClass': string, + * 'wizardClass': string}[] list of known module types + * / */ - public static function getList() + public static function getList(): array { self::loadDb(); return self::$moduleTypes; @@ -63,9 +74,9 @@ abstract class ConfigModule * @param string $description Description for this module type * @param string $group Title for group this module type belongs to * @param bool $unique Can only one such module be added to a config? - * @param int $sortOrder Lower comes first, alphabetical ordering otherwiese + * @param int $sortOrder Lower comes first, alphabetical ordering otherwise */ - public static function registerModule($id, $title, $description, $group, $unique, $sortOrder = 0) + public static function registerModule(string $id, string $title, string $description, string $group, bool $unique, int $sortOrder = 0): void { if (isset(self::$moduleTypes[$id])) { ErrorHandler::traceError("Config Module $id already registered!"); @@ -93,21 +104,33 @@ abstract class ConfigModule * Get fresh instance of ConfigModule subclass for given module type. * * @param string $moduleType name of module type - * @return false|\ConfigModule module instance + * @return ConfigModule module instance */ - public static function getInstance($moduleType) + public static function getInstance(string $moduleType): ConfigModule + { + $ret = self::getInstanceOrNull($moduleType); + if ($ret === null) { + Message::addError('main.error-read', $moduleType . '.inc.php'); + Util::redirect('?do=sysconfig'); + } + return $ret; + } + + public static function getInstanceOrNull(string $moduleType): ?ConfigModule { self::loadDb(); if (!isset(self::$moduleTypes[$moduleType])) { error_log('Unknown module type: ' . $moduleType); - return false; + return null; } return new self::$moduleTypes[$moduleType]['moduleClass']; } - public static function instanceFromDbRow($dbRow) + private static function instanceFromDbRow(array $dbRow): ?ConfigModule { - $instance = self::getInstance($dbRow['moduletype']); + $instance = self::getInstanceOrNull($dbRow['moduletype']); + if ($instance === null) + return null; $instance->currentVersion = $dbRow['version']; $instance->moduleArchive = $dbRow['filepath']; $instance->moduleData = json_decode($dbRow['contents'], true); @@ -125,37 +148,37 @@ abstract class ConfigModule * Get module instance from id. * * @param int $moduleId module id to get - * @return false|\ConfigModule The requested module from DB, or false on error + * @return ?ConfigModule The requested module from DB, or null on error */ - public static function get($moduleId) + public static function get(int $moduleId): ?ConfigModule { $ret = Database::queryFirst("SELECT moduleid, title, moduletype, filepath, contents, version, status, dateline FROM configtgz_module " . " WHERE moduleid = :moduleid LIMIT 1", array('moduleid' => $moduleId)); if ($ret === false) - return false; + return null; return self::instanceFromDbRow($ret); } /** * Get module instances from module type. * - * @param int $moduleType module type to get - * @return \ConfigModule[]|false The requested modules from DB, or false on error + * @param string $moduleType module type to get + * @return ?ConfigModule[] The requested modules from DB, or null on error */ - public static function getAll($moduleType = false) + public static function getAll(string $moduleType = null): ?array { - if ($moduleType === false) { + if ($moduleType === null) { $ret = Database::simpleQuery("SELECT moduleid, title, moduletype, filepath, contents, version, status, dateline FROM configtgz_module"); } else { $ret = Database::simpleQuery("SELECT moduleid, title, moduletype, filepath, contents, version, status, dateline FROM configtgz_module " . " WHERE moduletype = :moduletype", array('moduletype' => $moduleType)); } if ($ret === false) - return false; + return null; $list = array(); foreach ($ret as $row) { $instance = self::instanceFromDbRow($row); - if ($instance === false) + if ($instance === null) continue; $list[] = $instance; } @@ -167,37 +190,37 @@ abstract class ConfigModule * * @return int module version */ - protected abstract function moduleVersion(); + protected abstract function moduleVersion(): int; /** * Validate the module's configuration. * - * @return boolean ok or not + * @return bool ok or not */ - protected abstract function validateConfig(); + protected abstract function validateConfig(): bool; /** * Set module specific data. * * @param string $key key, name or id of data being set * @param mixed $value Module specific data - * @return boolean true if data was successfully set, false otherwise (i.e. invalid data being set) + * @return bool true if data was successfully set, false otherwise (i.e. invalid data being set) */ - public abstract function setData($key, $value); + public abstract function setData(string $key, $value): bool; /** * Get module specific data. * Can be overridden by modules. * - * @param string $key key, name or id of data to get, or false to get the raw moduleData array + * @param ?string $key key, name or id of data to get, or null to get the raw moduleData array * @return mixed Module specific data */ - public function getData($key) + public function getData(?string $key) { - if ($key === false) + if ($key === null) return $this->moduleData; if (!is_array($this->moduleData) || !isset($this->moduleData[$key])) - return false; + return null; return $this->moduleData[$key]; } @@ -205,25 +228,25 @@ abstract class ConfigModule * Module specific version of generate. * * @param string $tgz File name of tgz module to write final output to - * @param string $parent Parent task of this task + * @param string|null $parent Parent task of this task * @return array|boolean true if generation is completed immediately, * a task struct if some task needs to be run for generation, * false on error */ - protected abstract function generateInternal($tgz, $parent); + protected abstract function generateInternal(string $tgz, ?string $parent); - private function createFileName() + private function createFileName(): string { return CONFIG_TGZ_LIST_DIR . '/modules/' . $this->moduleType() . '_id-' . $this->moduleId . '__' . mt_rand() . '-' . time() . '.tgz'; } - public function allowDownload() + public function allowDownload(): bool { return false; } - public function needRebuild() + public function needRebuild(): bool { return $this->moduleStatus !== 'OK' || $this->currentVersion < $this->moduleVersion(); } @@ -233,17 +256,15 @@ abstract class ConfigModule * * @return int id */ - public final function id() + public final function id(): int { return $this->moduleId; } /** * Get module title. - * - * @return string */ - public final function title() + public final function title(): string { return $this->moduleTitle; } @@ -253,17 +274,17 @@ abstract class ConfigModule * * @return string tgz file absolute path */ - public final function archive() + public final function archive(): string { return $this->moduleArchive; } - public final function status() + public final function status(): string { return $this->moduleStatus; } - public final function currentVersion() + public final function currentVersion(): int { return $this->currentVersion; } @@ -273,11 +294,10 @@ abstract class ConfigModule * * @return string module type */ - public final function moduleType() + public final function moduleType(): string { + // Yes, need to pass $this, otherwise we get ConfigModule, the base class this function is part of $name = get_class($this); - if ($name === false) - ErrorHandler::traceError('ConfigModule::moduleType: get_class($this) returned false!'); // ConfigModule_* if (!preg_match('/^ConfigModule_(\w+)$/', $name, $out)) ErrorHandler::traceError('ConfigModule::moduleType: get_class($this) returned "' . $name . '"'); @@ -292,7 +312,7 @@ abstract class ConfigModule * @param string $title display name of the module * @return boolean true if inserted successfully, false if module config is invalid */ - public final function insert($title) + public final function insert(string $title): bool { if ($this->moduleId !== 0) ErrorHandler::traceError('ConfigModule::insert called when moduleId != 0'); @@ -326,7 +346,7 @@ abstract class ConfigModule * * @return boolean true on success, false otherwise */ - public final function update($title = '') + public final function update(string $title = ''): bool { if ($this->moduleId === 0) ErrorHandler::traceError('ConfigModule::update called when moduleId == 0'); @@ -353,15 +373,15 @@ abstract class ConfigModule * Updating the database etc. will happen later through a callback. * * @param boolean $deleteOnError if true, the db entry will be deleted if generation failed - * @param string $parent Parent task of this task + * @param string|null $parent Parent task of this task * @param int $timeoutMs maximum time in milliseconds we wait for completion * @return string|boolean task id if deferred generation was started, * true if generation succeeded (without using a task or within $timeoutMs) * false on error */ - public final function generate($deleteOnError, $parent = NULL, $timeoutMs = 0) + public final function generate(bool $deleteOnError, string $parent = NULL, int $timeoutMs = 0) { - if ($this->moduleId === 0 || $this->moduleTitle === false) + if ($this->moduleId === 0 || empty($this->moduleTitle)) ErrorHandler::traceError('ConfigModule::generateAsync called on uninitialized/uninserted module!'); $tmpTgz = '/tmp/bwlp-id-' . $this->moduleId . '_' . mt_rand() . '_' . time() . '.tgz'; $ret = $this->generateInternal($tmpTgz, $parent); @@ -395,7 +415,7 @@ abstract class ConfigModule /** * Delete the module. */ - public final function delete() + public final function delete(): void { if ($this->moduleId === 0) ErrorHandler::traceError('ConfigModule::delete called with invalid module id!'); @@ -410,17 +430,19 @@ abstract class ConfigModule $this->moduleTitle = false; $this->moduleArchive = false; } - return $ret; } - private function markUpdated($tmpTgz) + /** + * @param ?string $tmpTgz new tar archive to use for this module, or null if the old one is still valid + */ + private function markUpdated(?string $tmpTgz): bool { if ($this->moduleId === 0) ErrorHandler::traceError('ConfigModule::markUpdated called with invalid module id!'); - if ($this->moduleArchive === false) + if ($this->moduleArchive === null) $this->moduleArchive = $this->createFileName(); // Move file - if ($tmpTgz === false) { + if ($tmpTgz === null) { if (!file_exists($this->moduleArchive)) { EventLog::failure('ConfigModule::markUpdated for "' . $this->moduleTitle . '" called with no tmpTgz and no existing tgz!'); $this->markFailed(); @@ -460,16 +482,18 @@ abstract class ConfigModule return $retval; } - private function markFailed() + private function markFailed(): void { if ($this->moduleId === 0) ErrorHandler::traceError('ConfigModule::markFailed called with invalid module id!'); - if ($this->moduleArchive === false) + if ($this->moduleArchive === '') { $this->moduleArchive = $this->createFileName(); - if (!file_exists($this->moduleArchive)) + } + if (!file_exists($this->moduleArchive)) { $status = 'MISSING'; - else + } else { $status = 'OUTDATED'; + } Database::exec("UPDATE configtgz_module SET filepath = :filename, status = :status WHERE moduleid = :id LIMIT 1", array( 'id' => $this->moduleId, 'filename' => $this->moduleArchive, @@ -477,7 +501,7 @@ abstract class ConfigModule )); } - public function dateline_s() + public function dateline_s(): string { return Util::prettyTime($this->dateline); } @@ -489,7 +513,7 @@ abstract class ConfigModule * Override this if you need to handle this, otherwise * the base implementation does nothing. */ - public function event_serverIpChanged() + public function event_serverIpChanged(): void { // Do::Nothing() } @@ -500,11 +524,10 @@ abstract class ConfigModule * Will be called if the server's IP address changes. The event will be propagated * to all config module classes so action can be taken if appropriate. */ - public static function serverIpChanged() + public static function serverIpChanged(): void { self::loadDb(); - $list = self::getAll(); - foreach ($list as $mod) { + foreach (self::getAll() ?? [] as $mod) { $mod->event_serverIpChanged(); } } @@ -513,53 +536,51 @@ abstract class ConfigModule * Called when (re)generating a config module failed, so we can * update the status in the DB and add a server log entry. * - * @param array $task - * @param array $args contains 'moduleid' and optionally 'deleteOnError' and 'tmpTgz' + * @param array $args contains 'moduleid' and optionally 'deleteOnError' */ - public static function generateFailed($task, $args) + public static function generateFailed(array $task, array $args): void { if (!isset($args['moduleid']) || !is_numeric($args['moduleid'])) { EventLog::warning('Ignoring generateFailed event as it has no moduleid assigned.'); return; } $module = self::get($args['moduleid']); - if ($module === false) { + if ($module === null) { EventLog::warning('generateFailed callback for module id ' . $args['moduleid'] . ', but no instance could be generated.'); return; } - if (isset($task['data']['error'])) + if (isset($task['data']['error'])) { $error = $task['data']['error']; - elseif (isset($task['data']['messages'])) + } elseif (isset($task['data']['messages'])) { $error = $task['data']['messages']; - else + } else { $error = ''; + } EventLog::failure("Generating module '" . $module->moduleTitle . "' failed.", $error); - if ($args['deleteOnError']) + if ($args['deleteOnError'] ?? false) { $module->delete(); - else + } else { $module->markFailed(); + } } /** * (Re)generating a config module succeeded. Update db entry. * - * @param array $args contains 'moduleid' and optionally 'deleteOnError' and 'tmpTgz' + * @param array $args contains 'moduleid' and optionally 'tmpTgz' */ - public static function generateSucceeded($args) + public static function generateSucceeded(array $args): void { if (!isset($args['moduleid']) || !is_numeric($args['moduleid'])) { EventLog::warning('Ignoring generateSucceeded event as it has no moduleid assigned.'); return; } $module = self::get($args['moduleid']); - if ($module === false) { + if ($module === null) { EventLog::warning('generateSucceeded callback for module id ' . $args['moduleid'] . ', but no instance could be generated.'); return; } - if (isset($args['tmpTgz'])) - $module->markUpdated($args['tmpTgz']); - else - $module->markUpdated(false); + $module->markUpdated($args['tmpTgz'] ?? null); } } diff --git a/modules-available/sysconfig/inc/configmodule/branding.inc.php b/modules-available/sysconfig/inc/configmodule/branding.inc.php index 76968ff4..84f79b44 100644 --- a/modules-available/sysconfig/inc/configmodule/branding.inc.php +++ b/modules-available/sysconfig/inc/configmodule/branding.inc.php @@ -17,10 +17,10 @@ class ConfigModule_Branding extends ConfigModule private $tmpFile = false; - protected function generateInternal($tgz, $parent) + protected function generateInternal(string $tgz, ?string $parent) { if (!$this->validateConfig()) { - return $this->archive() !== false && file_exists($this->archive()); // No new temp file given, old archive still exists, pretend it worked... + return !empty($this->archive()) && file_exists($this->archive()); // No new temp file given, old archive still exists, pretend it worked... } return Taskmanager::submit('MoveFile', array( 'source' => $this->tmpFile, @@ -30,17 +30,17 @@ class ConfigModule_Branding extends ConfigModule )); } - protected function moduleVersion() + protected function moduleVersion(): int { return self::VERSION; } - protected function validateConfig() + protected function validateConfig(): bool { return $this->tmpFile !== false && file_exists($this->tmpFile); } - public function setData($key, $value) + public function setData(string $key, $value): bool { if ($key !== 'tmpFile' || !is_string($value) || !file_exists($value)) return false; @@ -48,12 +48,12 @@ class ConfigModule_Branding extends ConfigModule return true; } - public function getData($key) + public function getData(?string $key): bool { return false; } - public function allowDownload() + public function allowDownload(): bool { return true; } diff --git a/modules-available/sysconfig/inc/configmodule/customodule.inc.php b/modules-available/sysconfig/inc/configmodule/customodule.inc.php index 56aa9277..b5c10104 100644 --- a/modules-available/sysconfig/inc/configmodule/customodule.inc.php +++ b/modules-available/sysconfig/inc/configmodule/customodule.inc.php @@ -16,12 +16,12 @@ class ConfigModule_CustomModule extends ConfigModule private $tmpFile = false; - protected function generateInternal($tgz, $parent) + protected function generateInternal(string $tgz, ?string $parent) { if (!$this->validateConfig()) { // No temp file given from wizard // Old archive still exists? pretend it worked... - if ($this->archive() === false || !file_exists($this->archive())) + if ($this->archive() === '' || !file_exists($this->archive())) return false; if ($this->currentVersion() == 1) { // Need an upgrade @@ -42,17 +42,17 @@ class ConfigModule_CustomModule extends ConfigModule )); } - protected function moduleVersion() + protected function moduleVersion(): int { return self::VERSION; } - protected function validateConfig() + protected function validateConfig(): bool { return $this->tmpFile !== false && file_exists($this->tmpFile); } - public function setData($key, $value) + public function setData(string $key, $value): bool { // Sets the temp file from the wizard, where it stored the processed archive if ($key !== 'tmpFile' || !file_exists($value)) @@ -61,12 +61,12 @@ class ConfigModule_CustomModule extends ConfigModule return true; } - public function getData($key) + public function getData(?string $key): bool { return false; } - public function allowDownload() + public function allowDownload(): bool { return true; } diff --git a/modules-available/sysconfig/inc/configmodule/ldapauth.inc.php b/modules-available/sysconfig/inc/configmodule/ldapauth.inc.php index 7af4671e..64af4c0e 100644 --- a/modules-available/sysconfig/inc/configmodule/ldapauth.inc.php +++ b/modules-available/sysconfig/inc/configmodule/ldapauth.inc.php @@ -5,7 +5,7 @@ class ConfigModule_LdapAuth extends ConfigModuleBaseLdap const MODID = 'LdapAuth'; - protected function preTaskmanagerHook(&$config) + protected function preTaskmanagerHook(array &$config) { // Just set the flag so the taskmanager job knows we're dealing with a normal ldap server, // not AD scheme diff --git a/modules-available/sysconfig/inc/configmodule/screensaver.inc.php b/modules-available/sysconfig/inc/configmodule/screensaver.inc.php index 08a2c9a1..1797331c 100644 --- a/modules-available/sysconfig/inc/configmodule/screensaver.inc.php +++ b/modules-available/sysconfig/inc/configmodule/screensaver.inc.php @@ -14,7 +14,7 @@ class ConfigModule_Screensaver extends ConfigModule const MODID = 'Screensaver'; const VERSION = 1; - protected function generateInternal($tgz, $parent) + protected function generateInternal(string $tgz, ?string $parent) { /* Validate if all data are available */ if (!$this->validateConfig()) @@ -30,21 +30,20 @@ class ConfigModule_Screensaver extends ConfigModule ), false); } - protected function moduleVersion() + protected function moduleVersion(): int { return self::VERSION; } - protected function validateConfig() + protected function validateConfig(): bool { - return isset($this->moduleData['qss']) && - isset($this->moduleData['texts']) && - isset($this->moduleData['texts']['text-idle-kill']) && - isset($this->moduleData['texts']['text-no-timeout']) && - isset($this->moduleData['texts']['text-shutdown']); + return isset($this->moduleData['texts']['text-no-timeout']) + && isset($this->moduleData['texts']['text-idle-kill']) + && isset($this->moduleData['texts']['text-shutdown']) + && isset($this->moduleData['qss']); } - public function setData($key, $value) + public function setData(string $key, $value): bool { switch ($key) { case 'qss': @@ -58,17 +57,15 @@ class ConfigModule_Screensaver extends ConfigModule return true; } - public function allowDownload() + public function allowDownload(): bool { return false; } /** * Creates a map with filepath => file content - * - * @return array in the form of Map<String, byte[]> */ - private function getFileArray() + private function getFileArray(): array { $files = array( '/opt/openslx/xscreensaver/style.qss' => $this->moduleData['qss'], @@ -98,7 +95,7 @@ class ConfigModule_Screensaver extends ConfigModule return $files; } - private function wrapHtmlTags($text_name) + private function wrapHtmlTags(string $text_name): string { return '<html><body>' . $this->moduleData['texts'][$text_name] . '</body></html>'; } diff --git a/modules-available/sysconfig/inc/configmodule/sshconfig.inc.php b/modules-available/sysconfig/inc/configmodule/sshconfig.inc.php index b5ab20e4..a62d1035 100644 --- a/modules-available/sysconfig/inc/configmodule/sshconfig.inc.php +++ b/modules-available/sysconfig/inc/configmodule/sshconfig.inc.php @@ -14,7 +14,7 @@ class ConfigModule_SshConfig extends ConfigModule const MODID = 'SshConfig'; const VERSION = 1; - protected function generateInternal($tgz, $parent) + protected function generateInternal(string $tgz, ?string $parent) { if (!$this->validateConfig()) return false; @@ -26,12 +26,12 @@ class ConfigModule_SshConfig extends ConfigModule return Taskmanager::submit('SshdConfigGenerator', $config); } - protected function moduleVersion() + protected function moduleVersion(): int { return self::VERSION; } - protected function validateConfig() + protected function validateConfig(): bool { // UPGRADE if (isset($this->moduleData['allowPasswordLogin']) && !isset($this->moduleData['allowedUsersLogin'])) { @@ -45,7 +45,7 @@ class ConfigModule_SshConfig extends ConfigModule && isset($this->moduleData['listenPort']); } - public function setData($key, $value) + public function setData(string $key, $value): bool { switch ($key) { case 'publicKey': diff --git a/modules-available/sysconfig/inc/configmodule/sshkey.inc.php b/modules-available/sysconfig/inc/configmodule/sshkey.inc.php index 2d212d25..e4a55ad7 100644 --- a/modules-available/sysconfig/inc/configmodule/sshkey.inc.php +++ b/modules-available/sysconfig/inc/configmodule/sshkey.inc.php @@ -14,7 +14,7 @@ class ConfigModule_SshKey extends ConfigModule const MODID = 'SshKey'; const VERSION = 1; - protected function generateInternal($tgz, $parent) + protected function generateInternal(string $tgz, ?string $parent) { if (!$this->validateConfig()) return false; @@ -30,17 +30,17 @@ class ConfigModule_SshKey extends ConfigModule return Taskmanager::submit('MakeTarball', $config); } - protected function moduleVersion() + protected function moduleVersion(): int { return self::VERSION; } - protected function validateConfig() + protected function validateConfig(): bool { return isset($this->moduleData['publicKey']); } - public function setData($key, $value) + public function setData(string $key, $value): bool { switch ($key) { case 'publicKey': diff --git a/modules-available/sysconfig/inc/configmodulebaseldap.inc.php b/modules-available/sysconfig/inc/configmodulebaseldap.inc.php index e3d99025..770a40e6 100644 --- a/modules-available/sysconfig/inc/configmodulebaseldap.inc.php +++ b/modules-available/sysconfig/inc/configmodulebaseldap.inc.php @@ -11,7 +11,7 @@ abstract class ConfigModuleBaseLdap extends ConfigModule 'shareOther', 'shareHomeDrive', 'shareDomain', 'credentialPassthrough', 'mapping', 'genuid', 'ldapAttrMountOpts', 'shareHomeMountOpts', 'nohomewarn'); - public static function getMapping($config = false, &$empty = true) + public static function getMapping(array $config = null, ?bool &$empty = true): array { $list = array( ['name' => 'uid', 'field' => 'uid', 'ad' => 'sAMAccountName'], @@ -46,10 +46,10 @@ abstract class ConfigModuleBaseLdap extends ConfigModule * * @param string $command start, restart, check * @param bool|int|int[] $ids list of IDs to run command on, or false meaning "all" - * @param string $parent if not NULL, this will be the parent task of the launch-task + * @param string|null $parent if not NULL, this will be the parent task of the launch-task * @return boolean|string false on error, id of task otherwise */ - public static function ldadp($command = 'start', $ids = false, $parent = null) + public static function ldadp(string $command = 'start', $ids = false, string $parent = null) { if ($ids === false) { $ids = self::getActiveModuleIds(); @@ -67,7 +67,7 @@ abstract class ConfigModuleBaseLdap extends ConfigModule return $task['id']; } - protected function generateInternal($tgz, $parent) + protected function generateInternal(string $tgz, ?string $parent) { $config = $this->moduleData; if (isset($config['certificate']) && !is_string($config['certificate'])) { @@ -97,7 +97,7 @@ abstract class ConfigModuleBaseLdap extends ConfigModule } // This is now always on, as we mask it transparently in our lightdm greeter $config['fixnumeric'] = 'true'; - $config['genuid'] = isset($config['genuid']) && !empty($config['genuid']); + $config['genuid'] = !empty($config['genuid']); $config['nohomewarn'] = isset($config['nohomewarn']) ? (int)$config['nohomewarn'] : 0; $this->preTaskmanagerHook($config); $task = Taskmanager::submit('CreateLdapConfig', $config); @@ -111,25 +111,23 @@ abstract class ConfigModuleBaseLdap extends ConfigModule * Hook called before running CreateLdapConfig task with the * configuration to be passed to the task. Passed by reference * so it can be modified. - * - * @param array $config */ - protected function preTaskmanagerHook(&$config) + protected function preTaskmanagerHook(array &$config) { } - protected function moduleVersion() + protected function moduleVersion(): int { return self::VERSION; } - protected function validateConfig() + protected function validateConfig(): bool { // Check if required fields are filled return ArrayUtil::hasAllKeys($this->moduleData, self::$REQUIRED_FIELDS); } - public function setData($key, $value) + public function setData(string $key, $value): bool { if (!in_array($key, self::$REQUIRED_FIELDS) && !in_array($key, self::$OPTIONAL_FIELDS)) return false; @@ -142,7 +140,7 @@ abstract class ConfigModuleBaseLdap extends ConfigModule /** * Server IP changed - rebuild all AD modules. */ - public function event_serverIpChanged() + public function event_serverIpChanged(): void { $this->generate(false); } diff --git a/modules-available/sysconfig/inc/configtgz.inc.php b/modules-available/sysconfig/inc/configtgz.inc.php index 9ab3ffd3..8ac87908 100644 --- a/modules-available/sysconfig/inc/configtgz.inc.php +++ b/modules-available/sysconfig/inc/configtgz.inc.php @@ -4,25 +4,25 @@ class ConfigTgz { private $configId = 0; - private $configTitle = false; - private $file = false; + private $configTitle = ''; + private $file = ''; private $modules = array(); private function __construct() { } - public function id() + public function id(): int { return $this->configId; } - public function title() + public function title(): string { return $this->configTitle; } - public function areAllModulesUpToDate() + public function areAllModulesUpToDate(): bool { if (!$this->configId > 0) ErrorHandler::traceError('ConfigTgz::areAllModulesUpToDate called on un-inserted config.tgz!'); @@ -37,24 +37,29 @@ class ConfigTgz return true; } - public function isActive() + public function isActive(): bool { return readlink(CONFIG_HTTP_DIR . '/default/config.tgz') === $this->file; } - - public function getModuleIds() + + /** + * @return int[] + */ + public function getModuleIds(): array { - $ret = array(); + $ret = []; foreach ($this->modules as $module) { - $ret[] = $module['moduleid']; + $ret[] = (int)$module['moduleid']; } return $ret; } - - public function update($title, $moduleIds) + + /** + * @param string $title New title for module + * @param int[] $moduleIds List of modules to include in this config + */ + public function update(string $title, array $moduleIds): void { - if (!is_array($moduleIds)) - return false; if (!empty($title)) { $this->configTitle = $title; } @@ -82,20 +87,19 @@ class ConfigTgz 'status' => 'OUTDATED', 'now' => time(), )); - return true; } /** * - * @param bool $deleteOnError - * @param int $timeoutMs - * @param string|null $parentTask parent task to order this rebuild after + * @param bool $deleteOnError Delete this config in case of error? + * @param int $timeoutMs max time to wait for completion + * @param string|null $parentTask parent task to order this (re)build after * @return string|bool true=success, false=error, string=taskid, still running */ - public function generate($deleteOnError = false, $timeoutMs = 0, $parentTask = null) + public function generate(bool $deleteOnError = false, int $timeoutMs = 0, ?string $parentTask = null) { - if (!($this->configId > 0) || !is_array($this->modules) || $this->file === false) - ErrorHandler::traceError('configId <= 0 or modules not array in ConfigTgz::rebuild()'); + if (!($this->configId > 0) || empty($this->file)) + ErrorHandler::traceError('configId <= 0 or no file in ConfigTgz::rebuild()'); $files = array(); // Get all config modules for system config foreach ($this->modules as $module) { @@ -140,11 +144,12 @@ class ConfigTgz $ret = Database::exec("DELETE FROM configtgz WHERE configid = :configid LIMIT 1", ['configid' => $this->configId], true); if ($ret !== false) { - if ($this->file !== false) + if (!empty($this->file)) { Taskmanager::submit('DeleteFile', array('file' => $this->file), true); + } $this->configId = 0; - $this->modules = false; - $this->file = false; + $this->modules = []; + $this->file = ''; } return $ret !== false; } @@ -156,7 +161,7 @@ class ConfigTgz $this->mark('OUTDATED'); } - private function markUpdated($task): void + private function markUpdated(array $task): void { if ($this->configId === 0) ErrorHandler::traceError('ConfigTgz::markUpdated called with invalid config id!'); @@ -194,7 +199,7 @@ class ConfigTgz { if ($this->configId === 0) ErrorHandler::traceError('ConfigTgz::markFailed called with invalid config id!'); - if ($this->file === false || !file_exists($this->file)) { + if (empty($this->file) || !file_exists($this->file)) { $this->mark('MISSING'); } else { $this->mark('OUTDATED'); @@ -218,12 +223,12 @@ class ConfigTgz * @param string $destFile where to store final result * @return false|array taskmanager task */ - private static function recompress($files, $destFile, $parentTask = null) + private static function recompress(array $files, string $destFile, $parentTask = null) { // Get stuff other modules want to inject $handler = function($hook) { include $hook->file; - return isset($file) ? $file : false; + return $file ?? false; }; foreach (Hook::load('config-tgz') as $hook) { $file = $handler($hook); @@ -246,7 +251,7 @@ class ConfigTgz * on each one. This mostly makes sense to call if a global module * that is injected via a hook has changed. */ - public static function rebuildAllConfigs() + public static function rebuildAllConfigs(): void { Database::exec("UPDATE configtgz SET status = :status", array( 'status' => 'OUTDATED' @@ -254,7 +259,7 @@ class ConfigTgz $res = Database::simpleQuery("SELECT configid FROM configtgz"); foreach ($res as $row) { $configTgz = self::get($row['configid']); - if ($configTgz !== false) { + if ($configTgz !== null) { $configTgz->generate(); } } @@ -263,12 +268,10 @@ class ConfigTgz /** * @param string $title Title of config * @param int[] $moduleIds Modules to include in config - * @return false|ConfigTgz The module instance, false on error + * @return ConfigTgz The module instance */ - public static function insert($title, $moduleIds) + public static function insert(string $title, array $moduleIds): ConfigTgz { - if (!is_array($moduleIds)) - return false; $instance = new ConfigTgz; $instance->configTitle = $title; // Create output file name (config.tgz) @@ -300,53 +303,53 @@ class ConfigTgz return $instance; } - public static function get($configId) + /** + * @param array{configid: int, title: string, filepath: string} $row Input data, fields mandatory + */ + private static function instanceFromRow(array $row): ConfigTgz { - $ret = Database::queryFirst("SELECT configid, title, filepath FROM configtgz WHERE configid = :configid", array( - 'configid' => $configId - )); - if ($ret === false) - return false; $instance = new ConfigTgz; - $instance->configId = $ret['configid']; - $instance->configTitle = $ret['title']; - $instance->file = $ret['filepath']; - $ret = Database::simpleQuery("SELECT moduleid, moduletype, filepath, status FROM configtgz_x_module " + $instance->configId = $row['configid']; + $instance->configTitle = $row['title']; + $instance->file = $row['filepath']; + $innerRes = Database::simpleQuery("SELECT moduleid, moduletype, filepath, status FROM configtgz_x_module " . " INNER JOIN configtgz_module USING (moduleid) " . " WHERE configid = :configid", array('configid' => $instance->configId)); $instance->modules = array(); - foreach ($ret as $row) { - $instance->modules[] = $row; + foreach ($innerRes as $innerRow) { + $instance->modules[] = $innerRow; } return $instance; } + public static function get(int $configId): ?ConfigTgz + { + $ret = Database::queryFirst("SELECT configid, title, filepath FROM configtgz WHERE configid = :configid", array( + 'configid' => $configId + )); + if ($ret === false) + return null; + return self::instanceFromRow($ret); + } + /** * @param int $moduleId ID of config module - * @return ConfigTgz[]|false + * @return ConfigTgz[] */ - public static function getAllForModule($moduleId) + public static function getAllForModule(int $moduleId): array { $res = Database::simpleQuery("SELECT configid, title, filepath FROM configtgz_x_module " . " INNER JOIN configtgz USING (configid) " . " WHERE moduleid = :moduleid", array( 'moduleid' => $moduleId )); - if ($res === false) - return false; + if ($res === false) { + EventLog::warning('ConfigTgz::getAllForModule failed: ' . Database::lastError()); + return []; + } $list = array(); foreach ($res as $row) { - $instance = new ConfigTgz; - $instance->configId = $row['configid']; - $instance->configTitle = $row['title']; - $instance->file = $row['filepath']; - $innerRes = Database::simpleQuery("SELECT moduleid, moduletype, filepath, status FROM configtgz_x_module " - . " INNER JOIN configtgz_module USING (moduleid) " - . " WHERE configid = :configid", array('configid' => $instance->configId)); - $instance->modules = array(); - foreach ($innerRes as $innerRow) { - $instance->modules[] = $innerRow; - } + $instance = self::instanceFromRow($row); $list[] = $instance; } return $list; @@ -356,31 +359,32 @@ class ConfigTgz * Called when (re)generating a config tgz failed, so we can * update the status in the DB and add a server log entry. * - * @param array $task * @param array $args contains 'configid' and optionally 'deleteOnError' */ - public static function generateFailed($task, $args) + public static function generateFailed(array $task, array $args): void { if (!isset($args['configid']) || !is_numeric($args['configid'])) { EventLog::warning('Ignoring generateFailed event as it has no configid assigned.'); return; } $config = self::get($args['configid']); - if ($config === false) { + if ($config === null) { EventLog::warning('generateFailed callback for config id ' . $args['configid'] . ', but no instance could be generated.'); return; } - if (isset($task['data']['error'])) + if (isset($task['data']['error'])) { $error = $task['data']['error']; - elseif (isset($task['data']['messages'])) + } elseif (isset($task['data']['messages'])) { $error = $task['data']['messages']; - else + } else { $error = ''; + } EventLog::failure("Generating config.tgz '" . $config->configTitle . "' failed.", $error); - if ($args['deleteOnError']) + if ($args['deleteOnError']) { $config->delete(); - else + } else { $config->markFailed(); + } } /** @@ -389,14 +393,14 @@ class ConfigTgz * @param array $task the task object * @param array $args contains 'configid' and optionally 'deleteOnError' */ - public static function generateSucceeded($task, $args) + public static function generateSucceeded(array $task, array $args): void { if (!isset($args['configid']) || !is_numeric($args['configid'])) { EventLog::warning('Ignoring generateSucceeded event as it has no configid assigned.'); return; } $config = self::get($args['configid']); - if ($config === false) { + if ($config === null) { EventLog::warning('generateSucceeded callback for config id ' . $args['configid'] . ', but no instance could be generated.'); return; } diff --git a/modules-available/sysconfig/inc/ldap.inc.php b/modules-available/sysconfig/inc/ldap.inc.php index 349a662e..e974a8a3 100644 --- a/modules-available/sysconfig/inc/ldap.inc.php +++ b/modules-available/sysconfig/inc/ldap.inc.php @@ -3,7 +3,7 @@ class Ldap { - public static function normalizeDn($dn) + public static function normalizeDn(string $dn): string { return trim(preg_replace('/[,;]\s*/', ',', $dn)); } diff --git a/modules-available/sysconfig/inc/ppd.inc.php b/modules-available/sysconfig/inc/ppd.inc.php index 75608c56..c28e0355 100644 --- a/modules-available/sysconfig/inc/ppd.inc.php +++ b/modules-available/sysconfig/inc/ppd.inc.php @@ -247,8 +247,8 @@ class Ppd private $data; private $dataLen; - private $error; - private $warnings; + private $error = null; + private $warnings = []; private $knownKeywordMalformed; @@ -301,7 +301,7 @@ class Ppd $this->dataLen = strlen($this->data); $this->encoder = false; $this->sourceEncoding = false; - $this->error = false; + $this->error = null; $this->warnings = array(); $this->knownKeywordMalformed = false; $this->settings = array(); @@ -309,8 +309,8 @@ class Ppd // Parse /* @var PpdOption $rawOption */ - /* @var PpdBlockInternal $currentBlock */ - $currentBlock = false; + /* @var ?PpdBlockInternal $currentBlock */ + $currentBlock = null; $inRawBlock = false; // True if in a multi-line InvocationValue or QuotedValue (3.6: Parsing Summary for Values) $wantsEnd = false; // For now we ignore values mostly while parsing. The spec says that InvocationValues must only contain printable @@ -318,7 +318,7 @@ class Ppd $lStart = -1; $lEnd = -1; $no = 0; - while ($lStart < $this->dataLen && $lEnd !== false) { + while ($lStart < $this->dataLen) { unset($mainKeyword, $optionKeyword, $optionTranslation, $option, $value, $valueTranslation); if ($no !== 0 && $this->data[$lEnd] === "\r" && $this->data[$lEnd + 1] === "\n") { $lEnd++; @@ -332,6 +332,8 @@ class Ppd } $lStart = $lEnd + 1; $lEnd = $this->nextLineEnd($lStart); + if ($lEnd === null) + break; $no++; // Validate $len = $lEnd - $lStart; @@ -343,7 +345,7 @@ class Ppd $this->warn($no, 'Exceeds length of 255'); } if (!$inRawBlock && preg_match_all('/[^\x09\x0A\x0D\x20-\xFF]/', $line, $out)) { - $chars = $this->escapeBinaryArray($out[0]); + $chars = self::escapeBinaryArray($out[0]); $this->warn($no, 'Contains invalid character(s) ' . $chars); } // Handle @@ -379,7 +381,7 @@ class Ppd continue; } $parts = preg_split('/\s*:\s*/', $line, 2); // TODO: UIConstrains - if (count($parts) !== 2) { + if (!is_array($parts) || count($parts) !== 2) { $this->warn($no, 'No colon found; not in "key [option]: value" format, ignoring line'); continue; } @@ -390,9 +392,10 @@ class Ppd continue; } $mainKeyword = $out[1]; - $optionKeyword = isset($out[3]) ? $out[3] : false; + $optionKeyword = $out[3] ?? null; $optionTranslation = isset($out[4]) ? $this->unhexTranslation($no, substr($out[4], 1)) : $optionKeyword; // If no translation given, fallback to option // 3b) Handle value + /** @var string $value */ $value = $parts[1]; if ($value[0] === '"') { // Start of InvocationValue or QuotedValue @@ -419,17 +422,17 @@ class Ppd // Key-value-pair parsed, now the fun part // Special cases for opening closing certain groups if ($mainKeyword === 'OpenGroup') { - if ($currentBlock !== false) { + if ($currentBlock !== null) { $this->error = 'Line ' . $no . ': OpenGroup while other block (type=' . $currentBlock->type . ', id=' . $currentBlock->id . ') was not closed yet'; return; } // TODO: Check unique - $nb = new PpdBlockInternal($value, $valueTranslation, 'Group', false, $lStart); + $nb = new PpdBlockInternal($value, $valueTranslation, 'Group', null, $lStart); $currentBlock = $nb; continue; } elseif ($mainKeyword === 'OpenSubGroup') { - if ($currentBlock === false || $currentBlock->type !== 'Group') { + if ($currentBlock === null || $currentBlock->type !== 'Group') { $this->error = 'Line ' . $no . ': OpenSubGroup with no preceding OpenGroup'; return; } @@ -445,12 +448,12 @@ class Ppd } else { $type = substr($type, 4); } - if ($currentBlock !== false && $currentBlock->isUi()) { + if ($currentBlock !== null && $currentBlock->isUi()) { $this->error = 'Line ' . $no . ': ' . $mainKeyword . ' while previous ' . $type . ' "' . $currentBlock->id . '" was not closed yet'; return; } - if ($optionKeyword === false) { + if ($optionKeyword === null) { $this->error = 'Line ' . $no . ': ' . $mainKeyword . ' with no option keyword'; return; } @@ -459,9 +462,10 @@ class Ppd return; } // TODO: Check unique - $nb = new PpdBlockInternal($optionKeyword, $optionTranslation, $type, $currentBlock, $lStart); + $nb = new PpdBlockInternal($optionKeyword, $optionTranslation ?? $optionKeyword, + $type, $currentBlock, $lStart); $nb->value = $value; - if ($currentBlock !== false) { + if ($currentBlock !== null) { $currentBlock->childBlocks[] = $nb; } $currentBlock = $nb; @@ -476,7 +480,7 @@ class Ppd } else { $type = substr($type, 5); } - if ($currentBlock === false) { + if ($currentBlock === null) { $this->error = 'Line ' . $no . ': ' . $mainKeyword . ' with no Open' . $type; return; } @@ -493,7 +497,7 @@ class Ppd $currentBlock = $currentBlock->parent; continue; } elseif ($mainKeyword === 'OrderDependency') { - if ($currentBlock === false || $currentBlock->isUi()) { + if ($currentBlock === null || $currentBlock->isUi()) { $this->warn($no, 'OrderDependency outside OpenUI/CloseUI block'); } continue; @@ -519,7 +523,7 @@ class Ppd } else { $this->requiredKeywords[$mainKeyword] = array($value); } - if (($err = $this->validateLine($this->REQUIRED_KEYWORDS[$mainKeyword], $optionKeyword, $value)) !== true) { + if (($err = Ppd::validateLine($this->REQUIRED_KEYWORDS[$mainKeyword], $optionKeyword, $value)) !== true) { $this->warn($no, 'Required main keyword ' . $mainKeyword . ': ' . $err); $this->knownKeywordMalformed = true; } @@ -527,7 +531,7 @@ class Ppd } // Other well known keywords if (isset($this->KNOWN_KEYWORDS[$mainKeyword])) { - if (($err = $this->validateLine($this->KNOWN_KEYWORDS[$mainKeyword], $optionKeyword, $value)) !== true) { + if (($err = Ppd::validateLine($this->KNOWN_KEYWORDS[$mainKeyword], $optionKeyword, $value)) !== true) { $this->warn($no, 'Known main keyword ' . $mainKeyword . ': ' . $err); $this->knownKeywordMalformed = true; } @@ -539,16 +543,16 @@ class Ppd continue; } if (substr($mainKeyword, 0, 17) === 'FoomaticRIPOption') { - if ($optionKeyword === false) { + if ($optionKeyword === null) { $this->warn($no, "$mainKeyword with no option keyword"); - } elseif ($currentBlock !== false && isset($this->settings[$optionKeyword])) { + } elseif ($currentBlock !== null && isset($this->settings[$optionKeyword])) { $option = $this->getOption($optionKeyword, $currentBlock); $option->foomatic[substr($mainKeyword, 11)] = new PpdOption($lStart, $len, $value, $valueTranslation); } else { $this->warn($no, 'TODO: ' . $line); } } elseif (substr($mainKeyword, 0, 6) === 'Custom') { - if ($optionKeyword === false) { + if ($optionKeyword === null) { $this->warn($no, "$mainKeyword with no option keyword"); } elseif ($optionKeyword !== 'True') { $this->warn($no, "$mainKeyword with option keyword other than 'True'; ignored"); @@ -557,7 +561,7 @@ class Ppd $option->custom = new PpdOption($lStart, $len, $value, $valueTranslation); } } elseif (substr($mainKeyword, 0, 11) === 'ParamCustom') { - if ($optionKeyword === false) { + if ($optionKeyword === null) { $this->warn($no, "$mainKeyword with no option keyword"); } elseif (substr($mainKeyword, 11) !== $optionKeyword) { $this->warn($no, "Don't know how to handle $mainKeyword with option keyword $optionKeyword " @@ -568,18 +572,18 @@ class Ppd } } elseif ($mainKeyword[0] === '?') { // Ignoring option query for now - } elseif ($optionKeyword === false && !isset($this->KNOWN_KEYWORDS[$mainKeyword])) { + } elseif ($optionKeyword === null && !isset($this->KNOWN_KEYWORDS[$mainKeyword])) { // Must be a definition for an option $this->warn($no, "Don't know how to handle line with main keyword '$mainKeyword', no option keyword found."); } else { // Some option for some option ;) - if ($optionKeyword === false) { + if ($optionKeyword === null) { // We know that this is a known main keyword otherwise we would have hit the previous elseif block $optionKeyword = $value; $optionTranslation = $valueTranslation; } $option = $this->getOption($mainKeyword, $currentBlock); - $optionInstance = new PpdOption($lStart, $len, $optionKeyword, $optionTranslation); + $optionInstance = new PpdOption($lStart, $len, $optionKeyword, $optionTranslation ?? $optionKeyword); if ($this->binary_in_array($mainKeyword, $this->REPEATED_KEYWORDS)) { // This can occur multiple times, just pile them up $option->values[] = $optionInstance; @@ -602,7 +606,7 @@ class Ppd } } // end while loop over ppd contents // - if ($currentBlock !== false) { + if ($currentBlock !== null) { $this->error = 'Block ' . $currentBlock->id . ' (' . $currentBlock->type . ') was never closed.'; return; } @@ -612,11 +616,11 @@ class Ppd $this->error = 'One or more required keywords missing'; } } - if ($this->error !== false) { + if ($this->error !== null) { return; } // All required keywords exist - if (preg_match('/utf\-?8/i', $this->requiredKeywords['LanguageEncoding'][0])) { + if (preg_match('/utf-?8/i', $this->requiredKeywords['LanguageEncoding'][0])) { $this->sourceEncoding = false; // Would be a NOOP } elseif (isset($this->ENCODINGS[$this->requiredKeywords['LanguageEncoding'][0]])) { $this->sourceEncoding = $this->ENCODINGS[$this->requiredKeywords['LanguageEncoding'][0]]; @@ -666,10 +670,10 @@ class Ppd } } - private function nextLineEnd($start) + private function nextLineEnd(int $start): ?int { if ($start >= $this->dataLen) - return false; + return null; while ($start < $this->dataLen) { $char = $this->data[$start]; if ($char === "\r" || $char === "\n") @@ -679,26 +683,26 @@ class Ppd return $this->dataLen; } - private function warn($lineNo, $message) + private function warn(int $lineNo, string $message): void { $line = 'Line ' . $lineNo . ': ' . $message; $this->warnings[] = $line; } - private function escapeBinaryArray($array) + private static function escapeBinaryArray(array $array): string { return array_reduce(array_unique($array), function ($carry, $item) { return $carry . '\x' . dechex(ord($item)); }, ''); } - private function unhexTranslation($lineNo, $translation) + private function unhexTranslation(int $lineNo, string $translation): string { if (strpos($translation, '<') === false) return $translation; return preg_replace_callback('/<[^>]*>/', function ($match) use ($lineNo) { if (preg_match_all('/[^a-fA-F0-9\<\>\s]/', $match[0], $out)) { - $this->warn($lineNo, 'Invalid character(s) in hex substring: ' . $this->escapeBinaryArray($out[0])); + $this->warn($lineNo, 'Invalid character(s) in hex substring: ' . self::escapeBinaryArray($out[0])); } $string = preg_replace('/[^a-fA-F0-9]/', '', $match[0]); if (strlen($string) % 2 !== 0) { @@ -709,7 +713,7 @@ class Ppd }, $translation); } - private function hexTranslation($translation) + private function hexTranslation(string $translation): string { return preg_replace_callback('/[\x00-\x1f\x7b-\xff\:\<\>]+/', function ($match) { return '<' . unpack('H*', $match[0])[1] . '>'; @@ -720,23 +724,23 @@ class Ppd * Get option object * * @param string $name option name - * @param \PpdBlockInternal $block which block this option is defined in - * @return \PpdSettingInternal the option object + * @param ?PpdBlockInternal $block which block this option is defined in + * @return PpdSettingInternal the option object */ - private function getOption($name, $block = false) + private function getOption(string $name, ?PpdBlockInternal $block = null): PpdSettingInternal { if (!isset($this->settings[$name])) { $this->settings[$name] = new PpdSettingInternal(); $this->settings[$name]->block = $block; - } elseif ($block !== false) { - if ($this->settings[$name]->block === false || $block->isChildOf($this->settings[$name]->block)) { + } elseif ($block !== null) { + if ($this->settings[$name]->block === null || $block->isChildOf($this->settings[$name]->block)) { $this->settings[$name]->block = $block; } } return $this->settings[$name]; } - private function binary_in_array($elem, $array) + private function binary_in_array($elem, $array): bool { $top = sizeof($array) - 1; $bot = 0; @@ -751,7 +755,7 @@ class Ppd return false; } - private function validateLine($validator, $option, $value) + private static function validateLine($validator, ?string $option, string $value) { if (is_array($validator)) { $oExp = $validator[0]; @@ -776,7 +780,7 @@ class Ppd return true; } - private function getEolChar() + private function getEolChar(): string { $rn = substr_count("\r\n", $this->data); $r = substr_count("\r", $this->data) - $rn; @@ -795,21 +799,21 @@ class Ppd * */ - public function getError() + public function getError(): ?string { return $this->error; } - public function getWarnings() + public function getWarnings(): array { return $this->warnings; } - public function getUISettings() + public function getUISettings(): array { $result = array(); foreach ($this->settings as $mk => $option) { - $isUi = ($option->block !== false && $option->block->isUi()) || isset($this->UI_KEYWORDS[$mk]); + $isUi = ($option->block !== null && $option->block->isUi()) || isset($this->UI_KEYWORDS[$mk]); if ($isUi) { $result[] = $mk; } @@ -817,30 +821,30 @@ class Ppd return $result; } - public function getSetting($name) + public function getSetting(string $name): ?PpdSetting { if (!isset($this->settings[$name])) - return false; + return null; return new PpdSetting($this->settings[$name], isset($this->UI_KEYWORDS[$name]), $this->encoder); } - public function removeSetting($name) + public function removeSetting(string $name): bool { if (!isset($this->settings[$name])) return false; $setting = $this->settings[$name]; $ranges = array(); - $this->mergeRanges($ranges, $setting->default); - $this->mergeRanges($ranges, $setting->custom); - $this->mergeRanges($ranges, $setting->customParam); + Ppd::mergeRangesFromOption($ranges, $setting->default); + Ppd::mergeRangesFromOption($ranges, $setting->custom); + Ppd::mergeRangesFromOption($ranges, $setting->customParam); foreach ($setting->foomatic as $obj) { - $this->mergeRanges($ranges, $obj); + Ppd::mergeRangesFromOption($ranges, $obj); } foreach ($setting->values as $obj) { - $this->mergeRanges($ranges, $obj); + Ppd::mergeRangesFromOption($ranges, $obj); } - if ($setting->block !== false && $setting->block->isUi()) { - $this->mergeRanges($ranges, $setting->block->start, $setting->block->end); + if ($setting->block !== null && $setting->block->isUi()) { + Ppd::mergeRanges($ranges, $setting->block->start, $setting->block->end); } $tmp = array_map(function ($e) { return $e[0]; }, $ranges); array_multisort($tmp, SORT_NUMERIC, $ranges); @@ -859,10 +863,10 @@ class Ppd $new .= substr($this->data, $last); $this->data = $new; $this->parse(); - return $this->error === false; + return $this->error === null; } - public function addEmptyOption($settingName, $option, $translation = false, $prepend = true) + public function addEmptyOption(string $settingName, string $option, string $translation = null, bool $prepend = true): bool { if (!isset($this->settings[$settingName])) return false; @@ -870,15 +874,15 @@ class Ppd $pos = false; if (!empty($setting->values)) { if ($prepend) { - $pos = array_reduce($setting->values, function ($carry, $option) { return min($carry, $option->lineOffset); }, PHP_INT_MAX); + $pos = array_reduce($setting->values, function (int $carry, PpdOption $option) { return min($carry, $option->lineOffset); }, PHP_INT_MAX); } else { - $pos = array_reduce($setting->values, function ($carry, $option) { return max($carry, $option->lineOffset); }, 0); + $pos = array_reduce($setting->values, function (int $carry, PpdOption $option) { return max($carry, $option->lineOffset); }, 0); } - } elseif ($setting->default !== false) { + } elseif ($setting->default !== null) { $pos = $setting->default->lineOffset; - } elseif ($setting->block !== false && $setting->block->isUi()) { + } elseif ($setting->block !== null && $setting->block->isUi()) { $pos = $this->nextLineEnd($setting->block->start); - while ($pos !== false && $pos < $this->dataLen && ($this->data[$pos] === "\r" || $this->data[$pos] === "\n")) { + while ($pos !== null && $pos < $this->dataLen && ($this->data[$pos] === "\r" || $this->data[$pos] === "\n")) { $pos++; } } @@ -886,23 +890,23 @@ class Ppd return false; } $line = '*' . $settingName . ' ' . $option; - if ($translation !== false) { + if ($translation !== null) { $line .= '/' . $this->hexTranslation(($this->encoder)($translation, true)); } $eol = $this->getEolChar(); $line .= ': ""' . $eol; $this->data = substr($this->data, 0, $pos) . $line . substr($this->data, $pos); $this->parse(); - return $this->error === false; + return $this->error === null; } - public function setDefaultOption($settingName, $optionName) + public function setDefaultOption($settingName, $optionName): bool { if (!isset($this->settings[$settingName])) return false; $setting = $this->settings[$settingName]; $line = '*Default' . $settingName . ': ' . $optionName; - if ($setting->default !== false) { + if ($setting->default !== null) { $start = $setting->default->lineOffset; $end = $start + $setting->default->lineLen; } elseif (empty($setting->values)) { @@ -914,22 +918,21 @@ class Ppd } $this->data = substr($this->data, 0, $start) . $line . substr($this->data, $end); $this->parse(); - return $this->error === false; + return $this->error === null; } - public function write($file) + public function write(string $file) { return file_put_contents($file, $this->data); } - private function mergeRanges(&$ranges, $start, $end = false) + private static function mergeRangesFromOption(array &$ranges, PpdOption $option): void + { + self::mergeRanges($ranges, $option->lineOffset, $option->lineOffset + $option->lineLen); + } + + private static function mergeRanges(array &$ranges, int $start, int $end): void { - if (is_object($start) && get_class($start) === 'PpdOption') { - $end = $start->lineOffset + $start->lineLen; - $start = $start->lineOffset; - } - if ($start === false || $end === false) - return; if ($start >= $end) return; // Don't even bother foreach (array_keys($ranges) as $key) { @@ -961,7 +964,7 @@ class Ppd /** * @return bool whether there was at least one known option with format restriction violated. */ - public function hasInvalidOption() + public function hasInvalidOption(): bool { return $this->knownKeywordMalformed; } @@ -1009,15 +1012,13 @@ class PpdSetting /** * PpdSetting constructor. - * - * @param \PpdSettingInternal $setting */ - public function __construct($setting, $isUi, $enc) + public function __construct(PpdSettingInternal $setting, bool $isUi, callable $enc) { - if ($setting->default !== false) { + if ($setting->default !== null) { $this->default = $setting->default->option; } - if ($setting->block !== false && $setting->block->isUi()) { + if ($setting->block !== null && $setting->block->isUi()) { $this->uiOptionType = $setting->block->value; $this->uiOptionTranslation = $enc($setting->block->translation); $this->isUi = true; @@ -1051,9 +1052,9 @@ class PpdSetting class PpdSettingInternal { /** - * @var \PpdOption + * @var ?PpdOption */ - public $default = false; + public $default = null; /** * @var \PpdOption[] */ @@ -1063,17 +1064,17 @@ class PpdSettingInternal */ public $foomatic = array(); /** - * @var \PpdOption + * @var ?PpdOption */ - public $custom = false; + public $custom = null; /** - * @var \PpdOption + * @var ?PpdOption */ - public $customParam = false; + public $customParam = null; /** - * @var \PpdBlockInternal the innermost block this option resides in + * @var ?PpdBlockInternal the innermost block this option resides in */ - public $block = false; + public $block = null; } class PpdOption @@ -1084,7 +1085,7 @@ class PpdOption public $lineLen; public $multiLine = false; - public function __construct($lineOffset, $lineLen, $option, $optionTranslation) + public function __construct(int $lineOffset, int $lineLen, string $option, string $optionTranslation) { $this->option = $option; $this->optionTranslation = $optionTranslation; @@ -1106,9 +1107,9 @@ class PpdBlockInternal */ public $childBlocks = array(); /** - * @var PpdBlockInternal|false + * @var ?PpdBlockInternal */ - public $parent; + public $parent = null; /** * @var int start byte in ppd @@ -1116,16 +1117,16 @@ class PpdBlockInternal public $start; /** - * @var int|bool end byte in ppd, false if block is not closed + * @var ?int end byte in ppd, null if block is not closed */ - public $end = false; + public $end = null; /** * @var string value of opening line for block, e.g. 'PickOne' for OpenUI */ - public $value = false; + public $value = ''; - public function __construct($id, $translation, $type, $parent, $start) + public function __construct(string $id, string $translation, string $type, ?PpdBlockInternal $parent, int $start) { $this->id = $id; $this->translation = $translation; @@ -1137,7 +1138,7 @@ class PpdBlockInternal /** * @return bool true if this is a UI block */ - public function isUi() + public function isUi(): bool { return $this->type == 'UI' || $this->type === 'JCLUI'; } @@ -1146,7 +1147,7 @@ class PpdBlockInternal * @param PpdBlockInternal $block some other PpdBlock instance * @return bool true if this is a child of $block */ - public function isChildOf(PpdBlockInternal $block) + public function isChildOf(PpdBlockInternal $block): bool { $parent = $this->parent; while ($parent !== false) { diff --git a/modules-available/sysconfig/inc/sysconfig.inc.php b/modules-available/sysconfig/inc/sysconfig.inc.php index 02131366..09860c7d 100644 --- a/modules-available/sysconfig/inc/sysconfig.inc.php +++ b/modules-available/sysconfig/inc/sysconfig.inc.php @@ -3,7 +3,7 @@ class SysConfig { - public static function getAll() + public static function getAll(): array { $res = Database::simpleQuery("SELECT c.configid, c.title, c.filepath, c.status, Group_Concat(cl.locationid) AS locs FROM configtgz c" . " LEFT JOIN configtgz_location cl USING (configid) GROUP BY c.configid"); diff --git a/modules-available/sysconfig/install.inc.php b/modules-available/sysconfig/install.inc.php index 9d32137c..53882882 100644 --- a/modules-available/sysconfig/install.inc.php +++ b/modules-available/sysconfig/install.inc.php @@ -125,28 +125,28 @@ Module::isAvailable('sysconfig'); $list = ConfigModule::getAll(); $parentTask = null; $configList = []; -if ($list === false) { +if ($list === null) { EventLog::warning('Could not regenerate configs - please do so manually'); } else { - foreach ($list as $ad) { - if ($ad->moduleType() === 'SshConfig') { + foreach ($list as $confMod) { + if ($confMod->moduleType() === 'SshConfig') { // 2020-11-12: Split SshConfig into SshConfig and SshKey - $pubkey = $ad->getData('publicKey'); + $pubkey = $confMod->getData('publicKey'); if (!empty($pubkey)) { - error_log('Legacy module with pubkey ' . $ad->id()); - $key = ConfigModule::getInstance('SshKey'); - if ($key !== false) { + error_log('Legacy module with pubkey ' . $confMod->id()); + $key = ConfigModule::getInstanceOrNull('SshKey'); + if ($key !== null) { $key->setData('publicKey', $pubkey); - if ($key->insert($ad->title())) { + if ($key->insert($confMod->title())) { // Insert worked, remove key from old module, add this module to the same configs $task = $key->generate(false, $parentTask); if ($task !== false) { $parentTask = $task; } error_log('Inserted new module with id ' . $key->id()); - $ad->setData('publicKey', false); - $ad->update(); - $configs = ConfigTgz::getAllForModule($ad->id()); + $confMod->setData('publicKey', false); + $confMod->update(); + $configs = ConfigTgz::getAllForModule($confMod->id()); foreach ($configs as $config) { // Add newly created key-only module to all configs $new = array_merge($config->getModuleIds(), [$key->id()]); @@ -158,9 +158,9 @@ if ($list === false) { } } } - if ($ad->needRebuild()) { + if ($confMod->needRebuild()) { $update[] = UPDATE_DONE; - $task = $ad->generate(false, $parentTask); + $task = $confMod->generate(false, $parentTask); if ($task !== false) { $parentTask = $task; } diff --git a/modules-available/sysconfig/page.inc.php b/modules-available/sysconfig/page.inc.php index e868ec67..41c4a2db 100644 --- a/modules-available/sysconfig/page.inc.php +++ b/modules-available/sysconfig/page.inc.php @@ -152,11 +152,12 @@ class Page_SysConfig extends Page $listid = Request::post('list', Request::REQUIRED, 'int'); $this->listConfigContents($listid); return; + default: } Message::addError('invalid-action', $action, 'main'); } - private function getLocationNames($locations, $ids) + private function getLocationNames(array $locations, array $ids): string { $ret = array(); foreach ($ids as $id) { @@ -236,7 +237,7 @@ class Page_SysConfig extends Page private function listModules() { // Config modules - $modules = ConfigModule::getAll(); + $modules = ConfigModule::getAll() ?? []; $types = array_map(function ($mod) { return $mod->moduleType(); }, $modules); $titles = array_map(function ($mod) { return $mod->title(); }, $modules); array_multisort($types, SORT_ASC, $titles, SORT_ASC, $modules); @@ -336,7 +337,7 @@ class Page_SysConfig extends Page { $configid = Request::post('rebuild', Request::REQUIRED, 'int'); $config = ConfigTgz::get($configid); - if ($config === false) { + if ($config === null) { Message::addError('config-invalid', $configid); Util::redirect('?do=sysconfig&locationid=' . $this->currentLoc); } @@ -377,7 +378,7 @@ class Page_SysConfig extends Page // Rebuild depending config.tgz foreach ($existing as $crow) { $config = ConfigTgz::get($crow['configid']); - if ($config !== false) { + if ($config !== null) { $config->generate(); } } @@ -401,7 +402,7 @@ class Page_SysConfig extends Page { $moduleid = Request::post('rebuild', Request::REQUIRED); $module = ConfigModule::get($moduleid); - if ($module === false) { + if ($module === null) { Message::addError('config-invalid', $moduleid); Util::redirect('?do=sysconfig'); } @@ -419,7 +420,7 @@ class Page_SysConfig extends Page { $configid = Request::post('del', Request::REQUIRED); $config = ConfigTgz::get($configid); - if ($config === false) { + if ($config === null) { Message::addError('config-invalid', $configid); Util::redirect('?do=sysconfig&locationid=' . $this->currentLoc); } diff --git a/modules-available/syslog/page.inc.php b/modules-available/syslog/page.inc.php index 023dd965..401d9dd8 100644 --- a/modules-available/syslog/page.inc.php +++ b/modules-available/syslog/page.inc.php @@ -126,7 +126,7 @@ class Page_SysLog extends Page )); } - private function eventToIconName($event) + private function eventToIconName(string $event): string { switch ($event) { case 'session-open': diff --git a/modules-available/systemstatus/inc/systemstatus.inc.php b/modules-available/systemstatus/inc/systemstatus.inc.php index 7f3e5d42..4f87fa4e 100644 --- a/modules-available/systemstatus/inc/systemstatus.inc.php +++ b/modules-available/systemstatus/inc/systemstatus.inc.php @@ -13,7 +13,7 @@ class SystemStatus * @param string|false $wantedSource What should be mounted as vmstore (false if nothing configured) * @return bool false if querying fs data from taskmanager failed */ - public static function diskStat(&$systemUsage, &$storeUsage, &$currentSource = false, &$wantedSource = false) + public static function diskStat(&$systemUsage, &$storeUsage, &$currentSource = false, &$wantedSource = false): bool { $task = Taskmanager::submit('DiskStat'); if ($task === false) diff --git a/modules-available/systemstatus/page.inc.php b/modules-available/systemstatus/page.inc.php index c87dabda..dbad2871 100644 --- a/modules-available/systemstatus/page.inc.php +++ b/modules-available/systemstatus/page.inc.php @@ -92,7 +92,7 @@ class Page_SystemStatus extends Page foreach ($tabs as $tab) { $data['tabs'][] = array( 'type' => $tab, - 'name' => Dictionary::translate('tab_' . $tab, true), + 'name' => Dictionary::translate('tab_' . $tab), 'enabled' => User::hasPermission('tab.' . $tab), 'important' => $tab === 'ListUpgradable' && SystemStatus::getAptLastDbUpdateTime() + 864000 < time(), ); @@ -117,7 +117,8 @@ class Page_SystemStatus extends Page $this->$action(); Message::renderList(); } else { - echo "Action $action not known in " . get_class(); + // get_class() !== get_class($this) + echo "Action $action not known in " . get_class($this); } } @@ -212,16 +213,17 @@ class Page_SystemStatus extends Page 'addresses' => $task['data']['addresses'] )); } - - private function sysInfo() + + private function sysInfo(): array { $data = array(); $memInfo = file_get_contents('/proc/meminfo'); $stat = file_get_contents('/proc/stat'); - preg_match_all('/\b(\w+):\s+(\d+)\s/s', $memInfo, $out, PREG_SET_ORDER); + preg_match_all('/\b(\w+):\s+(\d+)\s/', $memInfo, $out, PREG_SET_ORDER); foreach ($out as $e) { $data[$e[1]] = $e[2]; } + /** @var array{user: numeric, nice: numeric, system: numeric, idle: numeric, iowait: numeric, irq: numeric, softirq: numeric} $out */ if (preg_match('/\bcpu\s+(?<user>\d+)\s+(?<nice>\d+)\s+(?<system>\d+)\s+(?<idle>\d+)\s+(?<iowait>\d+)\s+(?<irq>\d+)\s+(?<softirq>\d+)(\s|$)/', $stat, $out)) { $data['CpuTotal'] = $out['user'] + $out['nice'] + $out['system'] + $out['idle'] + $out['iowait'] + $out['irq'] + $out['softirq']; $data['CpuIdle'] = $out['idle'] + $out['iowait']; @@ -438,7 +440,7 @@ class Page_SystemStatus extends Page $output = []; foreach ($ids as $id) { $module = ConfigModule::get($id); - if ($module === false) { + if ($module === null) { $name = "#$id"; } else { $name = $module->title(); @@ -462,10 +464,7 @@ class Page_SystemStatus extends Page return; $status = Taskmanager::waitComplete($taskId, 3500); - if (isset($status['data']['messages'])) - $data = $status['data']['messages']; - else - $data = 'Taskmanager error'; + $data = $status['data']['messages'] ?? 'Taskmanager error'; echo '<pre>', htmlspecialchars($data, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), '</pre>'; } @@ -478,14 +477,14 @@ class Page_SystemStatus extends Page return; $status = Taskmanager::waitComplete($taskId, 3500); - if (isset($status['data']['messages'])) - $data = $status['data']['messages']; - else - $data = 'Taskmanager error'; + $data = $status['data']['messages'] ?? 'Taskmanager error'; echo '<pre>', htmlspecialchars($data, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), '</pre>'; } + /** + * @return array{percent: numeric, size: string, free: string, color: string, filesystem: string} + */ private function convertDiskStat(array $stat, int $minFreeMb): array { return [ diff --git a/modules-available/translation/page.inc.php b/modules-available/translation/page.inc.php index da4205d2..578e27dc 100644 --- a/modules-available/translation/page.inc.php +++ b/modules-available/translation/page.inc.php @@ -1,5 +1,7 @@ <?php +use JetBrains\PhpStorm\NoReturn; + /** * The pages where you can administrate the website translations */ @@ -45,12 +47,12 @@ class Page_Translation extends Page $this->builtInSections = array('template', 'messages', 'module', 'menucategory', 'custom'); } - private function isValidSection($section) + private function isValidSection(string $section): bool { return in_array($section, $this->builtInSections); } - private function loadCustomHandler($moduleName) + private function loadCustomHandler(string $moduleName): ?array { $path = 'modules/' . $moduleName . '/hooks/translation.inc.php'; $HANDLER = array(); @@ -75,7 +77,7 @@ class Page_Translation extends Page } } if (empty($backup)) - return false; + return null; return $backup; } @@ -83,7 +85,8 @@ class Page_Translation extends Page * Redirect to the closest matching page, as extracted from * get/post parameters. */ - private function redirect($level = 99) + #[NoReturn] + private function redirect(int $level = 99): void { $params = array('do' => 'translation'); if ($level > 0 && $this->module !== false) { @@ -329,9 +332,9 @@ class Page_Translation extends Page Render::addTemplate('menu-category-list', $data); } - private function showModuleCustom() + private function showModuleCustom(): void { - if ($this->customHandler === false) + if ($this->customHandler === null) return; foreach ($this->customHandler['subsections'] as $subsection) { $this->showModuleCustomSubsection($subsection); @@ -420,11 +423,11 @@ class Page_Translation extends Page /** * Get all tags used by templates of the given module. - * @param \Module $module module in question, false to use the one being edited. + * @param \Module $module module in question, null to use the one being edited. * * @return array of array(tag => array of templates using that tag) */ - private function loadUsedTemplateTags($module = false) + private function loadUsedTemplateTags(Module $module = null): array { if ($module === false) { $module = $this->module; @@ -451,10 +454,10 @@ class Page_Translation extends Page * 'files' => array(filename => occurencecount, ...) * ) * - * @param \Module $module module in question, false to use the one being edited + * @param \Module $module module in question, null to use the one being edited * @return array see above */ - private function loadUsedMessageTags($module = false) + private function loadUsedMessageTags(Module $module = null): array { if ($module === false) { $module = $this->module; @@ -484,10 +487,9 @@ class Page_Translation extends Page /** * Get all module tags used/required. * - * @param string $module - * @return array of array(tagname => (bool)required) + * @return array (<tagname> => (bool)required) */ - private function loadUsedModuleTags($module = false) + private function loadUsedModuleTags(Module $module = null): array { if ($module === false) { $module = $this->module; @@ -499,7 +501,7 @@ class Page_Translation extends Page } unset($tag); // Fixup special tags - if ($module->getCategory() === false) { + if ($module->getCategory() === null) { unset($tags['module_name']); unset($tags['page_title']); } else { @@ -509,7 +511,7 @@ class Page_Translation extends Page return $tags; } - private function loadUsedMenuCategories() + private function loadUsedMenuCategories(): array { $module = $this->module; $skip = strlen($module->getIdentifier()) + 1; @@ -517,7 +519,7 @@ class Page_Translation extends Page $want = array(); foreach (Module::getAll() as $module) { $cat = $module->getCategory(); - if (is_string($cat) && substr($cat, 0, $skip) === $match) { + if (substr($cat, 0, $skip) === $match) { $want[substr($cat, $skip)] = true; } } @@ -533,14 +535,14 @@ class Page_Translation extends Page * @param string $subsection Name of subsection * @return array|false List of tags as KEYS of array */ - private function loadUsedCustomTags($subsection) + private function loadUsedCustomTags(string $subsection) { if (!isset($this->customHandler['grep_'.$subsection])) return false; return $this->customHandler['grep_'.$subsection]($this->module); } - private function getTagsFromTemplate($templateFile) + private function getTagsFromTemplate(string $templateFile) { //checks if the template is valid if (!file_exists($templateFile)) { @@ -561,10 +563,10 @@ class Page_Translation extends Page * * @param string $lang lang to use * @param array $tags Array of tags, where the tag names are the keys - * @param \Module|false $module the module to work with, defaults to the currently edited module + * @param Module $module the module to work with, defaults to the currently edited module * @return array [missingCount, unusedCount] */ - private function getModuleTemplateStatus($lang, $tags = false, $module = false) + private function getModuleTemplateStatus(string $lang, array $tags, Module $module = null): array { return $this->getModuleTranslationStatus($lang, 'template-tags', true, $tags, $module); } @@ -576,12 +578,12 @@ class Page_Translation extends Page * * @param string $lang lang cc to use * @param string $file the name of the translation file to load for checking - * @param boolean $fallback whether to check the global-tags of the main module as fallback + * @param bool $fallback whether to check the global-tags of the main module as fallback * @param array $tags list of tags that are expected to exist. Tags are the array keys! - * @param \Module|false $module the module to work with, defaults to the currently edited module + * @param Module $module the module to work with, defaults to the currently edited module * @return array [missingCount, unusedCount] */ - private function getModuleTranslationStatus($lang, $file, $fallback, $tags, $module = false) + private function getModuleTranslationStatus(string $lang, string $file, bool $fallback, array $tags, Module $module = null): array { if ($module === false) { $module = $this->module; @@ -616,7 +618,7 @@ class Page_Translation extends Page return array($missing, $unused); } - private function checkModuleTranslation($module) + private function checkModuleTranslation(Module $module): string { $templateTags = $this->loadUsedTemplateTags($module); $messageTags = $this->loadUsedMessageTags($module); @@ -651,7 +653,7 @@ class Page_Translation extends Page * * @return array of all php file names */ - private function getAllFiles($dir, $extension) + private function getAllFiles(string $dir, string $extension): array { $php = array(); $extLen = -strlen($extension); @@ -671,10 +673,10 @@ class Page_Translation extends Page /** * Finds and returns all PHP files of current module. * - * @param \Module $module Module to get the php files of + * @param Module $module Module to get the php files of * @return array of php file names */ - private function getModulePhpFiles($module) + private function getModulePhpFiles(Module $module): array { return $this->getAllFiles('modules/' . $module->getIdentifier(), '.php'); } @@ -682,10 +684,9 @@ class Page_Translation extends Page /** * Get array to pass to edit page with all the tags and translations. * - * @param string $path the template's path * @return array structure to pass to the tags list in the edit template */ - private function loadTemplateEditArray() + private function loadTemplateEditArray(): array { $tags = $this->loadUsedTemplateTags(); $table = $this->buildTranslationTable('template-tags', array_keys($tags), true); @@ -704,10 +705,9 @@ class Page_Translation extends Page /** * Get array to pass to edit page with all the message ids. * - * @param string $path the template's path * @return array structure to pass to the tags list in the edit template */ - private function loadMessagesEditArray() + private function loadMessagesEditArray(): array { $tags = $this->loadUsedMessageTags(); $table = $this->buildTranslationTable('messages', array_keys($tags), true); @@ -731,16 +731,15 @@ class Page_Translation extends Page /** * Get array to pass to edit page with all the message ids. * - * @param string $path the template's path * @return array structure to pass to the tags list in the edit template */ - private function loadModuleEditArray() + private function loadModuleEditArray(): array { $tags = $this->loadUsedModuleTags(); return $this->buildTranslationTable('module', array_keys($tags), true); } - private function loadMenuCategoryEditArray() + private function loadMenuCategoryEditArray(): array { $tags = $this->loadUsedMenuCategories(); return $this->buildTranslationTable('categories', array_keys($tags), true); @@ -749,10 +748,9 @@ class Page_Translation extends Page /** * Get array to pass to edit page with all the message ids. * - * @param string $path the template's path * @return array structure to pass to the tags list in the edit template */ - private function loadCustomEditArray() + private function loadCustomEditArray(): array { $tags = $this->loadUsedCustomTags($this->subsection); return $this->buildTranslationTable($this->subsection, array_keys($tags), true); @@ -767,7 +765,7 @@ class Page_Translation extends Page * @param string $str the partial method call * @return int number of arguments to the method, minus the message id */ - private function countMessageParams($str) + private function countMessageParams(string $str): int { $quote = false; $escape = false; @@ -826,11 +824,11 @@ class Page_Translation extends Page * )). * * @param string $regexp regular expression - * @param array $files list of files to scan - * @param array $tags existing tag array to append to + * @param string[] $files list of files to scan + * @param string[] $tags existing tag array to append to * @return array of all tags found, where the tag is the key, and the value is as described above */ - private function loadTagsFromPhp($regexp, $files, $tags = []) + private function loadTagsFromPhp(string $regexp, array $files, array $tags = []): array { // Get all php files, so we can find all strings that need to be translated // Now find all tags in all php files. Only works for literal usage, not something like $foo = 'bar'; Dictionary::translate($foo); @@ -855,32 +853,28 @@ class Page_Translation extends Page /** * @param string $file Source dictionary - * @param string[]|false $requiredTags Tags that are considered required + * @param string[] $requiredTags Tags that are considered required * @param bool $findAlreadyTranslated If true, try to find a translation for this string in another language * @return array numeric array suitable for passing to mustache */ - private function buildTranslationTable($file, $requiredTags = false, $findAlreadyTranslated = false) + private function buildTranslationTable(string $file, array $requiredTags, bool $findAlreadyTranslated = false): array { $tags = array(); - if (is_array($requiredTags)) { - foreach ($requiredTags as $tagName) { - $tags[$tagName] = array('tag' => $tagName, 'required' => true); - } + foreach ($requiredTags as $tagName) { + $tags[$tagName] = array('tag' => $tagName, 'required' => true); } // Sort here, so all tags known to be used are in alphabetical order ksort($tags); // Finds every tag within the JSON language file $jsonTags = Dictionary::getArray($this->module->getIdentifier(), $file, $this->destLang); - if (is_array($jsonTags)) { - // Sort these separately so unused tags will be at the bottom of the list, but still ordered alphabetically - ksort($jsonTags); - foreach ($jsonTags as $tag => $translation) { - $tags[$tag]['translation'] = $translation; - if (strpos($translation, "\n") !== false) { - $tags[$tag]['big'] = true; - } - $tags[$tag]['tag'] = $tag; + // Sort these separately so unused tags will be at the bottom of the list, but still ordered alphabetically + ksort($jsonTags); + foreach ($jsonTags as $tag => $translation) { + $tags[$tag]['translation'] = $translation; + if (strpos($translation, "\n") !== false) { + $tags[$tag]['big'] = true; } + $tags[$tag]['tag'] = $tag; } if ($findAlreadyTranslated) { // For each tag, include a translated string from another language as reference @@ -894,17 +888,15 @@ class Page_Translation extends Page $tagid = 0; foreach ($tags as &$tag) { $tag['tagid'] = $tagid++; - if ($requiredTags !== false) { - // We have a list of required tags, so mark those that are missing or unused - if (!isset($tag['required'])) { - $tag['unused'] = true; - } elseif (!isset($tag['translation']) && !isset($globals[$tag['tag']])) { - $tag['missing'] = true; - } - if (isset($globals[$tag['tag']])) { - $tag['isglobal'] = true; - $tag['placeholder'] = $globals[$tag['tag']]; - } + // We have a list of required tags, so mark those that are missing or unused + if (!isset($tag['required'])) { + $tag['unused'] = true; + } elseif (!isset($tag['translation']) && !isset($globals[$tag['tag']])) { + $tag['missing'] = true; + } + if (isset($globals[$tag['tag']])) { + $tag['isglobal'] = true; + $tag['placeholder'] = $globals[$tag['tag']]; } } // Finally remove tagname from the keys so mustache will iterate over them via {{#..}} @@ -919,7 +911,7 @@ class Page_Translation extends Page * @param string $file translation unit * @param array $tags list of tags, formatted as used in buildTranslationTable() */ - private function findTranslationSamples($file, &$tags) + private function findTranslationSamples(string $file, array &$tags): void { $srcLangs = array_unique(array_merge(array(LANG), array('en'), Dictionary::getLanguages())); if (($key = array_search($this->destLang, $srcLangs)) !== false) { @@ -927,8 +919,6 @@ class Page_Translation extends Page } foreach ($srcLangs as $lang) { $otherLang = Dictionary::getArray($this->module->getIdentifier(), $file, $lang); - if (!is_array($otherLang)) - continue; $missing = false; foreach (array_keys($tags) as $tag) { if (isset($tags[$tag]['samplelang'])) @@ -945,7 +935,7 @@ class Page_Translation extends Page } } - private function getJsonFile() + private function getJsonFile(): string { $prefix = 'modules/' . $this->module->getIdentifier() . '/lang/' . $this->destLang; // File @@ -963,7 +953,7 @@ class Page_Translation extends Page } // Custom submodule if ($this->section === 'custom') { - if ($this->customHandler === false || !isset($this->customHandler['subsections'])) { + if ($this->customHandler === null || !isset($this->customHandler['subsections'])) { Message::addError('no-custom-handlers'); $this->redirect(1); } @@ -975,13 +965,12 @@ class Page_Translation extends Page } Message::addError('invalid-section', $this->section); $this->redirect(1); - return false; } /** * Updates a JSON file with it's new tags or/and tags values */ - private function updateJson() + private function updateJson(): void { $this->ensureValidDestLanguage(); if ($this->module === false) { diff --git a/modules-available/vmstore/baseconfig/getconfig.inc.php b/modules-available/vmstore/baseconfig/getconfig.inc.php index 3bad16e1..d239a3d7 100644 --- a/modules-available/vmstore/baseconfig/getconfig.inc.php +++ b/modules-available/vmstore/baseconfig/getconfig.inc.php @@ -1,5 +1,8 @@ <?php +/** @var ?string $uuid */ +/** @var ?string $ip */ + // VMStore path and type $vmstore = Property::getVmStoreConfig(); if (is_array($vmstore) && isset($vmstore['storetype'])) { @@ -21,6 +24,7 @@ if (is_array($vmstore) && isset($vmstore['storetype'])) { ConfigHolder::add("SLX_VM_NFS_OPTS", $vmstore['cifsopts']); } break; + default: } } diff --git a/modules-available/vmstore/inc/vmstorebenchmark.inc.php b/modules-available/vmstore/inc/vmstorebenchmark.inc.php index b13f4e37..b819ef8a 100644 --- a/modules-available/vmstore/inc/vmstorebenchmark.inc.php +++ b/modules-available/vmstore/inc/vmstorebenchmark.inc.php @@ -24,13 +24,12 @@ class VmStoreBenchmark } /** - * @param array $machineUuids * @param string $image relative path/name of image * @param string $serverOrMode IP address of DNBD3 server, OR 'auto' for all servers known to client, or 'nfs' for NFS * @param int $start timestamp when the clients should start * @return ?string taskId, or null on error */ - public static function start(string $id, array $machineUuids, string $image, string $serverOrMode, int &$start) + public static function start(string $id, array $machineUuids, string $image, string $serverOrMode, int &$start): ?string { Module::isAvailable('rebootcontrol'); $clients = Database::queryAll('SELECT machineuuid, clientip FROM machine WHERE machineuuid IN (:uuids)', @@ -68,6 +67,9 @@ COMMAND; return $task['id'] ?? null; } + /** + * @return array{cpu: array, net: array} + */ public static function parseBenchLine(string $line): array { $out = ['cpu' => [], 'net' => []]; diff --git a/modules-available/vmstore/page.inc.php b/modules-available/vmstore/page.inc.php index cf0487f1..b27d47ce 100644 --- a/modules-available/vmstore/page.inc.php +++ b/modules-available/vmstore/page.inc.php @@ -12,10 +12,10 @@ class Page_VmStore extends Page User::load(); if (User::hasPermission('edit')) { - Dashboard::addSubmenu('?do=vmstore', Dictionary::translate('menu_edit', true)); + Dashboard::addSubmenu('?do=vmstore', Dictionary::translate('menu_edit')); } if (User::hasPermission('benchmark')) { - Dashboard::addSubmenu('?do=vmstore&show=benchmark', Dictionary::translate('menu_benchmark', true)); + Dashboard::addSubmenu('?do=vmstore&show=benchmark', Dictionary::translate('menu_benchmark')); } if (Request::any('show') === 'benchmark') { @@ -71,12 +71,12 @@ class Page_VmStore extends Page Util::redirect('?do=VmStore'); } // Validate syntax of nfs/cifs - if ($storetype === 'nfs' && !preg_match('#^\S+:\S+$#is', $vmstore['nfsaddr'])) { + if ($storetype === 'nfs' && !preg_match('#^\S+:\S+$#i', $vmstore['nfsaddr'])) { Message::addError('main.value-invalid', 'nfsaddr', $vmstore['nfsaddr']); Util::redirect('?do=VmStore'); } $vmstore['cifsaddr'] = str_replace('\\', '/', $vmstore['cifsaddr']); - if ($storetype === 'cifs' && !preg_match('#^//\S+/.+$#is', $vmstore['cifsaddr'])) { + if ($storetype === 'cifs' && !preg_match('#^//\S+/.+$#i', $vmstore['cifsaddr'])) { Message::addError('main.value-invalid', 'nfsaddr', $vmstore['nfsaddr']); Util::redirect('?do=VmStore'); } @@ -91,7 +91,7 @@ class Page_VmStore extends Page if (!Module::isAvailable('rebootcontrol')) { ErrorHandler::traceError('rebootcontrol module not enabled'); } - Render::setTitle(Dictionary::translate('page-title-benchmark', true)); + Render::setTitle(Dictionary::translate('page-title-benchmark')); if (Request::post('action') === 'start') { $this->benchmarkActionStart(); } @@ -111,7 +111,7 @@ class Page_VmStore extends Page } } - private function getJobFromId(int $id) + private function getJobFromId(int $id): ?array { $data = Property::getListEntry(VmStoreBenchmark::PROP_LIST_KEY, $id); if ($data !== null) { @@ -202,7 +202,7 @@ class Page_VmStore extends Page $servers = []; if (Dnbd3::isEnabled()) { $servers[] = ['idx' => 'auto', - 'server' => Dictionary::translate('dnbd3-all-loadbalance', true)]; + 'server' => Dictionary::translate('dnbd3-all-loadbalance')]; foreach ($lookup as $ip => $idx) { $servers[] = ['idx' => $idx, 'server' => $ip]; } @@ -251,7 +251,7 @@ class Page_VmStore extends Page ]; if ($remaining > 0) { $args['remaining'] = $remaining; - $args['refresh'] = $refresh; + $args['refresh'] = $refresh ?? 60; } Module::isAvailable('js_chart'); Render::addTemplate('benchmark-result', $args); diff --git a/modules-available/webinterface/baseconfig/getconfig.inc.php b/modules-available/webinterface/baseconfig/getconfig.inc.php index 1bc5c1e3..53a5993c 100644 --- a/modules-available/webinterface/baseconfig/getconfig.inc.php +++ b/modules-available/webinterface/baseconfig/getconfig.inc.php @@ -1,5 +1,8 @@ <?php +/** @var ?string $uuid */ +/** @var ?string $ip */ + $file = '/opt/openslx/configs/modules/self-signed-ca.tar'; if (is_file($file) && is_readable($file)) { ConfigHolder::add('SLX_REMOTE_SSL', $_SERVER['SERVER_ADDR']); diff --git a/tools/convert-modules.php b/tools/convert-modules.php index aa43d951..1b92490d 100644 --- a/tools/convert-modules.php +++ b/tools/convert-modules.php @@ -78,7 +78,7 @@ foreach ( $exFile = "modules/$module/lang/$lang/template-tags.json"; $existing = @json_decode(@file_get_contents($exFile), true); if (!is_array($existing)) $existing = array(); - $existing = $existing + $old; + $existing += $old; ksort($existing); if (file_put_contents($exFile, json_encode($existing, JSON_PRETTY_PRINT)) > 0) { unlink($path); diff --git a/tools/jedec.php b/tools/jedec.php index a4df9667..1883abb9 100644 --- a/tools/jedec.php +++ b/tools/jedec.php @@ -13,11 +13,11 @@ $last = 0; $index = 1; $line = file_get_contents('jedec'); -preg_match_all("/^\s*([1-9][0-9]?|1[01][0-9]|12[0-6])\s+([^\r\n]{2,9}(?:[a-z][^\r\n]{0,10}){1,3}[\r\n]?[^\r\n0]{0,31})(?:\s*[\r\n]\s|\s+)((?:[10]\s+){8})([0-9a-f]{2})\s*\$/sim", $line, $oout, PREG_SET_ORDER); +preg_match_all("/^\s*([1-9][0-9]?|1[01][0-9]|12[0-6])\s+([^\r\n]{2,9}(?:[a-z][^\r\n]{0,10}){1,3}[\r\n]?[^\r\n0]{0,31})(?:\s*[\r\n]\s|\s+)((?:[10]\s+){8})([0-9a-f]{2})\s*\$/im", $line, $oout, PREG_SET_ORDER); $output = []; foreach ($oout as $out) { $id = (int)$out[1]; - $name = preg_replace("/[\s\r\n]+/ms", ' ', $out[2]); + $name = preg_replace("/[\s\r\n]+/m", ' ', $out[2]); $bin = $out[3]; $hex = $out[4]; if ($id < $last) { |