TYPO3 v15 dev-main snapshot ()

This commit is contained in:
2026-08-10 22:31:34 +02:00
commit 8a3bef5a34
61 changed files with 4603 additions and 0 deletions
+190
View File
@@ -0,0 +1,190 @@
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Reports\Service;
use Psr\Http\Message\ServerRequestInterface;
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Registry;
use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;
use TYPO3\CMS\Reports\ExtendedStatusProviderInterface;
use TYPO3\CMS\Reports\Registry\StatusRegistry;
use TYPO3\CMS\Reports\RequestAwareStatusProviderInterface;
use TYPO3\CMS\Reports\Status;
/**
* Service for collecting and processing system status information
*
* @internal This is not part of the public API and may change at any time
*/
#[Autoconfigure(public: true)]
final readonly class StatusService
{
public function __construct(
private StatusRegistry $statusRegistry,
private Registry $registry,
) {}
/**
* Runs through all status providers and returns all statuses collected.
*
* @param ServerRequestInterface|null $request
* @return Status[][]
*/
public function getSystemStatus(?ServerRequestInterface $request = null): array
{
$status = [];
foreach ($this->statusRegistry->getProviders() as $statusProvider) {
$statusProviderId = $statusProvider->getLabel();
$status[$statusProviderId] ??= [];
if ($statusProvider instanceof RequestAwareStatusProviderInterface) {
$statuses = $statusProvider->getStatus($request);
} else {
$statuses = $statusProvider->getStatus();
}
$status[$statusProviderId] = array_merge($status[$statusProviderId], $statuses);
}
return $status;
}
/**
* Runs through all status providers and returns all statuses collected, which are detailed.
*
* @return Status[][]
*/
public function getDetailedSystemStatus(): array
{
$status = [];
foreach ($this->statusRegistry->getProviders() as $statusProvider) {
$statusProviderId = $statusProvider->getLabel();
if ($statusProvider instanceof ExtendedStatusProviderInterface) {
$statuses = $statusProvider->getDetailedStatus();
$status[$statusProviderId] = array_merge($status[$statusProviderId] ?? [], $statuses);
}
}
return $status;
}
/**
* Determines the highest severity from the given statuses.
*
* @param array<string, array<string, Status>> $statusCollection An array of Status objects.
* @return int The highest severity found from the statuses.
*/
public function getHighestSeverity(array $statusCollection): int
{
$highestSeverity = ContextualFeedbackSeverity::NOTICE;
foreach ($statusCollection as $providerStatuses) {
foreach ($providerStatuses as $status) {
if ($status->getSeverity()->value > $highestSeverity->value) {
$highestSeverity = $status->getSeverity();
}
// Reached the highest severity level, no need to go on
if ($highestSeverity === ContextualFeedbackSeverity::ERROR) {
break;
}
}
}
return $highestSeverity->value;
}
/**
* Collects system status and stores the highest severity in the registry.
* This is useful for displaying warnings at login or in the backend.
*
* @param ServerRequestInterface|null $request
*/
public function collectAndStoreSystemStatus(?ServerRequestInterface $request = null): void
{
$status = $this->getSystemStatus($request);
$this->registry->set('tx_reports', 'status.highestSeverity', $this->getHighestSeverity($status));
}
/**
* Sorts the status providers (alphabetically and puts primary status providers at the beginning)
*
* @param array<string, array<string, Status>> $statusCollection A collection of statuses (with providers)
* @return array<string, array<string, Status>> The collection of statuses sorted by provider
*/
public function sortStatusProviders(array $statusCollection): array
{
$languageService = $this->getLanguageService();
// Extract the primary status collections, i.e. the status groups
// that must appear on top of the status report
// Change their keys to localized collection titles
$primaryStatuses = [
$languageService->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_typo3') => $statusCollection['typo3'] ?? [],
$languageService->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_system') => $statusCollection['system'] ?? [],
$languageService->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_security') => $statusCollection['security'] ?? [],
$languageService->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_configuration') => $statusCollection['configuration'] ?? [],
];
unset($statusCollection['typo3'], $statusCollection['system'], $statusCollection['security'], $statusCollection['configuration']);
// Assemble list of secondary status collections with left-over collections
// Change their keys using localized labels if available
$secondaryStatuses = [];
foreach ($statusCollection as $statusProviderId => $collection) {
if (str_starts_with($statusProviderId, 'LLL:')) {
// Label provided by extension
$label = $languageService->sL($statusProviderId);
} else {
// Generic label
// @todo phase this out
$label = $languageService->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_' . $statusProviderId);
}
$providerLabel = empty($label) ? $statusProviderId : $label;
$secondaryStatuses[$providerLabel] = $collection;
}
// Sort the secondary status collections alphabetically
ksort($secondaryStatuses);
return array_merge($primaryStatuses, $secondaryStatuses);
}
/**
* Sorts the statuses by severity
*
* @param array<string, Status> $statusCollection A collection of statuses per provider
* @return list<Status> The collection of statuses sorted by severity
*/
public function sortStatuses(array $statusCollection): array
{
$statuses = [];
$sortTitle = [];
$header = null;
foreach ($statusCollection as $status) {
if ($status->getTitle() === 'TYPO3') {
$header = $status;
continue;
}
$statuses[] = $status;
$sortTitle[] = $status->getSeverity();
}
array_multisort($sortTitle, SORT_DESC, $statuses);
// Making sure that the core version information is always on the top
if (is_object($header)) {
array_unshift($statuses, $header);
}
return $statuses;
}
private function getLanguageService(): LanguageService
{
return $GLOBALS['LANG'];
}
}