summaryrefslogtreecommitdiffstats
path: root/inc
diff options
context:
space:
mode:
authorSimon Rettberg2023-11-14 14:47:55 +0100
committerSimon Rettberg2023-11-14 14:47:55 +0100
commit06bff0b9b84d47c43f9bc8aff06a29d85ebb7ed0 (patch)
tree7e5493b102074672d8cfd8fe1a61e49f080edbe8 /inc
parentUpdate phpstorm config (diff)
downloadslx-admin-06bff0b9b84d47c43f9bc8aff06a29d85ebb7ed0.tar.gz
slx-admin-06bff0b9b84d47c43f9bc8aff06a29d85ebb7ed0.tar.xz
slx-admin-06bff0b9b84d47c43f9bc8aff06a29d85ebb7ed0.zip
Add function param/return types, fix a lot more phpstorm complaints
Diffstat (limited to 'inc')
-rw-r--r--inc/arrayutil.inc.php11
-rw-r--r--inc/crypto.inc.php5
-rw-r--r--inc/dashboard.inc.php33
-rw-r--r--inc/database.inc.php13
-rw-r--r--inc/dictionary.inc.php72
-rw-r--r--inc/download.inc.php13
-rw-r--r--inc/errorhandler.inc.php11
-rw-r--r--inc/event.inc.php4
-rw-r--r--inc/fileutil.inc.php16
-rw-r--r--inc/hook.inc.php12
-rw-r--r--inc/iputil.inc.php34
-rw-r--r--inc/mailer.inc.php14
-rw-r--r--inc/message.inc.php35
-rw-r--r--inc/module.inc.php63
-rw-r--r--inc/paginate.inc.php25
-rw-r--r--inc/permission.inc.php16
-rw-r--r--inc/property.inc.php30
-rw-r--r--inc/render.inc.php52
-rw-r--r--inc/request.inc.php4
-rw-r--r--inc/session.inc.php20
-rw-r--r--inc/taskmanager.inc.php30
-rw-r--r--inc/taskmanagercallback.inc.php30
-rw-r--r--inc/trigger.inc.php22
-rw-r--r--inc/user.inc.php22
-rw-r--r--inc/util.inc.php41
25 files changed, 303 insertions, 325 deletions
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');
+ }
}
}