Commit 1f6d09cc authored by Christian Kuhn's avatar Christian Kuhn
Browse files

[TASK] Modernize ext:lowlevel view

This is a partial refactoring of ext:lowlevel. There
are some loose ends like HTML in the searchAction()
and some other details. Those might be target of a
bigger refactoring. However, the patch cleans up
controller and view and improves separation of
concerns already:

* Rename mainAction() to handleRequest()
* Use BackendTemplateView
* Hand over template to render as view->render('MyTemplate')
* Use DI in related controllers
* Switch from a ServiceProvider.php to casual Services.yaml
* Declare strict_types=1
* Return and property types in PHP classes
* PageRenderer JS module loading via fluid, not PHP
* f:translate with full LLL: keys

Change-Id: I0afe0938990f145e77aedd131f366226142382f3
Resolves: #96530
Related: #96513
Releases: main
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/73007

Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Stefan Bürk's avatarStefan Bürk <stefan@buerk.tech>
Tested-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Stefan Bürk's avatarStefan Bürk <stefan@buerk.tech>
Reviewed-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
parent 73e8bed8
......@@ -106,17 +106,18 @@ class DbCheckModuleCest
$this->goToPageAndSeeHeadline($I, 'Manage Reference Index', 'Manage Reference Index');
$I->click('Check reference index');
$I->waitForElement('.alert');
$I->waitForElement('.callout-warning');
$I->click('Update reference index');
$I->waitForElement('.alert');
$I->waitForElement('.callout-warning');
$I->click('Check reference index');
$I->waitForElement('.alert-success');
$I->see('Index Integrity was perfect!', '.alert-success');
$I->waitForElement('.callout-success');
$I->see('Index integrity was perfect!', '.callout-success');
$I->click('Update reference index');
$I->see('Index Integrity was perfect!', '.alert-success');
$I->waitForElement('.callout-success');
$I->see('Index integrity was perfect!', '.callout-success');
}
/**
......
......@@ -25,9 +25,8 @@ use TYPO3\CMS\Backend\View\ArrayBrowser;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Http\HtmlResponse;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Fluid\View\StandaloneView;
use TYPO3\CMS\Fluid\View\BackendTemplateView;
use TYPO3\CMS\Lowlevel\ConfigurationModuleProvider\ProviderRegistry;
/**
......@@ -37,18 +36,15 @@ use TYPO3\CMS\Lowlevel\ConfigurationModuleProvider\ProviderRegistry;
class ConfigurationController
{
protected ProviderRegistry $configurationProviderRegistry;
protected PageRenderer $pageRenderer;
protected UriBuilder $uriBuilder;
protected ModuleTemplateFactory $moduleTemplateFactory;
public function __construct(
ProviderRegistry $configurationProviderRegistry,
PageRenderer $pageRenderer,
UriBuilder $uriBuilder,
ModuleTemplateFactory $moduleTemplateFactory
) {
$this->configurationProviderRegistry = $configurationProviderRegistry;
$this->pageRenderer = $pageRenderer;
$this->uriBuilder = $uriBuilder;
$this->moduleTemplateFactory = $moduleTemplateFactory;
}
......@@ -62,7 +58,7 @@ class ConfigurationController
* @return ResponseInterface the response with the content
* @throws \RuntimeException
*/
public function mainAction(ServerRequestInterface $request): ResponseInterface
public function handleRequest(ServerRequestInterface $request): ResponseInterface
{
$moduleTemplate = $this->moduleTemplateFactory->create($request);
$backendUser = $this->getBackendUser();
......@@ -113,11 +109,8 @@ class ConfigurationController
$backendUser->writeUC();
// Render main body
$view = GeneralUtility::makeInstance(StandaloneView::class);
$view->getRequest()->setControllerExtensionName('lowlevel');
$view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName(
'EXT:lowlevel/Resources/Private/Templates/Backend/Configuration.html'
));
$view = GeneralUtility::makeInstance(BackendTemplateView::class);
$view->setTemplateRootPaths(['EXT:lowlevel/Resources/Private/Templates']);
$view->assignMultiple([
'treeName' => $configurationProvider->getLabel(),
'searchString' => $searchString,
......@@ -126,8 +119,7 @@ class ConfigurationController
]);
// Prepare module setup
$moduleTemplate->setContent($view->render());
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Lowlevel/ConfigurationView');
$moduleTemplate->setContent($view->render('Configuration'));
// Shortcut in doc header
$shortcutButton = $moduleTemplate->getDocHeaderComponent()->getButtonBar()->makeShortcutButton();
......@@ -163,20 +155,12 @@ class ConfigurationController
return new HtmlResponse($moduleTemplate->renderContent());
}
/**
* Returns the Backend User
* @return BackendUserAuthentication
*/
protected function getBackendUser(): BackendUserAuthentication
{
return $GLOBALS['BE_USER'];
}
/**
* Returns the Language Service
* @return LanguageService
*/
protected function getLanguageService()
protected function getLanguageService(): LanguageService
{
return $GLOBALS['LANG'];
}
......
......@@ -34,8 +34,8 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
* @TODO: updated and the whole API is better defined. There are some known bugs
* @TODO: in this library. Further it would be nice with a facility to not only
* @TODO: analyze but also clean up!
* @see \TYPO3\CMS\Lowlevel\Controller\DatabaseIntegrityController::func_relations()
* @see \TYPO3\CMS\Lowlevel\Controller\DatabaseIntegrityController::func_records()
* @see \TYPO3\CMS\Lowlevel\Controller\DatabaseIntegrityController::relationsAction()
* @see \TYPO3\CMS\Lowlevel\Controller\DatabaseIntegrityController::recordStatisticsAction()
*/
class DatabaseIntegrityCheck
{
......
<?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\Lowlevel;
use Psr\Container\ContainerInterface;
use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Backend\Template\ModuleTemplateFactory;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Package\AbstractServiceProvider;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Lowlevel\ConfigurationModuleProvider\ProviderRegistry;
/**
* @internal
*/
class ServiceProvider extends AbstractServiceProvider
{
protected static function getPackagePath(): string
{
return __DIR__ . '/../';
}
public function getFactories(): array
{
return [
Controller\ConfigurationController::class => [ static::class, 'getConfigurationController' ],
Controller\DatabaseIntegrityController::class => [ static::class, 'getDatabaseIntegrityController' ],
];
}
public static function getConfigurationController(ContainerInterface $container): Controller\ConfigurationController
{
return self::new(
$container,
Controller\ConfigurationController::class,
[
$container->get(ProviderRegistry::class),
$container->get(PageRenderer::class),
$container->get(UriBuilder::class),
$container->get(ModuleTemplateFactory::class),
]
);
}
public static function getDatabaseIntegrityController(ContainerInterface $container): Controller\DatabaseIntegrityController
{
return self::new(
$container,
Controller\DatabaseIntegrityController::class,
[
$container->get(IconFactory::class),
$container->get(PageRenderer::class),
$container->get(UriBuilder::class),
$container->get(ModuleTemplateFactory::class),
]
);
}
}
......@@ -7,6 +7,11 @@ services:
TYPO3\CMS\Lowlevel\:
resource: '../Classes/*'
TYPO3\CMS\Lowlevel\Controller\ConfigurationController:
tags: ['backend.controller']
TYPO3\CMS\Lowlevel\Controller\DatabaseIntegrityController:
tags: ['backend.controller']
TYPO3\CMS\Lowlevel\Command\ListSysLogCommand:
tags:
- name: 'console.command'
......
......@@ -306,6 +306,9 @@
<trans-unit id="refindex_description" resname="refindex_description">
<source>Allows you to maintain the reference index kept by TYPO3.</source>
</trans-unit>
<trans-unit id="refindex_ok" resname="refindex_ok">
<source>Index integrity was perfect!</source>
</trans-unit>
<trans-unit id="title" resname="title">
<source>Database integrity check</source>
</trans-unit>
......
<h1>{f:translate(key:'search_whole_database')}</h1>
<f:format.raw>{submenu}</f:format.raw>
<f:if condition="{searchMode} == 'query'">
<f:then>
<f:format.raw>{queryMaker}</f:format.raw>
</f:then>
<f:else>
<h2>{f:translate(key:'searchOptions')}</h2>
<f:format.raw>{searchOptions}</f:format.raw>
<h2>{f:translate(key:'result')}</h2>
<f:format.raw>{results}</f:format.raw>
</f:else>
</f:if>
<h1>{f:translate(key:'manageRefIndex')}</h1>
<p class="lead">{f:translate(key:'referenceIndex_description')}</p>
<f:format.raw>{content}</f:format.raw>
<div class="t3js-reference-index-actions">
<button type="submit" class="btn btn-default" name="_check" value="1">
{f:translate(key:'referenceIndex_buttonCheck')}
</button>
<button type="submit" class="btn btn-default" name="_update" value="1">
{f:translate(key:'referenceIndex_buttonUpdate')}
</button>
</div><br /><br />
<h2>{f:translate(key:'checkScript_headline')}</h2>
<p>{f:translate(key:'checkScript')}</p>
<h3>{f:translate(key:'checkScript_check_description')}</h3>
<p>
<code>php {binaryPath} referenceindex:update -c</code>
</p>
<h3>{f:translate(key:'checkScript_update_description')}</h3>
<p>
<code>php {binaryPath} referenceindex:update</code>
</p>
<p>
{f:translate(key:'checkScript_moreDetails')}<br>
<a href="{ReadmeLink}" target="_new">{ReadmeLocation}</a>
</p>
<h1>{f:translate(key:'relations')}</h1>
<h2>{f:translate(key:'select_db')}</h2>
<f:format.raw>{select_db}</f:format.raw>
<h2>{f:translate(key:'group_db')}</h2>
<f:format.raw>{group_db}</f:format.raw>
<html
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers"
data-namespace-typo3-fluid="true"
>
<f:be.pageRenderer
includeRequireJsModules="{
0: 'TYPO3/CMS/Lowlevel/ConfigurationView'
}"
/>
<form action="" id="ConfigurationView" method="post">
<h1><f:translate key="configuration" /></h1>
<h1><f:translate key="LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:configuration" /></h1>
<h2>{treeName}</h2>
......@@ -11,14 +21,14 @@
</button>
<label for="lowlevel-searchString" class="visually-hidden">
<f:translate key="enterSearchPhrase"/>
<f:translate key="LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:enterSearchPhrase"/>
</label>
<input class="form-control"
type="search"
id="lowlevel-searchString"
name="searchString"
value="{searchString}"
placeholder="{f:translate(key: 'enterSearchPhrase')}"
placeholder="{f:translate(key: 'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:enterSearchPhrase')}"
/>
<button class="btn btn-default dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false"></button>
......@@ -35,7 +45,7 @@
{f:if(condition:'{regexSearch}', then: ' checked')}
/>
<label for="lowlevel-regexSearch" class="form-check-label">
<f:translate key="useRegExp" />
<f:translate key="LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:useRegExp" />
</label>
</div>
</div>
......@@ -58,3 +68,4 @@
<f:format.raw>{tree}</f:format.raw>
</div>
</form>
</html>
<html
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
data-namespace-typo3-fluid="true"
>
<f:if condition="{searchMode} == 'query'">
<f:be.pageRenderer
includeRequireJsModules="{
0: 'TYPO3/CMS/Lowlevel/QueryGenerator'
}"
/>
</f:if>
<h1>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:search_whole_database')}</h1>
<f:format.raw>{submenu}</f:format.raw>
<form action="" method="post" id="DatabaseIntegrityView" name="queryform">
<f:if condition="{searchMode} == 'query'">
<f:then>
<f:format.raw>{queryMaker}</f:format.raw>
</f:then>
<f:else>
<h2>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:searchOptions')}</h2>
<f:format.raw>{searchOptions}</f:format.raw>
<h2>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:result')}</h2>
<f:format.raw>{results}</f:format.raw>
</f:else>
</f:if>
</form>
</html>
<h1>{f:translate(key:'title')}</h1>
<html
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers"
data-namespace-typo3-fluid="true"
>
<h1>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:title')}</h1>
<dl class="t3-overview-list">
<f:for each="{availableFunctions}" as="url" key="name">
<dt>
<a href="{url}">
<core:icon identifier="module-dbint" size="small" /> {f:translate(key: name)}
<core:icon identifier="module-dbint" size="small" /> {f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:{name}')}
</a>
</dt>
<dd>{f:translate(key:'{name}_description')}</dd>
<dd>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:{name}_description')}</dd>
</f:for>
</dl>
</html>
<h1>{f:translate(key:'records')}</h1>
<html
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
data-namespace-typo3-fluid="true"
>
<h1>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:records')}</h1>
<h2>{f:translate(key:'pages')}</h2>
<h2>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:pages')}</h2>
<table class="table table-striped table-hover">
<colgroup>
<col width="24">
......@@ -10,21 +14,21 @@
<thead>
<tr>
<th colspan="2"></th>
<th>{f:translate(key:'count')}</th>
<th>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:count')}</th>
</tr>
</thead>
<tbody>
<f:for each="{pages}" as="item" key="name">
<tr>
<td><f:format.raw>{item.icon}</f:format.raw></td>
<td>{f:translate(key:'{name}')}</td>
<td>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:{name}')}</td>
<td>{item.count}</td>
</tr>
</f:for>
</tbody>
</table>
<h2>{f:translate(key:'doktype')}</h2>
<h2>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:doktype')}</h2>
<table class="table table-striped table-hover">
<colgroup>
<col width="24">
......@@ -34,8 +38,8 @@
<thead>
<tr>
<th></th>
<th>{f:translate(key:'doktype_value')}</th>
<th>{f:translate(key:'count')}</th>
<th>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:doktype_value')}</th>
<th>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:count')}</th>
</tr>
</thead>
<tbody>
......@@ -49,7 +53,7 @@
</tbody>
</table>
<h2>{f:translate(key:'tables')}</h2>
<h2>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:tables')}</h2>
<table class="table table-striped table-hover">
<colgroup>
<col width="24">
......@@ -59,9 +63,9 @@
<thead>
<tr>
<th></th>
<th>{f:translate(key:'label')}</th>
<th>{f:translate(key:'tablename')}</th>
<th>{f:translate(key:'total_lost')}</th>
<th>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:label')}</th>
<th>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:tablename')}</th>
<th>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:total_lost')}</th>
<th></th>
</tr>
</thead>
......@@ -77,3 +81,4 @@
</f:for>
</tbody>
</table>
</html>
<html
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
data-namespace-typo3-fluid="true"
>
<f:be.pageRenderer
includeRequireJsModules="{
0: 'TYPO3/CMS/Lowlevel/ReferenceIndex'
}"
/>
<h1>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:manageRefIndex')}</h1>
<p class="lead">{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:referenceIndex_description')}</p>
<f:if condition="{referenceIndexResult}">
<f:be.infobox state="{f:if(condition:'{referenceIndexResult.errors}', then:'1', else:'0')}" title="{referenceIndexResult.resultText}">
<f:if condition="{referenceIndexResult.errors}">
<f:then>
<f:for each="{referenceIndexResult.errors}" as="error">
{error}<br/>
</f:for>
</f:then>
<f:else>
<f:translate key="LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:refindex_ok"/>
</f:else>
</f:if>
</f:be.infobox>
</f:if>
<form action="" method="post" id="DatabaseIntegrityView" name="queryform">
<div class="t3js-reference-index-actions">
<button type="submit" class="btn btn-default" name="checkOnly" value="1">
{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:referenceIndex_buttonCheck')}
</button>
<button type="submit" class="btn btn-default" name="update" value="1">
{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:referenceIndex_buttonUpdate')}
</button>
</div>
</form>
<h2>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:checkScript_headline')}</h2>
<p>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:checkScript')}</p>
<h3>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:checkScript_check_description')}</h3>
<p>
<code>php {binaryPath} referenceindex:update -c</code>
</p>
<h3>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:checkScript_update_description')}</h3>
<p>
<code>php {binaryPath} referenceindex:update</code>
</p>
<h2>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:checkScript_moreDetails')}</h2>
<p>
<a href="{ReadmeLink}" target="_new">{ReadmeLocation}</a>
</p>
</html>
<html
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
data-namespace-typo3-fluid="true"
>
<h1>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:relations')}</h1>
<h2>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:select_db')}</h2>
<f:format.raw>{select_db}</f:format.raw>
<h2>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:group_db')}</h2>
<f:format.raw>{group_db}</f:format.raw>
</html>
......@@ -30,7 +30,6 @@
},
"typo3/cms": {
"Package": {
"serviceProvider": "TYPO3\\CMS\\Lowlevel\\ServiceProvider",
"partOfFactoryDefault": true
},
"extension-key": "lowlevel"
......
......@@ -14,7 +14,7 @@ ExtensionManagementUtility::addModule(
'',
'',
[
'routeTarget' => DatabaseIntegrityController::class . '::mainAction',
'routeTarget' => DatabaseIntegrityController::class . '::handleRequest',
'access' => 'admin',
'name' => 'system_dbint',
'workspaces' => 'online',
......@@ -28,7 +28,7 @@ ExtensionManagementUtility::addModule(
'',
'',
[
'routeTarget' => ConfigurationController::class . '::mainAction',
'routeTarget' => ConfigurationController::class . '::handleRequest',
'access' => 'admin',
'name' => 'system_config',
'workspaces' => 'online',
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment