Deprecation: #91814 - AbstractControl::setOnClick

See forge#91814

Description

In favor of allowing Content-Security-Policy HTTP headers, inline JavaScript invocation via \TYPO3\CMS\Backend\Template\Components\AbstractControl::setOnClick has been marked as deprecated. Existing instructions can be migrated using existing JavaScript helpers GlobalEventHandler or ActionDispatcher and their capabilities to provide similar functionality using data- attributes.

There might be scenarios that require a custom JavaScript module handling specific use cases that are not covered by mentioned JavaScript helpers.

Impact

Using affected PHP methods (see section below) will trigger PHP E_USER_DEPRECATED errors.

Affected Installations

All sites using 3rd party extensions that are using following methods directly or in inherited class implementations:

  • \TYPO3\CMS\Backend\Template\Components\AbstractControl->setOnClick

  • \TYPO3\CMS\Backend\Template\Components\AbstractControl->getOnClick

Migration

Mentioned JavaScript helpers cover most common use cases by using data- attributes instead of onclick event attributes with corresponding HTML elements.

  • consider replacing simple <a ... onclick="window.location.href=[URI]" with plain HTML links like <a href="[URI]">

  • replacing BackendUtility::viewOnClick, see documentation & examples

  • using data- attributes for GlobalEventHandler and ActionDispatcher, see documentation & examples

Example #1: open a new window/tab

$button->setOnClick(
    'window.open(\'' . $this->getDceEditLink($contentUid) . '\', \'editDcePopup\', ' .
    '\'height=768,width=1024,status=0,menubar=0,scrollbars=1\')'
);

Code block above being substituted with ActionDispatcher capabilities, using data-dispatch-action and data-dispatch-args HTML attributes:

$button->setDataAttributes([
    'dispatch-action' => 'TYPO3.WindowManager.localOpen',
    // JSON encoded representation of JavaScript function arguments
    // (HTML attributes are encoded in \TYPO3\CMS\Backend\Template\Components\Buttons\LinkButton)
    'dispatch-args' => GeneralUtility::jsonEncodeForHtmlAttribute([
        $this->getDceEditLink($contentUid),
        'editDcePopup',
        'height=768,width=1024,status=0,menubar=0,scrollbars=1',
    ], false)
]);

Example #2: preview page in frontend

$viewButton = $buttonBar->makeLinkButton()
    // @deprecated setOnClick
    ->setOnClick(BackendUtility::viewOnClick($pageUid, '', BackendUtility::BEgetRootLine($pageUid)))
    ->setTitle($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage'))
    ->setIcon($iconFactory->getIcon('actions-view-page', Icon::SIZE_SMALL))
    ->setHref('#');

Code block above being substituted with \TYPO3\CMS\Backend\Routing\PreviewUriBuilder based on ActionDispatcher capabilities, using data-dispatch-action and data-dispatch-args HTML attributes:

$previewDataAttributes = PreviewUriBuilder::create($pageUid)
    ->withRootLine(BackendUtility::BEgetRootLine($pageUid))
    ->buildDispatcherDataAttributes();
$viewButton = $buttonBar->makeLinkButton()
    // substituted with HTML data attributes
    ->setDataAttributes($previewDataAttributes ?? [])
    ->setTitle($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage'))
    ->setIcon($iconFactory->getIcon('actions-view-page', Icon::SIZE_SMALL))
    ->setHref('#');

Example #3: confirmation dialog

  • taken form extension news

  • see corresponding pull-request

  • side-note: There was a bug in extension news, examples below have been adjusted to show how the scenario probably would have been before, using confirm()

$pasteTitle = 'Paste from Clipboard';
$confirmMessage = GeneralUtility::quoteJSvalue('Shall we paste the record?');
$viewButton = $buttonBar->makeLinkButton()
    ->setHref($clipBoard->pasteUrl('', $this->pageUid))
    // @deprecated inline JavaScript requesting user confirmation
    ->setOnClick('return confirm(' . $confirmMessage . ')')
    ->setTitle($pasteTitle)
    ->setIcon($this->iconFactory->getIcon('actions-document-paste-into', Icon::SIZE_SMALL));

Code block above being substituted with capabilities of modal dialog handling and functionalities of the Bootstrap framework.

$pasteTitle = 'Paste from Clipboard';
$confirmMessage = 'Shall we paste the record?';
$viewButton = $buttonBar->makeLinkButton()
    ->setHref($clipBoard->pasteUrl('', $this->pageUid))
    // using CSS class to trigger confirmation in modal box
    ->setClasses('t3js-modal-trigger')
    ->setDataAttributes([
        'title' => $pasteTitle,
        'bs-content' => $confirmMessage,
    ])
    ->setTitle($pasteTitle)
    ->setIcon($this->iconFactory->getIcon('actions-document-paste-into', Icon::SIZE_SMALL));