Skip to content

Commit

Permalink
[TASK] Avoid last usage of BU::getFuncCheck() and deprecate
Browse files Browse the repository at this point in the history
Resolves: #99579
Releases: main
Change-Id: If8aa4864656da59e328076c9240fcd31e5eba16c
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/77425
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Stefan Bürk <stefan@buerk.tech>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: core-ci <typo3@b13.com>
Tested-by: Stefan Bürk <stefan@buerk.tech>
  • Loading branch information
maddy2101 authored and lolli42 committed Jan 18, 2023
1 parent 85bb087 commit 42a4c03
Show file tree
Hide file tree
Showing 12 changed files with 333 additions and 44 deletions.
31 changes: 13 additions & 18 deletions typo3/sysext/backend/Classes/Controller/RecordListController.php
Expand Up @@ -180,9 +180,9 @@ public function mainAction(ServerRequestInterface $request): ResponseInterface
if (!($this->modTSconfig['disableSearchBox'] ?? false) && ($tableListHtml || !empty($search_field))) {
$searchBoxHtml = $this->renderSearchBox($request, $view, $dbList, $search_field, $search_levels);
}
$toggleClipboardHtml = '';
$renderToggleClipBoard = false;
if ($tableListHtml && ($this->modTSconfig['enableClipBoard'] ?? '') === 'selectable') {
$toggleClipboardHtml = $this->renderToggleClipboardHtml($this->id, $singleTable, $clipboardEnabled);
$renderToggleClipBoard = true;
}
$clipboardHtml = '';
if ($clipboardEnabled && ($tableListHtml || $clipboard->hasElements())) {
Expand All @@ -197,6 +197,12 @@ public function mainAction(ServerRequestInterface $request): ResponseInterface
$view->getDocHeaderComponent()->setMetaInformation($pageinfo);
}
$this->getDocHeaderButtons($view, $clipboard, $queryParams, $singleTable, $dbList->listURL(), []);
$route = $request->getAttribute('route');
$params = ['id' => $this->id];
if ($singleTable) {
$params['table'] = $singleTable;
}
$url = $this->uriBuilder->buildUriFromRoute($route->getOption('_identifier'), $params) . '&clipBoard=${value}';
$view->assignMultiple([
'pageId' => $this->id,
'pageTitle' => $title,
Expand All @@ -207,7 +213,11 @@ public function mainAction(ServerRequestInterface $request): ResponseInterface
'pageTranslationsHtml' => $pageTranslationsHtml,
'searchBoxHtml' => $searchBoxHtml,
'tableListHtml' => $tableListHtml,
'toggleClipboardHtml' => $toggleClipboardHtml,
'displayToggleClipboard' => $renderToggleClipBoard,
'toggleClipboardName' => 'clipBoard',
'toggleClipboardId' => 'checkShowClipBoard',
'toggleClipboardChecked' => $clipboardEnabled ? ' checked="checked"' : '',
'toggleClipboardFormUrl' => $url,
'clipboardHtml' => $clipboardHtml,
'additionalContentBottom' => $additionalRecordListEvent->getAdditionalContentBelow(),
]);
Expand Down Expand Up @@ -588,21 +598,6 @@ protected function renderPageTranslations(DatabaseRecordList $dbList, array $sit
return $pageTranslationsDatabaseRecordList->getTable('pages');
}

public function renderToggleClipboardHtml(int $pageId, string $singleTable, bool $checked): string
{
$languageService = $this->getLanguageService();
$html = [];
$html[] = '<div class="mb-3">';
$html[] = '<div class="form-check form-switch">';
$html[] = BackendUtility::getFuncCheck($pageId, 'clipBoard', $checked, '', $singleTable ? '&table=' . $singleTable : '', 'id="checkShowClipBoard"');
$html[] = '<label class="form-check-label" for="checkShowClipBoard">';
$html[] = htmlspecialchars($languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:showClipBoard'));
$html[] = '</label>';
$html[] = '</div>';
$html[] = '</div>';
return implode(LF, $html);
}

/**
* Check if page can be edited by current user
*/
Expand Down
82 changes: 81 additions & 1 deletion typo3/sysext/backend/Classes/ElementBrowser/FileBrowser.php
Expand Up @@ -16,14 +16,17 @@
namespace TYPO3\CMS\Backend\ElementBrowser;

use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Backend\ElementBrowser\Event\IsFileSelectableEvent;
use TYPO3\CMS\Backend\Routing\Route;
use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Backend\Tree\View\LinkParameterProviderInterface;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Backend\View\BackendViewFactory;
use TYPO3\CMS\Backend\View\FolderUtilityRenderer;
use TYPO3\CMS\Backend\View\RecordSearchBoxComponent;
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Messaging\FlashMessage;
Expand All @@ -42,6 +45,7 @@
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\HttpUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Core\Utility\PathUtility;

/**
* Browser for files. This is used when adding a FAL inline image with the 'add image' button in FormEngine.
Expand Down Expand Up @@ -463,7 +467,7 @@ protected function getThumbnailSelector(): string
return '
<div class="col-auto">
<div class="form-check form-switch">
' . BackendUtility::getFuncCheck('', 'SET[displayThumbs]', $currentValue, $this->thisScript, $addParams, 'id="checkDisplayThumbs"') . '
' . self::getFuncCheck('', 'SET[displayThumbs]', $currentValue, $request, $this->thisScript, $addParams, 'id="checkDisplayThumbs"') . '
<label for="checkDisplayThumbs" class="form-check-label">
' . htmlspecialchars($lang->sL('LLL:EXT:backend/Resources/Private/Language/locallang_browse_links.xlf:displayThumbs')) . '
</label>
Expand Down Expand Up @@ -516,4 +520,80 @@ public function getScriptUrl()
{
return $this->thisScript;
}

//################################
// copied over from BackendUtility to enable deprecation of the original method
// @todo finish fluidification of template and remove HTML generation from controller
//################################

/**
* Checkbox function menu.
* Works like ->getFuncMenu() but takes no $menuItem array since this is a simple checkbox.
*
* @param mixed $mainParams $id is the "&id=" parameter value to be sent to the module, but it can be also a parameter array which will be passed instead of the &id=...
* @param string $elementName The form elements name, probably something like "SET[...]
* @param string|bool $currentValue The value to be selected currently.
* @param string $script The script to send the &id to, if empty it's automatically found
* @param string $addParams Additional parameters to pass to the script.
* @param string $tagParams Additional attributes for the checkbox input tag
* @return string HTML code for checkbox
* @see getFuncMenu()
*/
protected static function getFuncCheck(
$mainParams,
$elementName,
$currentValue,
ServerRequestInterface $request,
$script = '',
$addParams = '',
$tagParams = ''
) {
// relies on module 'TYPO3/CMS/Backend/ActionDispatcher'
$scriptUrl = self::buildScriptUrl($mainParams, $addParams, $request, $script);
$attributes = GeneralUtility::implodeAttributes([
'type' => 'checkbox',
'class' => 'form-check-input',
'name' => $elementName,
'value' => '1',
'data-global-event' => 'change',
'data-action-navigate' => '$data=~s/$value/',
'data-navigate-value' => sprintf('%s&%s=${value}', $scriptUrl, $elementName),
'data-empty-value' => '0',
], true);
return
'<input ' . $attributes .
($currentValue ? ' checked="checked"' : '') .
($tagParams ? ' ' . $tagParams : '') .
' />';
}

/**
* Builds the URL to the current script with given arguments
*
* @param mixed $mainParams $id is the "&id=" parameter value to be sent to the module, but it can be also a parameter array which will be passed instead of the &id=...
* @param string $addParams Additional parameters to pass to the script.
* @param string $script The script to send the &id to, if empty it's automatically found
* @return string The complete script URL
* @todo Check if this can be removed or replaced by routing
*/
protected static function buildScriptUrl($mainParams, $addParams, ServerRequestInterface $request, $script = '')
{
if (!is_array($mainParams)) {
$mainParams = ['id' => $mainParams];
}

$route = $request->getAttribute('route');
if ($route instanceof Route) {
$uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
$scriptUrl = (string)$uriBuilder->buildUriFromRoute($route->getOption('_identifier'), $mainParams);
$scriptUrl .= $addParams;
} else {
if (!$script) {
$script = PathUtility::basename(Environment::getCurrentScript());
}
$scriptUrl = $script . HttpUtility::buildQueryString($mainParams, '?') . $addParams;
}

return $scriptUrl;
}
}
6 changes: 6 additions & 0 deletions typo3/sysext/backend/Classes/Utility/BackendUtility.php
Expand Up @@ -2218,6 +2218,7 @@ public static function getDropdownMenu(
* @param string $tagParams Additional attributes for the checkbox input tag
* @return string HTML code for checkbox
* @see getFuncMenu()
* @deprecated since TYPO3 v12.2. will be removed in TYPO3 v13.0.
*/
public static function getFuncCheck(
$mainParams,
Expand All @@ -2227,6 +2228,11 @@ public static function getFuncCheck(
$addParams = '',
$tagParams = ''
) {
trigger_error(
'BackendUtility::getFuncCheck will be removed in TYPO3 v13.0, use Fluid based templating instead.',
E_USER_DEPRECATED
);

// relies on module 'TYPO3/CMS/Backend/ActionDispatcher'
$scriptUrl = self::buildScriptUrl($mainParams, $addParams, $script);
$attributes = GeneralUtility::implodeAttributes([
Expand Down
14 changes: 13 additions & 1 deletion typo3/sysext/backend/Resources/Private/Templates/RecordList.html
Expand Up @@ -46,7 +46,19 @@ <h1>{pageTitle}</h1>

<f:format.raw>{tableListHtml}</f:format.raw>

<f:format.raw>{toggleClipboardHtml}</f:format.raw>
<f:if condition="{displayToggleClipboard}">
<div class="mb-3">
<div class="form-check form-switch">
<input type="checkbox" class="form-check-input" name="{toggleClipboardName}" value="1" data-global-event="change"
data-action-navigate="$data=~s/$value/" data-empty-value="0" {toggleClipboardChecked} id="{toggleClipboardId}"
data-navigate-value="{toggleClipboardFormUrl}"
>
<label class="form-check-label" for="{toggleClipboardId}">
<f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:showClipBoard" />
</label>
</div>
</div>
</f:if>
<f:format.raw>{clipboardHtml}</f:format.raw>

<f:format.raw>{additionalContentBottom}</f:format.raw>
Expand Down
Expand Up @@ -854,14 +854,6 @@ public function getLabelFromItemListMergedReturnsCorrectFields(
self::assertEquals($expectedLabel, LabelFromItemListMergedReturnsCorrectFieldsFixture::getLabelFromItemListMerged($pageId, $table, $column, $key));
}

/**
* @test
*/
public function getFuncCheckReturnsInputTagWithValueAttribute(): void
{
self::assertStringMatchesFormat('<input %Svalue="1"%S/>', BackendUtility::getFuncCheck('params', 'test', true));
}

public function getLabelsFromItemsListDataProvider(): array
{
return [
Expand Down
@@ -0,0 +1,59 @@
.. include:: /Includes.rst.txt

.. _deprecation-99579-1673983578:

====================================================
Deprecation: #99579 - BackendUtility::getFuncCheck()
====================================================

See :issue:`99579`

Description
===========

Method :php:`\TYPO3\CMS\Backend\Utility\BackendUtility::getFuncCheck()` has
been marked as deprecated and should not be used any longer.


Impact
======

Calling the method will raise a deprecation level log error and will
stop working with TYPO3 v13.


Affected installations
======================

The method may be used in extensions that add backend modules. The
extension scanner finds usages with a strong match.


Migration
=========

:php:`BackendUtility::getFuncCheck()` is a helper method that renders a
select drop down and is typically used to trigger a GET request when
the user selects an option.

In general, such HTML should not be generated by PHP, but by Fluid templating.
The method is thus typically used by old school backend modules that have not
or only partially been transferred to Fluid, improving the controller-view
separation.

The most simple and ugly migration is to copy the method to an own controller
that consumes the method. The better solution is to add the arguments as variables
to the Fluid template and render the drop down in Fluid. This should be a pretty
straight transition as well and typically avoids another :html:`<f:format.raw>`
ViewHelper usage.

Note that requests send by these drop downs should switch from GET to POST in
case they change server state (eg. changing records) along the way: State changing
requests should be restricted to POST as an additional security measure, and to
not violate the HTTP protocol. The TYPO3 core comes with more and more examples
on how to handle this properly. For instance all drop downs and checkbox toggles
of the tstemplate extension (Web->TypoScript backend module) have been changed to
do this and can be studied on how to trigger immediate POST actions when clicking
such elements.

.. index:: Backend, PHP-API, FullyScanned, ext:backend
Expand Up @@ -129,6 +129,7 @@ public function handleRequest(ServerRequestInterface $request): ResponseInterfac
}

$viewOption = (int)$moduleData->get('tsconf_parts');
$alphaSortStatus = $moduleData->get('tsconf_alphaSort');
if ($viewOption === 99) {
$rootLine = BackendUtility::BEgetRootLine($this->id, '', true);

Expand Down Expand Up @@ -210,7 +211,7 @@ public function handleRequest(ServerRequestInterface $request): ResponseInterfac
$this->view->assign('tsconfParts99', false);
$pageTsConfig = BackendUtility::getPagesTSconfig($this->id);

if ($moduleData->get('tsconf_alphaSort')) {
if ($alphaSortStatus) {
$pageTsConfig = ArrayUtility::sortByKeyRecursive($pageTsConfig);
}

Expand All @@ -219,7 +220,13 @@ public function handleRequest(ServerRequestInterface $request): ResponseInterfac
]);
}
if ($viewOption !== 99) {
$this->view->assign('alphaSort', BackendUtility::getFuncCheck($this->id, 'tsconf_alphaSort', (bool)$moduleData->get('tsconf_alphaSort'), '', '', 'id="checkTsconf_alphaSort"'));
$route = $request->getAttribute('route');
$params = ['id' => $this->id];
$this->view->assignMultiple([
'displayAlphaSort' => true,
'alphaSortChecked' => (bool)$alphaSortStatus === true ? 'checked="checked"' : '',
'alphaSortUrl' => $this->uriBuilder->buildUriFromRoute($route->getOption('_identifier'), $params) . '&tsconf_alphaSort=${value}',
]);
}
$this->view->assignMultiple([
'dropdownMenuOptions' => $allowedModuleOptions['tsconf_parts'],
Expand Down
Expand Up @@ -13,13 +13,17 @@ <h1>{f:translate(key: 'LLL:EXT:info/Resources/Private/Language/InfoPageTsConfig.
</label>
<f:render partial="DropdownMenu" arguments="{name: 'tsconf_parts', id: 'tsconf_parts', options: dropdownMenuOptions, currentValue: dropdownMenuCurrentValue}"/>
</div>
<f:if condition="{alphaSort}">
<f:if condition="{displayAlphaSort}">
<div class="col">
<div class="form-check form-switch">
<label class="form-check-label" for="checkTsconf_alphaSort">
{f:translate(key: 'LLL:EXT:info/Resources/Private/Language/InfoPageTsConfig.xlf:sort_alphabetic')}
</label>
<f:format.raw>{alphaSort}</f:format.raw>
<input type="checkbox" class="form-check-input" name="tsconf_alphaSort" value="1" data-global-event="change"
data-action-navigate="$data=~s/$value/"
data-navigate-value="{alphaSortUrl}"
data-empty-value="0" id="checkTsconf_alphaSort" {alphaSortChecked}
>
</div>
</div>
</f:if>
Expand Down
Expand Up @@ -1436,4 +1436,11 @@
'Deprecation-99564-DeprecatedBackendUtilityGetDropdownMenu.rst',
],
],
'TYPO3\CMS\Backend\Utility\BackendUtility::getFuncCheck' => [
'numberOfMandatoryArguments' => 3,
'maximumNumberOfArguments' => 6,
'restFiles' => [
'Deprecation-99579-BackendUtilityGetFuncCheck.rst',
],
],
];

0 comments on commit 42a4c03

Please sign in to comment.