---
title: "Feature: #97231 - PSR-14 events for modifying inline element controls"
manual: "TYPO3 Core Changelog"
version: "main"
permalink: "https://docs.typo3.org/permalink/changelog:feature-97231"
source: "Changelog/12.0/Feature-97231-PSR-14EventsForModifyingInlineElementControls.rst"
typo3-version: "12.0"
typo3-major: 12
type: "feature"
issue: 97231
forge: "https://forge.typo3.org/issues/97231"
tags: ["Backend", "PHP-API", "ext:backend"]
rendered: "2026-09-20T18:31:11+00:00"
---

# Feature: #97231 - PSR-14 events for modifying inline element controls {#feature-97231}

See [forge#97231](https://forge.typo3.org/issues/97231)

## Description {#description}

The new PSR-14 events `\TYPO3\CMS\Backend\Form\Event\ModifyInlineElementEnabledControlsEvent`
and `\TYPO3\CMS\Backend\Form\Event\ModifyInlineElementControlsEvent`
have been introduced, which serve as a more powerful and flexible replacement
for the now removed hook
`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tceforms_inline.php']['tceformsInlineHook']`.

The `\TYPO3\CMS\Backend\Form\Event\ModifyInlineElementEnabledControlsEvent`
is called before any control markup is generated. It can be used to
enable or disable each control. With this event it's therefore possible
to e.g. enable a control, which is disabled in TCA, only for some use case.

The `\TYPO3\CMS\Backend\Form\Event\ModifyInlineElementControlsEvent`
is called after the markup for all enabled controls has been generated. It
can be used to either change the markup of a control, to add a new control
or to completely remove a control.

> [!NOTE]
> Previously the deprecated hook interface `InlineElementHookInterface`
> required hook implementations to implement both methods
> `renderForeignRecordHeaderControl_preProcess()` and
> `renderForeignRecordHeaderControl_postProcess()`, even if only
> one was used. This is now resolved since listeners can be registered
> only for the needed PSR-14 event.

## Example {#example}

Registration of the event in your extension's `Services.yaml`:

```yaml
MyVendor\MyPackage\Frontend\MyEventListener:
  tags:
    - name: event.listener
      identifier: 'my-package/backend/modify-enabled-controls'
      method: 'modifyEnabledControls'
    - name: event.listener
      identifier: 'my-package/backend/modify-controls'
      method: 'modifyControls'
```

The corresponding event listener class:

```php
use TYPO3\CMS\Backend\Form\Event\ModifyInlineElementEnabledControlsEvent;
use TYPO3\CMS\Backend\Form\Event\ModifyInlineElementControlsEvent;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Utility\GeneralUtility;

class MyEventListener
{

    public function modifyEnabledControls(
        ModifyInlineElementEnabledControlsEvent $event
    ): void {
        // Enable a control depending on the foreign table
        if ($event->getForeignTable() === 'sys_file_reference'
            && $event->isControlEnabled('sort')) {
            $event->enableControl('sort');
        }
    }

    public function modifyControls(
        ModifyInlineElementControlsEvent $event
    ): void {
        // Add a custom control depending on the parent table
        if ($event->getElementData()['inlineParentTableName'] === 'tt_content') {
            $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
            $iconCode = $iconFactory->getIcon(
                'my-icon-identifier',
                Icon::SIZE_SMALL
            )->render();
            $event->setControl(
                'tx_my_control',
                '<a href="/some/url" class="btn btn-default t3js-modal-trigger">'
                . $iconCode . '</a>'
            );
        }
    }
}
```

## Available Methods {#available-methods}

The list below describes all specific methods for the `ModifyInlineElementEnabledControlsEvent`:

| Method | Parameters | Description |
| --- | --- | --- |
| enableControl() | `$identifier` | Enable a control, if it exists. Returns whether the control could be enabled. |
| disableControl() | `$identifier` | Disable a control, if it exists. Returns whether the control could be disabled. |
| hasControl | `$identifier` | Whether a control exists for the given identifier. |
| isControlEnabled() | `$identifier` | Returns whether the control is enabled. Will also return `false` in case no control exists for the requested identifier. |
| getControlsState() | `$identifier` | Returns all controls with their state (enabled or disabled). |
| getEnabledControls() |  | Returns only the enabled controls. |

The list below describes all specific methods for the `ModifyInlineElementControlsEvent`:

| Method | Parameters | Description |
| --- | --- | --- |
| getControls() |  | Returns all controls with their markup. |
| setControls() | `$controls` | Overwrite the controls. |
| getControl() | `$identifier` | Returns the markup for the requested control. |
| setControl() | `$identifier` `$markup` | Set a control with the given identifier and markup. Overwrites an existing control with the same identifier. |
| hasControl() | `$identifier` | Returns whether a control exists for the given identifier. |
| removeControl() | `$identifier` | Removes a control from the inline element. Returns whether the control could be disabled. |

The list below describes all common methods of both events:

| Method | Description |
| --- | --- |
| getElementData() | Returns the whole element data. |
| getRecord() | Returns the current record of the controls are created for. |
| getParentUid() | Returns the uid of the parent (embedding) record (uid or NEW...). |
| getForeignTable() | Returns the table (foreign_table) the controls are created for. |
| getFieldConfiguration() | Returns the TCA configuration of the inline record field. |
| isVirtual() | Returns whether the current records is only virtually shown and not physically part of the parent record. |

## Impact {#impact}

The main advantages of the new PSR-14 events are an increased amount of
available information, the object-oriented approach as well as the new
built-in convenience features.

Additionally, it's no longer necessary to implement empty methods, required
by the interface.
