diff --git a/libraries/classes/Server/SysInfo/WindowsNt.php b/libraries/classes/Server/SysInfo/WindowsNt.php index f16b3494a6..fcd06d6e0d 100644 --- a/libraries/classes/Server/SysInfo/WindowsNt.php +++ b/libraries/classes/Server/SysInfo/WindowsNt.php @@ -4,21 +4,21 @@ declare(strict_types=1); namespace PhpMyAdmin\Server\SysInfo; -use COM; +use com; +use Throwable; +use function array_merge; use function class_exists; -use function count; -use function in_array; -use function is_string; -use function trim; +use function intdiv; +use function intval; /** * Windows NT based SysInfo class */ class WindowsNt extends Base { - /** @var COM|null */ - private $wmi; + /** @var object|null */ + private $wmiService = null; /** * The OS name @@ -32,15 +32,18 @@ class WindowsNt extends Base */ public function __construct() { - if (! class_exists('COM')) { - $this->wmi = null; - + if (! class_exists('com')) { return; } - // initialize the wmi object - $objLocator = new COM('WbemScripting.SWbemLocator'); - $this->wmi = $objLocator->ConnectServer(); + /** + * @see https://www.php.net/manual/en/class.com.php + * @see https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemlocator + * @see https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemservices + * + * @psalm-suppress MixedAssignment, UndefinedMagicMethod + */ + $this->wmiService = (new com('WbemScripting.SWbemLocator'))->ConnectServer(); } /** @@ -50,15 +53,7 @@ class WindowsNt extends Base */ public function loadavg() { - $sum = 0; - $buffer = $this->getWMI('Win32_Processor', ['LoadPercentage']); - - foreach ($buffer as $load) { - $value = $load['LoadPercentage']; - $sum += $value; - } - - return ['loadavg' => $sum / count($buffer)]; + return ['loadavg' => $this->getLoadPercentage()]; } /** @@ -66,46 +61,7 @@ class WindowsNt extends Base */ public function supported(): bool { - return $this->wmi !== null; - } - - /** - * Reads data from WMI - * - * @param string $strClass Class to read - * @param array $strValue Values to read - * - * @return array with results - */ - private function getWMI($strClass, array $strValue = []) - { - $arrData = []; - - $objWEBM = $this->wmi->Get($strClass); - // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps - $arrProp = $objWEBM->Properties_; - $arrWEBMCol = $objWEBM->Instances_(); - foreach ($arrWEBMCol as $objItem) { - $arrInstance = []; - foreach ($arrProp as $propItem) { - // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps - $name = $propItem->Name; - if (! empty($strValue) && ! in_array($name, $strValue)) { - continue; - } - - $value = $objItem->$name; - if (is_string($value)) { - $arrInstance[$name] = trim($value); - } else { - $arrInstance[$name] = $value; - } - } - - $arrData[] = $arrInstance; - } - - return $arrData; + return $this->wmiService !== null; } /** @@ -115,33 +71,101 @@ class WindowsNt extends Base */ public function memory() { - $buffer = $this->getWMI( - 'Win32_OperatingSystem', - [ - 'TotalVisibleMemorySize', - 'FreePhysicalMemory', - ] - ); - $mem = []; - $mem['MemTotal'] = $buffer[0]['TotalVisibleMemorySize']; - $mem['MemFree'] = $buffer[0]['FreePhysicalMemory']; - $mem['MemUsed'] = $mem['MemTotal'] - $mem['MemFree']; + return array_merge($this->getSystemMemory(), $this->getPageFileUsage()); + } - $buffer = $this->getWMI('Win32_PageFileUsage'); - - $mem['SwapTotal'] = 0; - $mem['SwapFree'] = 0; - $mem['SwapUsed'] = 0; - $mem['SwapPeak'] = 0; - - foreach ($buffer as $swapdevice) { - $mem['SwapTotal'] += $swapdevice['AllocatedBaseSize'] * 1024; - $mem['SwapUsed'] += $swapdevice['CurrentUsage'] * 1024; - $mem['SwapPeak'] += $swapdevice['PeakUsage'] * 1024; + /** + * @return array + * @psalm-return array{MemTotal: int, MemFree: int, MemUsed: int} + */ + private function getSystemMemory(): array + { + if ($this->wmiService === null) { + return ['MemTotal' => 0, 'MemFree' => 0, 'MemUsed' => 0]; } - $mem['SwapFree'] = $mem['SwapTotal'] - $mem['SwapUsed']; + /** + * @see https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemobject-instances- + * @see https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-operatingsystem + * + * @var object[] $instances + * @psalm-suppress MixedMethodCall + * @phpstan-ignore-next-line + */ + $instances = $this->wmiService->Get('Win32_OperatingSystem')->Instances_(); + $totalMemory = 0; + $freeMemory = 0; + foreach ($instances as $instance) { + // phpcs:disable Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps + $totalMemory += (int) $instance->TotalVisibleMemorySize; /* @phpstan-ignore-line */ + $freeMemory += (int) $instance->FreePhysicalMemory; /* @phpstan-ignore-line */ + // phpcs:enable + } - return $mem; + return ['MemTotal' => $totalMemory, 'MemFree' => $freeMemory, 'MemUsed' => $totalMemory - $freeMemory]; + } + + /** + * @return array + * @psalm-return array{SwapTotal: int, SwapUsed: int, SwapPeak: int, SwapFree: int} + */ + private function getPageFileUsage(): array + { + if ($this->wmiService === null) { + return ['SwapTotal' => 0, 'SwapUsed' => 0, 'SwapPeak' => 0, 'SwapFree' => 0]; + } + + /** + * @see https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemobject-instances- + * @see https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-pagefileusage + * + * @var object[] $instances + * @psalm-suppress MixedMethodCall + * @phpstan-ignore-next-line + */ + $instances = $this->wmiService->Get('Win32_PageFileUsage')->Instances_(); + $total = 0; + $used = 0; + $peak = 0; + foreach ($instances as $instance) { + // phpcs:disable Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps + $total += intval($instance->AllocatedBaseSize) * 1024; /* @phpstan-ignore-line */ + $used += intval($instance->CurrentUsage) * 1024; /* @phpstan-ignore-line */ + $peak += intval($instance->PeakUsage) * 1024; /* @phpstan-ignore-line */ + // phpcs:enable + } + + return ['SwapTotal' => $total, 'SwapUsed' => $used, 'SwapPeak' => $peak, 'SwapFree' => $total - $used]; + } + + private function getLoadPercentage(): int + { + if ($this->wmiService === null) { + return 0; + } + + /** + * @see https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemobject-instances- + * @see https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-processor + * + * @var object[] $instances + * @psalm-suppress MixedMethodCall + * @phpstan-ignore-next-line + */ + $instances = $this->wmiService->Get('Win32_Processor')->Instances_(); + $i = 0; + $sum = 0; + foreach ($instances as $instance) { + // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps + $sum += (int) $instance->LoadPercentage; /* @phpstan-ignore-line */ + // Can't use count($instances). + $i++; + } + + try { + return intdiv($sum, $i); + } catch (Throwable $throwable) { + return 0; + } } } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index a4be71f9a9..7a4bc3536d 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -7335,21 +7335,6 @@ parameters: count: 1 path: libraries/classes/Server/SysInfo/WindowsNt.php - - - message: "#^Cannot call method Get\\(\\) on COM\\|null\\.$#" - count: 1 - path: libraries/classes/Server/SysInfo/WindowsNt.php - - - - message: "#^Method PhpMyAdmin\\\\Server\\\\SysInfo\\\\WindowsNt\\:\\:getWMI\\(\\) has parameter \\$strValue with no value type specified in iterable type array\\.$#" - count: 1 - path: libraries/classes/Server/SysInfo/WindowsNt.php - - - - message: "#^Method PhpMyAdmin\\\\Server\\\\SysInfo\\\\WindowsNt\\:\\:getWMI\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: libraries/classes/Server/SysInfo/WindowsNt.php - - message: "#^Method PhpMyAdmin\\\\Server\\\\SysInfo\\\\WindowsNt\\:\\:loadavg\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 diff --git a/psalm-baseline.xml b/psalm-baseline.xml index fa0687f8ca..c6a166cf31 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -2755,8 +2755,7 @@ $GLOBALS['sql_query'] - - $GLOBALS['db'] + $GLOBALS['message'] $GLOBALS['password'] ?? '' $GLOBALS['password'] ?? null @@ -2772,9 +2771,8 @@ $GLOBALS['queries'] - + $GLOBALS['_add_user_error'] - $GLOBALS['db'] $GLOBALS['db_and_table'] $GLOBALS['dbname'] $GLOBALS['dbname_is_wildcard'] @@ -2802,7 +2800,6 @@ $GLOBALS['tooltip_truename'] $GLOBALS['total_num_tables'] $GLOBALS['url_dbname'] - $_REQUEST['db'] $db_name @@ -6704,7 +6701,7 @@ $params - + $info $params['single_table'] $subObject @@ -12803,66 +12800,6 @@ $params['sort_order'] - - - $buffer[0]['FreePhysicalMemory'] - $buffer[0]['TotalVisibleMemorySize'] - $load['LoadPercentage'] - $swapdevice['AllocatedBaseSize'] - $swapdevice['CurrentUsage'] - $swapdevice['PeakUsage'] - - - $arrInstance[$name] - $arrInstance[$name] - - - $arrInstance[$name] - $arrProp - $arrWEBMCol - $load - $mem['MemFree'] - $mem['MemTotal'] - $mem['MemUsed'] - $mem['SwapPeak'] - $mem['SwapTotal'] - $mem['SwapUsed'] - $name - $objItem - $objLocator - $objWEBM - $propItem - $sum - $swapdevice - $this->wmi - $value - $value - - - ConnectServer - Instances_ - - - $mem['MemTotal'] - $sum - $swapdevice['AllocatedBaseSize'] - $swapdevice['CurrentUsage'] - $swapdevice['PeakUsage'] - $value - - - $objItem->$name - $objWEBM->Properties_ - $propItem->Name - - - Get - - - $this->wmi - COM|null - - $config->getCookie('phpMyAdmin')