f7cloud_client/apps/support/lib/Sections/PhpInfoSection.php
2026-03-05 13:40:40 +00:00

104 lines
2.9 KiB
PHP

<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Support\Sections;
use DOMDocument;
use DOMXPath;
use OCA\Support\IDetail;
use OCA\Support\Section;
class PhpInfoSection extends Section {
public function __construct(
) {
parent::__construct('phpinfo', 'Phpinfo');
}
#[\Override]
public function getDetails(): array {
ob_start();
phpinfo(INFO_CONFIGURATION | INFO_MODULES);
$phpinfo = ob_get_clean();
if ($phpinfo === false) {
$this->createDetail('error', 'Failed to retrieve phpinfo output.', IDetail::TYPE_SINGLE_LINE);
return parent::getDetails();
}
if (strpos($phpinfo, '<!DOCTYPE html>') === false) {
// If phpinfo output is not HTML, we dump the raw output
$this->createDetail('phpifo', $phpinfo, IDetail::TYPE_COLLAPSIBLE_PREFORMAT);
return parent::getDetails();
}
$parsedInfo = array_values($this->parsePhpInfoFromHtml($phpinfo))[0] ?? [];
foreach ($parsedInfo as $sectionName => $sectionData) {
$this->createDetail($sectionName, json_encode($sectionData, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES), IDetail::TYPE_COLLAPSIBLE_PREFORMAT);
}
return parent::getDetails();
}
private function parsePhpInfoFromHtml(string $phpInfoHtmlStr): array {
$dom = new DOMDocument();
libxml_use_internal_errors(true);
$dom->loadHTML($phpInfoHtmlStr, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
libxml_clear_errors();
$xpath = new DOMXPath($dom);
$result = [];
$currentSection = '';
$currentSubsection = '';
$elements = $xpath->query('//h1 | //h2 | //table');
foreach ($elements as $el) {
if ($el->nodeName === 'h1') {
$currentSection = trim($el->textContent);
$result[$currentSection] = [];
} elseif ($el->nodeName === 'h2') {
$currentSubsection = trim($el->textContent);
if (!isset($result[$currentSection][$currentSubsection])) {
$result[$currentSection][$currentSubsection] = [];
}
} elseif ($el->nodeName === 'table') {
$rows = $el->getElementsByTagName('tr');
foreach ($rows as $row) {
$cols = $row->getElementsByTagName('td');
$ths = $row->getElementsByTagName('th');
if ($cols->length === 2) {
// Single key => value
$key = trim($cols->item(0)->textContent);
$val = trim($cols->item(1)->textContent);
$result[$currentSection][$currentSubsection][$key] = $val;
} elseif ($cols->length === 3) {
// Directive with local/master value
$key = trim($cols->item(0)->textContent);
$local = trim($cols->item(1)->textContent);
$master = trim($cols->item(2)->textContent);
$result[$currentSection][$currentSubsection][$key] = [
'local' => $local,
'master' => $master,
];
} elseif ($ths->length > 0) {
// This is a header row; skip or save metadata
continue;
}
}
}
}
return $result;
}
}