From 06bff0b9b84d47c43f9bc8aff06a29d85ebb7ed0 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 14 Nov 2023 14:47:55 +0100 Subject: Add function param/return types, fix a lot more phpstorm complaints --- inc/arrayutil.inc.php | 11 +------ inc/crypto.inc.php | 5 ++- inc/dashboard.inc.php | 33 +++++++++---------- inc/database.inc.php | 13 ++++---- inc/dictionary.inc.php | 72 +++++++++++++++++++---------------------- inc/download.inc.php | 13 ++++---- inc/errorhandler.inc.php | 11 ++++--- inc/event.inc.php | 4 +-- inc/fileutil.inc.php | 16 ++++----- inc/hook.inc.php | 12 +++---- inc/iputil.inc.php | 34 ++++++++++--------- inc/mailer.inc.php | 14 +++----- inc/message.inc.php | 35 ++++++++++---------- inc/module.inc.php | 63 ++++++++++++++++++------------------ inc/paginate.inc.php | 25 +++++++------- inc/permission.inc.php | 16 ++++----- inc/property.inc.php | 30 ++++++----------- inc/render.inc.php | 52 ++++++++++++++--------------- inc/request.inc.php | 4 +-- inc/session.inc.php | 20 ++++++------ inc/taskmanager.inc.php | 30 ++++++++--------- inc/taskmanagercallback.inc.php | 30 ++++++++--------- inc/trigger.inc.php | 22 ++++--------- inc/user.inc.php | 22 +++++++------ inc/util.inc.php | 41 ++++++++++++++--------- 25 files changed, 303 insertions(+), 325 deletions(-) (limited to 'inc') 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 - * @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 @@ $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 ' ', - (self::$dashboard !== false ? self::parse('main-menu', self::$dashboard, 'main') : ''), + (self::$dashboard !== null ? self::parse('main-menu', self::$dashboard, 'main') : ''), '
', 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 '

Template ' . htmlspecialchars($template) . '

' . nl2br(htmlspecialchars(print_r($params, true))) . '
'; } - 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 @@ 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 @@ 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'); + } } } -- cgit v1.2.3-55-g7522