---
title: "Breaking: #98281 - Make AbstractPlugin @internal"
manual: "TYPO3 Core Changelog"
version: "main"
permalink: "https://docs.typo3.org/permalink/changelog:breaking-98281-1662549900"
source: "Changelog/12.0/Breaking-98281-MakeAbstractPluginInternal.rst"
typo3-version: "12.0"
typo3-major: 12
type: "breaking"
issue: 98281
forge: "https://forge.typo3.org/issues/98281"
tags: ["Frontend", "FullyScanned", "ext:frontend"]
rendered: "2026-09-20T18:31:11+00:00"
---

# Breaking: #98281 - Make AbstractPlugin @internal {#breaking-98281-1662549900}

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

## Description {#description}

Extending the class `\TYPO3\CMS\Frontend\Plugin\AbstractPlugin` is not a
recommended way of developing Frontend plugins anymore. This class is not
maintained anymore and may be removed in future versions without further notice.

The TypoScript property `plugin.tx_myextension_pi1._DEFAULT_PI_VARS`
has only been used in the class `AbstractPlugin`. It is therefore not public
API anymore.

## Impact {#impact}

Plugins based on `\TYPO3\CMS\Frontend\Plugin\AbstractPlugin` will
continue to function. However, there will be warnings about using internal
code displayed in most IDEs.

`_DEFAULT_PI_VARS` has been removed from syntax highlighting as it is
not public API anymore.

## Affected installations {#affected-installations}

All extensions having classes that extend
`\TYPO3\CMS\Frontend\Plugin\AbstractPlugin` are affected.

## Migration {#migration}

Remove the dependency of `\TYPO3\CMS\Frontend\Plugin\AbstractPlugin`. If
functionality of this class is still used, copy it into your plugin.

### Example {#example}

Class before migration:

**EXT:gh_randomcontent/Classes/Plugin/RandomContent.php**

```php
use Psr\Http\Message\ServerRequestInterface;

class RandomContent extends AbstractPlugin
{
    public function main(
      string $content,
      array $conf,
      ServerRequestInterface $request,
    ): string
    {
        $this->conf = $conf;

        // Init FlexForm configuration for plugin
        $this->pi_initPIflexForm();
        if ($this->pi_getFFvalue(
            $this->cObj->data['pi_flexform'],
            'which_pages', 'sDEF')
        ) {
            $this->conf['pages'] = $this->pi_getFFvalue(
                $this->cObj->data['pi_flexform'],
                'which_pages', 'sDEF'
            );
        }
        // ...
    }
}
```

Class after migration:

**EXT:gh_randomcontent/Classes/Plugin/RandomContent.php**

```php
use Psr\Http\Message\ServerRequestInterface;

class RandomContent
{
    /**
     * The back-reference to the mother cObj object set at call time
     */
    public $cObj;

    /**
     * This setter is called when the plugin is called from UserContentObject (USER)
     * via ContentObjectRenderer->callUserFunction().
     *
     * @param ContentObjectRenderer $cObj
     */
    public function setContentObjectRenderer(ContentObjectRenderer $cObj): void
    {
        $this->cObj = $cObj;
    }

    public function main(
      string $content,
      array $conf,
      ServerRequestInterface $request,
    ): string
    {
        $this->conf = $conf;

        $this->pi_initPIflexForm(); // Init FlexForm configuration for plugin
        if ($this->pi_getFFvalue($this->cObj->data['pi_flexform'],
            'which_pages', 'sDEF')) {
            $this->conf['pages'] = $this->pi_getFFvalue(
                $this->cObj->data['pi_flexform'],
                'which_pages',
                'sDEF'
            );
        }
        // ...
    }

    /**
     * Converts $this->cObj->data['pi_flexform'] from XML string to FlexForm array.
     *
     * @param string $field Field name to convert
     */
    public function pi_initPIflexForm($field = 'pi_flexform')
    {
        // ...
    }

    public function pi_getFFvalue(
        $T3FlexForm_array,
        $fieldName,
        $sheet = 'sDEF',
        $lang = 'lDEF',
        $value = 'vDEF'
    ) {
        // ...
    }
}
```

It is also possible to migrate to an Extbase plugin using a controller.
See the [Extbase documentation, chapter
"Frontend Plugins"](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ExtensionArchitecture/Extbase/Registration/FrontendPlugin.html#extbase_registration_of_frontend_plugins).

> [!IMPORTANT]
> The `AbstractPlugin` is [deprecated](https://docs.typo3.org/permalink/changelog:deprecation-100639-1681740974)
> through a follow-up change and will be removed in TYPO3 v13. Executing
> a plugin via the TypoScript userFunc (also utilized the `$request` argument for
> the `main` method) continues to work, as long as the collection of `AbstractPlugin`
> methods are ported to the custom user class.
