TYPO3 v15 dev-main snapshot ()

This commit is contained in:
2026-08-10 22:31:09 +02:00
commit af8cc155b5
6818 changed files with 642608 additions and 0 deletions
@@ -0,0 +1,38 @@
.. include:: /Includes.rst.txt
.. _breaking-101292-1742899857:
======================================================================
Breaking: #101292 - Strong-typed PropertyMappingConfigurationInterface
======================================================================
See :issue:`101292`
Description
===========
Extbase's :php-short:`\TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface`
is now fully typed with native PHP types.
Impact
======
Existing implementations will no longer work without adjustment. According to
the Liskov Substitution Principle, all implementations must follow the updated
method signatures and type restrictions defined in the interface.
Affected installations
======================
TYPO3 installations with custom PHP code implementing a custom
:php-short:`\TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration` are
affected. Such cases are rare.
Migration
=========
Add the required native PHP types to all custom implementations of the
:php-short:`\TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface`
to fulfill the updated interface definition.
.. index:: PHP-API, NotScanned, ext:extbase
@@ -0,0 +1,54 @@
.. include:: /Includes.rst.txt
.. _breaking-101392-1742741515:
=================================================================================
Breaking: #101392 - getIdentifier() and setIdentifier() from AbstractFile removed
=================================================================================
See :issue:`101392`
Description
===========
When using the PHP API of the **File Abstraction Layer (FAL)**, several classes
are involved in representing file objects.
In addition to the
:php-short:`\TYPO3\CMS\Core\Resource\FileInterface`, there is also the
:php-short:`\TYPO3\CMS\Core\Resource\AbstractFile` class, from which most file-
related classes inherit.
To ensure stricter type consistency, the abstract class no longer implements
the methods :php:`getIdentifier()` and :php:`setIdentifier()`. Implementing
these methods is now the responsibility of each subclass.
The methods are now implemented in the respective concrete classes inheriting
from :php-short:`\TYPO3\CMS\Core\Resource\AbstractFile`.
Impact
======
In the unlikely case that the TYPO3 File Abstraction Layer has been extended
with custom PHP classes derived from
:php-short:`\TYPO3\CMS\Core\Resource\AbstractFile`, this change will
cause a fatal PHP error, as the new abstract methods :php:`getIdentifier()` and
:php:`setIdentifier()` must be implemented by the subclass.
Affected installations
======================
TYPO3 installations that include custom code extending the File Abstraction
Layer are affected. Such cases are considered highly uncommon.
Migration
=========
Implement the two methods :php:`getIdentifier()` and :php:`setIdentifier()` in
any custom file class extending
:php-short:`\TYPO3\CMS\Core\Resource\AbstractFile`.
This can also be implemented in older TYPO3 versions to ensure forward
compatibility with TYPO3 v14 and later.
.. index:: PHP-API, NotScanned, ext:core
@@ -0,0 +1,52 @@
.. include:: /Includes.rst.txt
.. _breaking-103141-1733501374:
============================================================
Breaking: #103141 - Use doctrine GUID type for TCA type=uuid
============================================================
See :issue:`103141`
Description
===========
The TYPO3 Doctrine implementation can now handle the proper
matching database type for UUID's.
Postgresql natively supports the UUID data type and is way faster
than the prior `VARCHAR(36)` generated from the string type.
The Doctrine DBAL GUID type uses `CHAR(36)` as the fixed field column size
for non-postgres databases, which is compatible as long
as valid UUID values were persisted in the configured database
table.
Impact
======
TYPO3 database tables can now natively properly apply the suitable
GUID column type when configured as TCA `type=uuid`.
A prerequisite for this is that you only have valid UUID's stored
in the database table, otherwise the database update will report
an error when applying migrations.
Affected installations
======================
Projects with database table columns set as TCA `type=uuid`.
Error are likely to occur, if invalid UUID data is stored
in field columns configured with this type.
Migration
=========
Use the database analyzer to migrate the database fields.
Invalid values are not migrated and need to be manually
cleaned up in affected instances.
.. index:: Database, FullyScanned, ext:core
@@ -0,0 +1,79 @@
.. include:: /Includes.rst.txt
.. _breaking-103910-1737267888:
=========================================================
Breaking: #103910 - Change logout handling in EXT:felogin
=========================================================
See :issue:`103910`
Description
===========
The logout handling has been adjusted to correctly dispatch the PSR-14 event
:php:`\TYPO3\CMS\FrontendLogin\Event\LogoutConfirmedEvent` when a logout
redirect is configured. The :php:`actionUri` variable has been removed, and the
logout template has been updated to reflect this change, including correct use
of the :php:`noredirect` functionality.
Impact
======
The PSR-14 event
:php-short:`\TYPO3\CMS\FrontendLogin\Event\LogoutConfirmedEvent` is now
correctly dispatched when a logout redirect is configured. Additionally, the
:php:`noredirect` parameter is now evaluated during logout.
Affected installations
======================
TYPO3 installations using EXT:felogin with a custom Fluid template for
the logout form.
Migration
=========
The :fluid:`{actionUri}` variable is no longer available and must be removed
from custom templates.
**Before:**
.. code-block:: html
:caption: Fluid template adjustment (before)
<!-- Before -->
<f:form action="login" actionUri="{actionUri}" target="_top" fieldNamePrefix="">
**After:**
.. code-block:: html
:caption: Fluid template adjustment (after)
<f:form action="login" target="_top" fieldNamePrefix="">
The evaluation of the :fluid:`{noRedirect}` variable must be added to the
template:
**Before:**
.. code-block:: html
:caption: Fluid template adjustment for noRedirect (before)
<div class="felogin-hidden">
<f:form.hidden name="logintype" value="logout" />
</div>
**After:**
.. code-block:: html
:caption: Fluid template adjustment for noRedirect (after)
<div class="felogin-hidden">
<f:form.hidden name="logintype" value="logout" />
<f:if condition="{noRedirect} != ''">
<f:form.hidden name="noredirect" value="1" />
</f:if>
</div>
.. index:: Frontend, NotScanned, ext:felogin
@@ -0,0 +1,40 @@
.. include:: /Includes.rst.txt
.. _breaking-103913-1740920635:
=======================================================================
Breaking: #103913 - Do not perform redirect in EXT:felogin logoutAction
=======================================================================
See :issue:`103913`
Description
===========
Redirect handling for the :php:`logoutAction` has been removed.
Impact
======
The :php:`logoutAction` no longer performs any configured redirect via plugin
settings or GET parameters.
Affected installations
======================
TYPO3 installations relying on redirect handling within
:php:`logoutAction` are affected.
Migration
=========
No migration is required. The previous redirect logic in
:php:`logoutAction()` has been removed because it was incorrect: it ignored
the :php:`showLogoutFormAfterLogin` setting and could trigger an unintended
redirect even when this option was enabled.
Valid redirects are already processed correctly by
:php:`loginAction()` and :php:`overviewAction()`, so the faulty branch was
removed without replacement.
.. index:: Frontend, NotScanned, ext:felogin
@@ -0,0 +1,58 @@
.. include:: /Includes.rst.txt
.. _breaking-104422-1721646316:
================================================================
Breaking: #104422 - Move GET parameters in sitemap into namespace
================================================================
See :issue:`104422`
Description
===========
The names of the GET parameters used in the sitemap generated by EXT:seo have
been changed from `page` and `sitemap` to `tx_seo[page]` and `tx_seo[sitemap]`,
respectively.
Impact
======
Applications, routing configurations, and third-party tools that rely on the
parameters being named `page` and `sitemap` will break.
Affected installations
======================
This affects installations that use the arguments `page` and `sitemap` or
override the sitemap templates of EXT:seo.
Migration
=========
If the arguments are mapped in the routing configuration, the code needs to
be slightly adapted. A working example:
.. code-block:: yaml
routeEnhancers:
Sitemap:
type: Simple
routePath: 'sitemap-type/{sitemap}'
aspects:
sitemap:
type: StaticValueMapper
map:
pages: pages
tx_news: tx_news
my_other_sitemap: my_other_sitemap
_arguments:
sitemap: 'tx_seo/sitemap'
If the templates in `EXT:seo/Resources/Private/Templates/XmlSitemap/Index.xml`
have been modified, adjust the generated links to match the original ones.
If the URL to a single sitemap has been provided to a third-party tool such as
a crawler or search engine, it must be re-added using the new URL.
.. index:: Frontend, ext:seo, NotScanned
@@ -0,0 +1,271 @@
.. include:: /Includes.rst.txt
.. _breaking-105377-1729513863:
====================================================
Breaking: #105377 - Deprecated functionality removed
====================================================
See :issue:`105377`
Description
===========
The following PHP classes that have previously been marked as deprecated with v13 have been removed:
- :php:`\TYPO3\CMS\Backend\Toolbar\Enumeration\InformationStatus` :ref:`(Deprecation entry) <deprecation-101174-1688128234>`
- :php:`\TYPO3\CMS\Core\DataHandling\SlugEnricher` :ref:`(Deprecation entry) <deprecation-103244-1709376790>`
- :php:`\TYPO3\CMS\Core\Resource\DuplicationBehavior` :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Type\Enumeration` :ref:`(Deprecation entry) <deprecation-101163-1681741493>`
- :php:`\TYPO3\CMS\Core\Type\Icon\IconState` :ref:`(Deprecation entry) <deprecation-101133-1687875352>`
- :php:`\TYPO3\CMS\Extbase\Mvc\View\GenericViewResolver` :ref:`(Deprecation entry) <deprecation-104773-1724942036>`
- :php:`\TYPO3\CMS\Extbase\Security\Cryptography\HashService` :ref:`(Deprecation entry) <deprecation-102763-1706358913>`
- :php:`\TYPO3\CMS\Fluid\View\AbstractTemplateView` :ref:`(Deprecation entry) <deprecation-104773-1724942036>`
- :php:`\TYPO3\CMS\Fluid\View\StandaloneView` :ref:`(Deprecation entry) <deprecation-104773-1724942036>`
- :php:`\TYPO3\CMS\Fluid\View\TemplateView` :ref:`(Deprecation entry) <deprecation-104773-1724942036>`
The following PHP classes have been declared :php:`final`:
- :php:`\TYPO3\CMS\Extensionmanager\Updates\ExtensionModel` :ref:`(Deprecation entry) <deprecation-102943-1706271208>`
The following PHP interfaces that have previously been marked as deprecated with v13 have been removed:
- :php:`\TYPO3\CMS\Core\Domain\Repository\PageRepositoryInitHookInterface` :ref:`(Deprecation entry) <deprecation-102806-1704876661>`
- :php:`\TYPO3\CMS\Core\Domain\Repository\PageRepositoryGetPageHookInterface` :ref:`(Deprecation entry) <deprecation-102806-1704876661>`
- :php:`\TYPO3\CMS\Extbase\Mvc\View\ViewResolverInterface` :ref:`(Deprecation entry) <deprecation-104773-1724942036>`
- :php:`\TYPO3\CMS\Frontend\ContentObject\ContentObjectGetDataHookInterface` :ref:`(Deprecation entry) <deprecation-102614-1701869807>`
- :php:`\TYPO3\CMS\Frontend\ContentObject\ContentObjectGetImageResourceHookInterface` :ref:`(Deprecation entry) <deprecation-102755-1704449836>`
- :php:`\TYPO3\CMS\Frontend\ContentObject\ContentObjectOneSourceCollectionHookInterface` :ref:`(Deprecation entry) <deprecation-102624-1701943829>`
- :php:`\TYPO3\CMS\Frontend\ContentObject\ContentObjectPostInitHookInterface` :ref:`(Deprecation entry) <deprecation-102581-1701449501>`
- :php:`\TYPO3\CMS\Frontend\ContentObject\ContentObjectStdWrapHookInterface` :ref:`(Deprecation entry) <deprecation-102745-1705054271>`
The following PHP interfaces changed:
- :php:`\TYPO3\CMS\Backend\LoginProvider\LoginProviderInterface->modifyView()` added :ref:`(Deprecation entry) <deprecation-104773-1724940753>`
- :php:`\TYPO3\CMS\Backend\LoginProvider\LoginProviderInterface->render()` removed :ref:`(Deprecation entry) <deprecation-104773-1724940753>`
- :php:`\TYPO3\CMS\Core\PageTitle\PageTitleProviderInterface->setRequest()` added :issue:`102817`
The following PHP class aliases that have previously been marked as deprecated with v13 have been removed:
- :php:`\TYPO3\CMS\Backend\Attribute\Controller` :ref:`(Deprecation entry) <deprecation-102631-1702031387>`
- :php:`\TYPO3\CMS\Backend\FrontendBackendUserAuthentication` :ref:`(Deprecation entry) <important-105175-1727799093>`
- :php:`\TYPO3\CMS\Core\Database\Schema\Types\EnumType` :ref:`(Deprecation entry) <deprecation-105279-1728669356>`
- :php:`\TYPO3\CMS\Core\View\FluidViewAdapter` :issue:`105086`
- :php:`\TYPO3\CMS\Core\View\FluidViewFactory` :issue:`105086`
- :php:`\TYPO3\CMS\Install\Updates\AbstractDownloadExtensionUpdate` :ref:`(Deprecation entry) <deprecation-102943-1706271208>`
- :php:`\TYPO3\CMS\Install\Updates\ExtensionModel` :ref:`(Deprecation entry) <deprecation-102943-1706271208>`
The following PHP class methods that have previously been marked as deprecated with v13 have been removed:
- :php:`\TYPO3\CMS\Backend\Controller\LoginController->getCurrentRequest()` :ref:`(Deprecation entry) <deprecation-104773-1724940753>`
- :php:`\TYPO3\CMS\Backend\Controller\LoginController->getLoginProviderIdentifier()` :ref:`(Deprecation entry) <deprecation-104773-1724940753>`
- :php:`\TYPO3\CMS\Backend\LoginProvider\Event\ModifyPageLayoutOnLoginProviderSelectionEvent->getController()` :ref:`(Deprecation entry) <deprecation-104773-1724940753>`
- :php:`\TYPO3\CMS\Backend\LoginProvider\Event\ModifyPageLayoutOnLoginProviderSelectionEvent->getPageRenderer()` :ref:`(Deprecation entry) <deprecation-104773-1724940753>`
- :php:`\TYPO3\CMS\Backend\View\BackendLayout\DataProviderContext->getData()` :ref:`(Deprecation entry) <deprecation-105252-1728471144>`
- :php:`\TYPO3\CMS\Backend\View\BackendLayout\DataProviderContext->getFieldName()` :ref:`(Deprecation entry) <deprecation-105252-1728471144>`
- :php:`\TYPO3\CMS\Backend\View\BackendLayout\DataProviderContext->getPageId()` :ref:`(Deprecation entry) <deprecation-105252-1728471144>`
- :php:`\TYPO3\CMS\Backend\View\BackendLayout\DataProviderContext->getPageTsConfig()` :ref:`(Deprecation entry) <deprecation-105252-1728471144>`
- :php:`\TYPO3\CMS\Backend\View\BackendLayout\DataProviderContext->getTableName()` :ref:`(Deprecation entry) <deprecation-105252-1728471144>`
- :php:`\TYPO3\CMS\Backend\View\BackendLayout\DataProviderContext->setData()` :ref:`(Deprecation entry) <deprecation-105252-1728471144>`
- :php:`\TYPO3\CMS\Backend\View\BackendLayout\DataProviderContext->setFieldName()` :ref:`(Deprecation entry) <deprecation-105252-1728471144>`
- :php:`\TYPO3\CMS\Backend\View\BackendLayout\DataProviderContext->setPageId()` :ref:`(Deprecation entry) <deprecation-105252-1728471144>`
- :php:`\TYPO3\CMS\Backend\View\BackendLayout\DataProviderContext->setPageTsConfig()` :ref:`(Deprecation entry) <deprecation-105252-1728471144>`
- :php:`\TYPO3\CMS\Backend\View\BackendLayout\DataProviderContext->setTableName()` :ref:`(Deprecation entry) <deprecation-105252-1728471144>`
- :php:`\TYPO3\CMS\Core\Authentication\BackendUserAuthentication->returnWebmounts()` :ref:`(Deprecation entry) <deprecation-104607-1723556132>`
- :php:`\TYPO3\CMS\Core\Imaging\Event\ModifyIconForResourcePropertiesEvent->getSize()` :ref:`(Deprecation entry) <deprecation-101475-1690546218>`
- :php:`\TYPO3\CMS\Core\Utility\DiffUtility->makeDiffDisplay()` :ref:`(Deprecation entry) <deprecation-104325-1720298173>`
- :php:`\TYPO3\CMS\Core\Versioning\VersionState->equals()` :ref:`(Deprecation entry) <deprecation-101175-1687941546>`
- :php:`\TYPO3\CMS\Extbase\Mvc\View\JsonView->renderSection()` :ref:`(Deprecation entry) <deprecation-101559-1721761906>`
- :php:`\TYPO3\CMS\Extbase\Mvc\View\JsonView->renderPartial()` :ref:`(Deprecation entry) <deprecation-101559-1721761906>`
- :php:`\TYPO3\CMS\Extbase\Service\CacheService->getPageIdStack()` :ref:`(Deprecation entry) <feature-104990-1726495719>`
- :php:`\TYPO3\CMS\Fluid\Core\Rendering\RenderingContext->setRequest()` :ref:`(Deprecation entry) <deprecation-104684-1724258020>`
- :php:`\TYPO3\CMS\Fluid\Core\Rendering\RenderingContext->getRequest()` :ref:`(Deprecation entry) <deprecation-104684-1724258020>`
- :php:`\TYPO3\CMS\Fluid\View\FluidViewAdapter->getLayoutRootPaths()` :ref:`(Deprecation entry) <deprecation-101559-1721761906>`
- :php:`\TYPO3\CMS\Fluid\View\FluidViewAdapter->getPartialRootPaths()` :ref:`(Deprecation entry) <deprecation-101559-1721761906>`
- :php:`\TYPO3\CMS\Fluid\View\FluidViewAdapter->getTemplatePaths()` :ref:`(Deprecation entry) <deprecation-101559-1721761906>`
- :php:`\TYPO3\CMS\Fluid\View\FluidViewAdapter->getTemplateRootPaths()` :ref:`(Deprecation entry) <deprecation-101559-1721761906>`
- :php:`\TYPO3\CMS\Fluid\View\FluidViewAdapter->getViewHelperResolver()` :ref:`(Deprecation entry) <deprecation-101559-1721761906>`
- :php:`\TYPO3\CMS\Fluid\View\FluidViewAdapter->hasTemplate()` :ref:`(Deprecation entry) <deprecation-101559-1721761906>`
- :php:`\TYPO3\CMS\Fluid\View\FluidViewAdapter->initializeRenderingContext()` :ref:`(Deprecation entry) <deprecation-101559-1721761906>`
- :php:`\TYPO3\CMS\Fluid\View\FluidViewAdapter->setCache()` :ref:`(Deprecation entry) <deprecation-101559-1721761906>`
- :php:`\TYPO3\CMS\Fluid\View\FluidViewAdapter->setFormat()` :ref:`(Deprecation entry) <deprecation-101559-1721761906>`
- :php:`\TYPO3\CMS\Fluid\View\FluidViewAdapter->setLayoutPathAndFilename()` :ref:`(Deprecation entry) <deprecation-101559-1721761906>`
- :php:`\TYPO3\CMS\Fluid\View\FluidViewAdapter->setLayoutRootPaths()` :ref:`(Deprecation entry) <deprecation-101559-1721761906>`
- :php:`\TYPO3\CMS\Fluid\View\FluidViewAdapter->setPartialRootPaths()` :ref:`(Deprecation entry) <deprecation-101559-1721761906>`
- :php:`\TYPO3\CMS\Fluid\View\FluidViewAdapter->setRequest()` :ref:`(Deprecation entry) <deprecation-101559-1721761906>`
- :php:`\TYPO3\CMS\Fluid\View\FluidViewAdapter->setTemplate()` :ref:`(Deprecation entry) <deprecation-101559-1721761906>`
- :php:`\TYPO3\CMS\Fluid\View\FluidViewAdapter->setTemplatePathAndFilename()` :ref:`(Deprecation entry) <deprecation-101559-1721761906>`
- :php:`\TYPO3\CMS\Fluid\View\FluidViewAdapter->setTemplateRootPaths()` :ref:`(Deprecation entry) <deprecation-101559-1721761906>`
- :php:`\TYPO3\CMS\Fluid\View\FluidViewAdapter->setTemplateSource()` :ref:`(Deprecation entry) <deprecation-101559-1721761906>`
- :php:`\TYPO3\CMS\Fluid\View\TemplatePaths->fillDefaultsByPackageName()` :ref:`(Deprecation entry) <deprecation-104764-1724851918>`
- :php:`\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->addCacheTags()` :ref:`(Deprecation entry) <deprecation-102422-1700563266>`
- :php:`\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->getPageCacheTags()` :ref:`(Deprecation entry) <deprecation-102422-1700563266>`
- :php:`\TYPO3\CMS\Frontend\Page\PageRepository->enableFields()` :ref:`(Deprecation entry) <deprecation-102793-1704798252>`
The following PHP static class methods that have previously been marked as deprecated for v13 have been removed:
- :php:`\TYPO3\CMS\Backend\Utility\BackendUtility::getTcaFieldConfiguration()` :ref:`(Deprecation entry) <deprecation-104304-1720084447>`
- :php:`\TYPO3\CMS\Backend\Utility\BackendUtility::thumbCode()` :ref:`(Deprecation entry) <deprecation-104662-1724058079>`
- :php:`\TYPO3\CMS\Core\Utility\GeneralUtility::hmac()` :ref:`(Deprecation entry) <deprecation-102762-1710402828>`
- :php:`\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPItoST43()` :ref:`(Deprecation entry) <deprecation-102821-1709843835>`
- :php:`\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPageTSConfig()` :ref:`(Deprecation entry) <deprecation-101799-1693397542>`
- :php:`\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addUserTSConfig()` :ref:`(Deprecation entry) <deprecation-101807-1693474000>`
- :php:`\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getExtensionIcon()` :ref:`(Deprecation entry) <deprecation-102895-1706003502>`
- :php:`\TYPO3\CMS\Core\Utility\MathUtility::convertToPositiveInteger()` :ref:`(Deprecation entry) <deprecation-103785-1714720280>`
- :php:`\TYPO3\CMS\Core\Versioning\VersionState::cast()` :ref:`(Deprecation entry) <deprecation-101175-1687941546>`
The following methods changed signature according to previous deprecations in v13 at the end of the argument list:
- :php:`\TYPO3\CMS\Backend\View\BackendLayout\DataProviderContext->__construct()` - All arguments are now mandatory :ref:`(Deprecation entry) <deprecation-105252-1728471144>`
- :php:`\TYPO3\CMS\Core\Imaging\IconFactory->getIcon()` (argument 4 is now of type :php:`\TYPO3\CMS\Core\Imaging\IconState|null`) :ref:`(Deprecation entry) <deprecation-101133-1687875352>`
- :php:`\TYPO3\CMS\Core\Resource\AbstractFile->copyTo()` (argument 3 is now of type :php:`\TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior`) :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Resource\AbstractFile->moveTo()` (argument 3 is now of type :php:`\TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior`) :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Resource\AbstractFile->rename()` (argument 2 is now of type :php:`\TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior`) :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Resource\FileInterface->rename()` (argument 2 is now of type :php:`\TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior`) :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Resource\FileReference->rename()` (argument 2 is now of type :php:`\TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior`) :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Resource\Folder->addFile()` (argument 3 is now of type :php:`\TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior`) :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Resource\Folder->addUploadedFile()` (argument 2 is now of type :php:`\TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior`) :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Resource\Folder->copyTo()` (argument 3 is now of type :php:`\TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior`) :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Resource\Folder->moveTo()` (argument 3 is now of type :php:`\TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior`) :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Resource\InaccessibleFolder->addFile()` (argument 3 is now of type :php:`\TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior`) :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Resource\InaccessibleFolder->addUploadedFile()` (argument 2 is now of type :php:`\TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior`) :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Resource\InaccessibleFolder->copyTo()` (argument 3 is now of type :php:`\TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior`) :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Resource\InaccessibleFolder->moveTo()` (argument 3 is now of type :php:`\TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior`) :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Resource\ResourceStorage->addFile()` (argument 4 is now of type :php:`\TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior`) :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Resource\ResourceStorage->addUploadedFile()` (argument 4 is now of type :php:`\TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior`) :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Resource\ResourceStorage->copyFile()` (argument 4 is now of type :php:`\TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior`) :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Resource\ResourceStorage->copyFolder()` (argument 4 is now of type :php:`\TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior`) :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Resource\ResourceStorage->moveFile()` (argument 4 is now of type :php:`\TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior`) :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Resource\ResourceStorage->moveFolder()` (argument 4 is now of type :php:`\TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior`) :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Resource\ResourceStorage->renameFile()` (argument 3 is now of type :php:`\TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior`) :ref:`(Deprecation entry) <deprecation-101151-1688113521>`
- :php:`\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPlugin()` (argument 2 :php:`$type` and 3 :php:`$extensionKey` have been dropped) :ref:`(Deprecation entry) <deprecation-105076-1726923626>`
The following public class properties have been dropped:
- :php:`\TYPO3\CMS\Core\DataHandling->checkStoredRecords` :ref:`(Deprecation entry) <deprecation-101793-1693356502>`
- :php:`\TYPO3\CMS\Core\DataHandling->checkStoredRecords_loose` :ref:`(Deprecation entry) <deprecation-101793-1693356502>`
- :php:`\TYPO3\CMS\Core\Utility\DiffUtility->stripTags` :ref:`(Deprecation entry) <deprecation-104325-1720298173>`
The following class property has changed/enforced type:
- :php:`\TYPO3\CMS\Extbase\Mvc\Controller\ActionController->view` (is now :php:`\TYPO3\CMS\Core\View\ViewInterface`) :ref:`(Deprecation entry) <deprecation-101559-1721761906>`
The following TypoScript options have been dropped or adapted:
- :typoscript:`<INCLUDE_TYPOSCRIPT: ...>` language construct :ref:`(Deprecation entry) <deprecation-105171-1727785626>`
The following user TSconfig options have been removed:
- :typoscript:`options.pageTree.backgroundColor` :ref:`(Deprecation entry) <deprecation-103211-1709038752>`
The following class constants have been dropped:
- :php:`\TYPO3\CMS\Core\Imaging\Icon::SIZE_DEFAULT` :ref:`(Deprecation entry) <deprecation-101475-1690546218>`
- :php:`\TYPO3\CMS\Core\Imaging\Icon::SIZE_LARGE` :ref:`(Deprecation entry) <deprecation-101475-1690546218>`
- :php:`\TYPO3\CMS\Core\Imaging\Icon::SIZE_MEDIUM` :ref:`(Deprecation entry) <deprecation-101475-1690546218>`
- :php:`\TYPO3\CMS\Core\Imaging\Icon::SIZE_MEGA` :ref:`(Deprecation entry) <deprecation-101475-1690546218>`
- :php:`\TYPO3\CMS\Core\Imaging\Icon::SIZE_SMALL` :ref:`(Deprecation entry) <deprecation-101475-1690546218>`
- :php:`\TYPO3\CMS\Core\Resource\AbstractFile::FILETYPE_APPLICATION` :ref:`(Deprecation entry) <deprecation-102032-1695805007>`
- :php:`\TYPO3\CMS\Core\Resource\AbstractFile::FILETYPE_AUDIO` :ref:`(Deprecation entry) <deprecation-102032-1695805007>`
- :php:`\TYPO3\CMS\Core\Resource\AbstractFile::FILETYPE_IMAGE` :ref:`(Deprecation entry) <deprecation-102032-1695805007>`
- :php:`\TYPO3\CMS\Core\Resource\AbstractFile::FILETYPE_TEXT` :ref:`(Deprecation entry) <deprecation-102032-1695805007>`
- :php:`\TYPO3\CMS\Core\Resource\AbstractFile::FILETYPE_UNKNOWN` :ref:`(Deprecation entry) <deprecation-102032-1695805007>`
- :php:`\TYPO3\CMS\Core\Resource\AbstractFile::FILETYPE_VIDEO` :ref:`(Deprecation entry) <deprecation-102032-1695805007>`
- :php:`\TYPO3\CMS\Extbase\Utility\ExtensionUtility::PLUGIN_TYPE_PLUGIN` :ref:`(Deprecation entry) <deprecation-105076-1726923626>`
The following global option handling have been dropped and are ignored:
- :php:`$GLOBALS['TYPO3_CONF_VARS']['BE']['defaultPageTSconfig']` :ref:`(Deprecation entry) <deprecation-101799-1693397542>`
- :php:`$GLOBALS['TYPO3_CONF_VARS']['BE']['defaultUserTSconfig']` :ref:`(Deprecation entry) <deprecation-101807-1693474000>`
The following global variables have been changed:
- :php:`$GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['SecondDatabase']['driverMiddlewares']['driver-middleware-identifier']`
must be an array, not a class string :ref:`(Deprecation entry) <deprecation-102586-1701536568>`
The following hooks have been removed:
- :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList']['customizeCsvHeader']` :ref:`(Deprecation entry) <deprecation-102337-1715591179>`
- :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList']['customizeCsvRow']` :ref:`(Deprecation entry) <deprecation-102337-1715591179>`
The following TCA options are not evaluated anymore:
- :php:`$GLOBALS['TCA'][$table]['types']['subtype_value_field']`
- :php:`$GLOBALS['TCA'][$table]['types']['subtypes_addlist']`
- :php:`$GLOBALS['TCA'][$table]['types']['subtypes_excludelist']`
The following extbase validator options have been removed:
- :php:`errorMessage` in :php:`\TYPO3\CMS\Extbase\Validation\Validator\RegularExpressionValidator` :ref:`(Deprecation entry) <deprecation-102326-1699703964>`
- Shorthand support of :php`TYPO3.CMS.Extbase` usage :ref:`(Deprecation entry) <deprecation-103965-1717335369>`
The following fallbacks have been removed:
- Accepting arrays returned by :php:`readFileContent()` in Indexed Search external parsers :ref:`(Deprecation entry) <deprecation-102908-1706081017>`
- Allowing instantiation of :php:`\TYPO3\CMS\Core\Imaging\IconRegistry` in ext_localconf.php :ref:`(Deprecation entry) <deprecation-104778-1724953249>`
- Accepting a comma-separated list of fields as value for the `columnsOnly` parameter :ref:`(Deprecation entry) <deprecation-104108-1718354448>`
- Support for extbase repository magic :php:`findByX()`, :php:`findOneByX()` and :php:`countByX()` methods :ref:`(Deprecation entry) <deprecation-100071-1677853787>`
- Fluid view helpers that extend :php:`\TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper`
should no longer register :html:`class` attribute and should rely on attribute auto registration
for the error class to be added correctly. :ref:`(Deprecation entry) <deprecation-104223-1721383576>`
- The legacy backend entry point :file:`typo3/index.php` has been removed along with handling of :file:`composer.json`
setting `extra.typo3/cms.install-deprecated-typo3-index-php` :ref:`(Deprecation entry) <deprecation-87889-1705928143>`
The following upgrade wizards have been removed:
- Install extension "fe_login_mode" from TER
- Migrate base and path to the new identifier property of the "sys_filemounts" table
- Migrate site settings to separate file
- Set workspace records in table "sys_template" to deleted
- Migrate backend user and groups to new module names
- Migrate backend groups "explicit_allowdeny" field to simplified format
- Migrate sys_log entries to a JSON formatted value
- Migrate storage and folder to the new folder_identifier property of the "sys_file_collection" table
The following row updater has been removed:
- :php:`\TYPO3\CMS\Install\Updates\RowUpdater\SysRedirectRootPageMoveMigration`
The following database table fields have been removed:
- :sql:`tt_content.list_type` :ref:`(Deprecation entry) <deprecation-105076-1726923626>`
The following JavaScript modules have been removed:
- :js:`@typo3/backend/document-save-actions.js` :ref:`(Deprecation entry) <deprecation-103528-1712153304>`
- :js:`@typo3/backend/wizard.js` :ref:`(Deprecation entry) <deprecation-103230-1709202638>`
- :js:`@typo3/t3editor/*` :ref:`(Deprecation entry) <deprecation-102440-1700638677>`
The following JavaScript method behaviours have changed:
- :js:`FormEngineValidation.markFieldAsChanged()` always requires :js:`HTMLInputElement|HTMLTextAreaElement|HTMLSelectElement` to be passed as first argument :ref:`(Deprecation entry) <deprecation-101912-1694611003>`
- :js:`FormEngineValidation.validateField()` always requires :js:`HTMLInputElement|HTMLTextAreaElement|HTMLSelectElement` to be passed as first argument :ref:`(Deprecation entry) <deprecation-101912-1694611003>`
The following JavaScript method has been removed:
- :js:`updateQueryStringParameter()` of :js:`@typo3/backend/utility.js` :ref:`(Deprecation entry) <deprecation-104154-1718802119>`
The following smooth migration for JavaScript modules have been removed:
- :js:`@typo3/backend/page-tree/page-tree-element` to :js:`@typo3/backend/tree/page-tree-element` :ref:`(Deprecation entry) <deprecation-103850-1715873982>`
The following localization XLIFF files have been removed:
- :file:`EXT:backend/Resources/Private/Language/locallang_db_new_content_el.xlf` :ref:`(see referenced change) <breaking-102834-1705491713>`
- :file:`EXT:frontend/Resources/Private/Language/Database.xlf` :ref:`(see referenced change) <breaking-102834-1705491713>`
The following template files have been removed:
- :file:`EXT:fluid_styled_content/Resources/Private/Templates/List.html` :ref:`(Deprecation entry) <deprecation-105076-1726923626>`
The following content element definitions have been removed:
- :typoscript:`tt_content.list` :ref:`(Deprecation entry) <deprecation-105076-1726923626>`
Impact
======
Using above removed functionality will most likely raise PHP fatal level errors,
may change website output or crashes browser JavaScript.
.. index:: Backend, CLI, Database, FlexForm, Fluid, Frontend, JavaScript, LocalConfiguration, PHP-API, RTE, TCA, TSConfig, TypoScript, PartiallyScanned
@@ -0,0 +1,102 @@
.. include:: /Includes.rst.txt
.. _breaking-105549-1742214899:
=======================================================================
Breaking: #105549 - Improved ISO8601 Date Handling in TYPO3 DataHandler
=======================================================================
See :issue:`105549`
Description
===========
The :php-short:`\TYPO3\CMS\Core\DataHandling\DataHandler` PHP API has been
extended to support both qualified and unqualified ISO8601 date formats, in
order to correctly process supplied timezone offsets when provided.
* *Qualified ISO8601:* Includes an explicit timezone offset (for example,
1999-12-11T10:09:00+01:00 or 1999-12-11T10:09:00Z)
* *Unqualified ISO8601:* Omits timezone offsets, representing *LOCALTIME*
(for example, 1999-12-11T10:09:00)
Previously, TYPO3 incorrectly used qualified ISO8601 with `Z` (`UTC+00:00`) to
denote *LOCALTIME* and applied the server's timezone offset, which led to
misinterpretations when another timezone offset was provided, or when real
UTC-0 was intended instead of LOCALTIME. Now, timezone offsets are accurately
applied if supplied, and are based on server localtime if omitted.
TYPO3 will use unqualified ISO8601 dates internally for communication between
FormEngine and the DataHandler API, ensuring timezone offsets are correctly
processed instead of being shifted when supplied to the
:php-short:`\TYPO3\CMS\Core\DataHandling\DataHandler` API.
In essence, this means that existing workarounds for previously applied
timezone offsets should be reviewed and removed.
Impact
======
TYPO3 now provides accurate and consistent handling of ISO8601 dates,
eliminating previous issues related to timezone interpretation and LOCALTIME
representation.
Affected installations
======================
Installations with custom TYPO3 extensions that invoke the
:php-short:`\TYPO3\CMS\Core\DataHandling\DataHandler` API with data for
`type="datetime"` fields are affected.
Migration
=========
Qualified ISO8601 dates with intended timezone offsets and
:php:`\DateTimeInterface` objects can now be passed directly to the
:php-short:`\TYPO3\CMS\Core\DataHandling\DataHandler` without requiring manual
timezone adjustments.
An example of a previous workaround that added timezone offsets for the
DataHandler:
.. code-block:: php
:caption: Passing datetime data via DataHandler PHP API (before)
$myDate = new \DateTime('yesterday');
$this->dataHandler->start([
'tx_myextension_mytable' => [
'NEW-1' => [
'pid' => 2,
// A previous workaround added the localtime offset to supplied
// dates, as it was subtracted by the DataHandler persistence
// layer
'mydatefield_1' => gmdate('c', $myDate->getTimestamp() + (int)date('Z')),
],
],
]);
Previous timezone-shifting workarounds can be removed and replaced with more
intuitive formats.
.. code-block:: php
:caption: Passing datetime data via DataHandler PHP API (after)
$myDate = new \DateTime('yesterday');
$this->dataHandler->start([
'tx_myextension_mytable' => [
'NEW-1' => [
'pid' => 2,
// Pass \DateTimeInterface object directly
'mydatefield_1' => $myDate,
// Format as LOCALTIME
'mydatefield_2' => $myDate->format('Y-m-d\TH:i:s'),
// Format with timezone information
// (offsets will be normalized to the persistence timezone
// format: UTC for integer fields, LOCALTIME for native
// DATETIME fields)
'mydatefield_3' => $myDate->format('c'),
],
],
]);
.. index:: Database, PHP-API, NotScanned, ext:core
@@ -0,0 +1,54 @@
.. include:: /Includes.rst.txt
.. _breaking-105686-1732289792:
=================================================================
Breaking: #105686 - Avoid obsolete $charset in sanitizeFileName()
=================================================================
See :issue:`105686`
Description
===========
The interface
:php:`\TYPO3\CMS\Core\Resource\Driver\DriverInterface` has been updated.
The method signature
.. code-block:: php
public function sanitizeFileName(string $fileName, string $charset = ''): string
has been simplified to:
.. code-block:: php
public function sanitizeFileName(string $fileName): string
Implementing classes no longer need to handle a second argument.
Impact
======
This change has little to no impact, since the main API caller - the Core
class :php-short:`\TYPO3\CMS\Core\Resource\ResourceStorage` - never passed a
second argument. The default implementation,
:php-short:`\TYPO3\CMS\Core\Resource\Driver\LocalDriver`, has therefore always
behaved as if handling UTF-8 strings.
Affected installations
======================
TYPO3 installations with custom File Abstraction Layer (FAL) drivers
implementing :php-short:`\TYPO3\CMS\Core\Resource\Driver\DriverInterface` may
be affected.
Migration
=========
Implementing classes should drop support for the second argument. Retaining it
does not cause a conflict with the interface, but the TYPO3 Core will never
call :php:`sanitizeFileName()` with a second parameter.
.. index:: FAL, PHP-API, NotScanned, ext:core
@@ -0,0 +1,69 @@
.. include:: /Includes.rst.txt
.. _breaking-105695-1732540153:
===============================================
Breaking: #105695 - Simplified CharsetConverter
===============================================
See :issue:`105695`
Description
===========
The following methods have been removed from
:php:`\TYPO3\CMS\Core\Charset\CharsetConverter`:
* :php:`CharsetConverter->conv()`
* :php:`CharsetConverter->utf8_encode()`
* :php:`CharsetConverter->utf8_decode()`
* :php:`CharsetConverter->specCharsToASCII()`, use
:php:`CharsetConverter->utf8_char_mapping()` instead
* :php:`CharsetConverter->sb_char_mapping()`
* :php:`CharsetConverter->euc_char_mapping()`
This removes most helper methods that implemented conversions between different
character sets from the TYPO3 Core. The vast majority of websites now use UTF-8
and no longer require the expensive charset conversions previously provided by
the Core framework.
Impact
======
Calling any of the removed methods will trigger a fatal PHP error.
Affected installations
======================
The TYPO3 Core has not exposed any of this low-level functionality in upper
layers such as TypoScript for quite some time. The removal should therefore
have little to no impact on most installations.
The only cases that *may* be affected are import or export extensions that
perform conversions between legacy character sets (for example, those in the
EUC family). Affected extensions can mitigate this change by copying the
TYPO3 v13 version of the class
:php-short:`\TYPO3\CMS\Core\Charset\CharsetConverter`, including the relevant
files from :file:`core/Resources/Private/Charsets/csconvtbl/`, into their own
codebase.
The extension scanner will detect usages and classify them as weak matches.
Migration
=========
Avoid calling any of the removed methods. Extensions that still require this
functionality should copy the necessary logic into their own codebase or use a
third-party library.
This particular case has a direct substitution:
.. code-block:: php
// Before
$charsetConverter->specCharsToASCII('utf-8', $myString);
// After
$charsetConverter->utf8_char_mapping($myString);
.. index:: PHP-API, FullyScanned, ext:core
@@ -0,0 +1,93 @@
.. include:: /Includes.rst.txt
.. _breaking-105728-1732882067:
==============================================================================================
Breaking: #105728 - Extbase backend modules not in page context rely on global TypoScript only
==============================================================================================
See :issue:`105728`
Description
===========
Configuration of Extbase-based backend modules can be done using frontend
TypoScript.
The standard prefix in TypoScript to do this is
:typoscript:`module.tx_myextension`. Extbase backend module controllers can
typically retrieve their configuration using a call like:
:php:`$configuration = $this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS, 'myextension');`
TypoScript itself is always bound to a page: The frontend must have
either some rootline page with a `sys_template` record or a page that has a site
set, otherwise frontend rendering will terminate with an error message.
Extbase-based backend modules are sometimes bound to pages as well: They can
have a rendered page tree configured in their module configuration and then
receive the selected page UID within the request as GET parameter :php:`id`.
Other Extbase-based backend modules, however, are not inside a page scope and do
not render the page tree. Examples of such modules within the TYPO3 Core are the
backend modules delivered by the `form` and `beuser` extensions.
Such Extbase-based backend modules without a page tree had a hard time
calculating their relevant frontend TypoScript-based configuration: Since
TypoScript is bound to pages, they looked for "the first" valid page in the page
tree, and the first valid `sys_template` record to calculate their TypoScript
configuration. This dependency on guesswork made final configuration of Extbase
backend module configuration not in page context brittle, opaque, and clumsy.
TYPO3 v14 puts an end to this: Extbase backend modules without page context
compile their TypoScript configuration from *global* TypoScript only and no longer
calculating TypoScript by guessing "the first valid" page.
The key call to register such "global" TypoScript is the method
:php:`ExtensionManagementUtility::addTypoScriptSetup()` in
:file:`ext_localconf.php` files.
Impact
======
Configuration of Extbase-based backend modules may change if their configuration
is defined by the first valid page in the page tree. Configuration of such
backend modules can no longer be changed by including TypoScript on the "first
valid" page.
Affected installations
======================
Instances with Extbase-based backend modules without a page tree may be affected.
Migration
=========
Configuration of Extbase-based backend modules without a page tree must be
supplied programmatically and made "global" by extending
:php:`$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_setup']` using
:php:`ExtensionManagementUtility::addTypoScriptSetup()` within extensions
:file:`ext_localconf.php` files. The backend module of the `form` extension is a
good example. Additional locations of extensions that deliver form YAML
definitions are defined like this:
.. code-block:: php
:caption: EXT:my_extension/ext_localconf.php
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
ExtensionManagementUtility::addTypoScriptSetup('
module.tx_form {
settings {
yamlConfigurations {
1732884807 = EXT:my_extension/Configuration/Yaml/FormSetup.yaml
}
}
}
');
Note it is also possible to use the method
:php:`ExtensionManagementUtility::addTypoScriptConstants()` to declare "global"
TypoScript constants and to use them in the TypoScript shown above.
.. index:: Backend, PHP-API, TypoScript, NotScanned, ext:extbase
@@ -0,0 +1,41 @@
.. include:: /Includes.rst.txt
.. _breaking-105733-1733018161:
=====================================================================================
Breaking: #105733 - FileNameValidator no longer accepts custom regex in __construct()
=====================================================================================
See :issue:`105733`
Description
===========
The class :php-short:`\TYPO3\CMS\Core\Resource\Security\FileNameValidator` no
longer accepts a custom file deny pattern in :php:`__construct()`. The service
is now stateless and can be injected without side effects.
Impact
======
A custom partial regex passed as the first constructor argument when
instantiating the service is now ignored. The service relies on
:php:`$GLOBALS['TYPO3_CONF_VARS']['BE']['fileDenyPattern']` configuration and a
hard-coded constant as a fallback.
Affected installations
======================
Instances with custom extensions using
:php:`GeneralUtility::makeInstance(FileNameValidator::class, 'some-custom-pattern');`
are affected. This is expected to be a very rare case.
Migration
=========
Extensions that need to be tested with custom patterns that cannot be declared
globally using :php:`$GLOBALS['TYPO3_CONF_VARS']['BE']['fileDenyPattern']`
should implement their own service for this purpose or inline the necessary
code. The core implementation performing the check is only a few lines long.
.. index:: PHP-API, NotScanned, ext:core
@@ -0,0 +1,40 @@
.. include:: /Includes.rst.txt
.. _breaking-105809-1733928218:
==========================================================
Breaking: #105809 - AfterMailerInitializationEvent removed
==========================================================
See :issue:`105809`
Description
===========
The event :php:`\TYPO3\CMS\Core\Mail\Event\AfterMailerInitializationEvent`
has been removed. This event became obsolete with the introduction of the
Symfony-based mailer in TYPO3 v10. It was only able to influence the TYPO3 Core
mailer by calling the :php:`@internal` method :php:`injectMailSettings()` *after*
the settings had already been determined. The event has been removed since it
no longer had a meaningful use case.
Impact
======
Event listeners registered for this event will no longer be triggered.
Affected installations
======================
This event has had little purpose since the switch to the Symfony-based mailer
and is probably not used in most instances. The extension scanner will find
usages.
Migration
=========
Check if this event can be substituted by reconfiguring
:php:`$GLOBALS['TYPO3_CONF_VARS']['MAIL']`, or by listening for the event
:php-short:`\TYPO3\CMS\Core\Mail\Event\BeforeMailerSentMessageEvent` instead.
.. index:: PHP-API, FullyScanned, ext:core
@@ -0,0 +1,68 @@
.. include:: /Includes.rst.txt
.. _breaking-105855-1734686200:
==============================================================================
Breaking: #105855 - Remove file backwards compatibility for alt and link field
==============================================================================
See :issue:`105855`
Description
===========
When the File Abstraction Layer (FAL) was introduced, the TYPO3 Core file fields
`media` for table `pages`, and `image` and `assets` for table
`tt_content`, had their so-called "overlay palettes" overridden to
`imageOverlayPalette`, so that additional fields like `alternative`, `link`, and
`crop` were displayed. However, this was done for all file types, including
`text`, `application`, and the fallback type `unknown`. For these types, the
additional fields served no meaningful purpose. For this reason, they have now
been removed.
Impact
======
The TYPO3 Core file fields `media` for table `pages`, `image` and
`assets` for table `tt_content`, will no longer display the fields
`alternative` and `link` for file types other than `image`.
Affected installations
======================
This affects installations that use one of the Core fields for file types
other than `image` (for example `text` or `application`) and make use of the
fields `alternative` and/or `link`.
This should not affect many installations, as these fields are used primarily
for images.
Migration
=========
These fields can be restored using TCA overrides if necessary. First,
register a new palette for the `sys_file_reference` table containing the desired
set of fields.
.. code-block:: php
:caption: EXT:my_extension/Configuration/TCA/Overrides/sys_file_reference.php
$GLOBALS['TCA']['sys_file_reference']['palettes']['myCustomPalette'] = [
'label' => 'My custom palette',
'showitem' => 'alternative,description,--linebreak--,link,title',
];
Then, use this palette for your specific Core field and file type. The following
example restores the fields `alternative` and `link` for the `media` field of
the `pages` table when the file type is `text`.
.. code-block:: php
:caption: EXT:my_extension/Configuration/TCA/Overrides/pages.php
use TYPO3\CMS\Core\Resource\FileType;
$GLOBALS['TCA']['pages']['columns']['media']['config']['overrideChildTca']
['types'][FileType::TEXT->value]['showitem'] =
'--palette--;;myCustomPalette,--palette--;;filePalette';
.. index:: FAL, TCA, NotScanned, ext:core
@@ -0,0 +1,42 @@
.. include:: /Includes.rst.txt
.. _breaking-105863-1735234295:
===============================================================================================
Breaking: #105863 - Remove `exposeNonexistentUserInForgotPasswordDialog` setting in EXT:felogin
===============================================================================================
See :issue:`105863`
Description
===========
The TypoScript setting
:php:`exposeNonexistentUserInForgotPasswordDialog` has been removed in
EXT:felogin.
Impact
======
Using the TypoScript setting
:php:`exposeNonexistentUserInForgotPasswordDialog` has no effect anymore. The
password recovery process in `EXT:felogin` now always shows the same message
when a username or email address is submitted in the password recovery form.
Affected installations
======================
Websites using the TypoScript setting
:php:`exposeNonexistentUserInForgotPasswordDialog` in EXT:felogin are affected.
Migration
=========
The setting has been removed without replacement. It is possible to use the
PSR-14 event
:php-short:`\TYPO3\CMS\FrontendLogin\Event\SendRecoveryEmailEvent` to implement
similar functionality if absolutely necessary. From a security perspective,
however, it is strongly recommended not to expose the existence of email
addresses or usernames.
.. index:: Frontend, NotScanned, ext:felogin
@@ -0,0 +1,81 @@
.. include:: /Includes.rst.txt
.. _breaking-105920-1736777357:
=============================================================================
Breaking: #105920 - Folder->getSubFolder() throws FolderDoesNotExistException
=============================================================================
See :issue:`105920`
Description
===========
An exception handling detail within the **File Abstraction Layer (FAL) resource
handling** has been changed. When calling
:php:`getSubFolder('mySubFolderName')` on a
:php-short:`\TYPO3\CMS\Core\Resource\Folder` object, and if this subfolder does
not exist, the specific
:php:`\TYPO3\CMS\Core\Resource\Exception\FolderDoesNotExistException` is
now raised instead of the global :php:`\InvalidArgumentException`.
Impact
======
The change may affect extensions that directly or indirectly call
:php:`Folder->getSubFolder()` and expect a :php:`\InvalidArgumentException` to
be thrown.
Affected installations
======================
:php-short:`\TYPO3\CMS\Core\Resource\Exception\FolderDoesNotExistException` does not extend
:php:`\InvalidArgumentException`. Code that currently expects a
:php:`\InvalidArgumentException` to be thrown needs to be adapted.
Migration
=========
The change is breaking for code that takes an "optimistic" approach like:
"get the subfolder object, and if this throws, create one". Example:
.. code-block:: php
try {
$mySubFolder = $myFolder->getSubFolder('mySubFolder');
} catch (\InvalidArgumentException) {
$mySubFolder = $myFolder->createFolder('mySubFolder');
}
This should be changed to catch a
:php-short:`\TYPO3\CMS\Core\Resource\Exception\FolderDoesNotExistException`
instead:
.. code-block:: php
use TYPO3\CMS\Core\Resource\Exception\FolderDoesNotExistException;
try {
$mySubFolder = $myFolder->getSubFolder('mySubFolder');
} catch (FolderDoesNotExistException) {
$mySubFolder = $myFolder->createFolder('mySubFolder');
}
Extensions that need to stay compatible with both TYPO3 v13 and v14 should catch
both exceptions and should later avoid catching
:php:`\InvalidArgumentException` when v13 compatibility is dropped:
.. code-block:: php
use TYPO3\CMS\Core\Resource\Exception\FolderDoesNotExistException;
try {
$mySubFolder = $myFolder->getSubFolder('mySubFolder');
} catch (\InvalidArgumentException|FolderDoesNotExistException) {
// @todo: Remove \InvalidArgumentException from catch list when
// TYPO3 v13 compatibility is dropped.
$mySubFolder = $myFolder->createFolder('mySubFolder');
}
.. index:: FAL, PHP-API, NotScanned, ext:core
@@ -0,0 +1,44 @@
.. include:: /Includes.rst.txt
.. _breaking-106041-1738329944:
========================================================================================================
Breaking: #106041 - TypoScript Extbase toggle config.tx_extbase.persistence.updateReferenceIndex removed
========================================================================================================
See :issue:`106041`
Description
===========
Extbase previously supported the TypoScript toggle
:typoscript:`config.tx_extbase.persistence.updateReferenceIndex` to control
whether the reference index should be updated when records are persisted.
It has become increasingly important that the reference index is always kept
up to date, since an increasing number of TYPO3 Core components rely on current
reference index data. Using the reference index at key points can improve read
and rendering performance significantly.
This toggle has been removed. Reference index updating is now always enabled.
Impact
======
The change may slightly increase database load, which can become noticeable
when Extbase updates many records at once.
Affected installations
======================
Instances with extensions that write many records using the Extbase persistence
layer may be affected.
Migration
=========
The TypoScript toggle
:typoscript:`config.tx_extbase.persistence.updateReferenceIndex` should be
removed from any extension codebase, as it is now ignored by Extbase.
.. index:: TypoScript, NotScanned, ext:extbase
@@ -0,0 +1,42 @@
.. include:: /Includes.rst.txt
.. _breaking-106056-1741414380:
===============================================================================
Breaking: #106056 - Add setRequest and getRequest to Extbase ValidatorInterface
===============================================================================
See :issue:`106056`
Description
===========
Custom validators implementing
:php:`\TYPO3\CMS\Extbase\Validation\Validator\ValidatorInterface` must now
also implement the methods :php:`setRequest()` and :php:`getRequest()`.
Impact
======
Missing implementations of the methods :php:`setRequest()` and
:php:`getRequest()` will now result in a PHP fatal error.
Affected installations
======================
TYPO3 installations with custom extensions implementing
:php-short:`\TYPO3\CMS\Extbase\Validation\Validator\ValidatorInterface`.
Migration
=========
The methods :php:`setRequest()` and :php:`getRequest()` must be implemented in
affected validators.
If there is no need to directly implement
:php-short:`\TYPO3\CMS\Extbase\Validation\Validator\ValidatorInterface`, it is
recommended to extend
:php-short:`\TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator`, where
both methods are already implemented.
.. index:: Backend, NotScanned, ext:extbase
@@ -0,0 +1,40 @@
.. include:: /Includes.rst.txt
.. _breaking-106118-1738942498:
==================================================================
Breaking: #106118 - Property DataHandler->storeLogMessages removed
==================================================================
See :issue:`106118`
Description
===========
The public property
:php:`\TYPO3\CMS\Core\DataHandling\DataHandler->storeLogMessages` has
been removed without substitution. It should no longer be used by extensions.
Impact
======
Setting or reading the property in an extension will now raise a PHP warning-
level error.
Affected installations
======================
Instances with extensions that access this property are affected. This should
be a very rare use case. No TYPO3 Extension Repository (TER) extensions were
affected during verification. The extension scanner is configured to find
usages as a weak match.
Migration
=========
The property has been removed. Any code setting or reading it from
:php:`\TYPO3\CMS\Core\DataHandling\DataHandler` instances should be removed. The
:php:`DataHandler->log()` method now always writes the given :php:`$details`
to the :sql:`sys_log` table.
.. index:: PHP-API, FullyScanned, ext:core
@@ -0,0 +1,128 @@
.. include:: /Includes.rst.txt
.. _breaking-106307-1763824774:
=================================================================
Breaking: #106307 - Use stronger cryptographic algorithm for HMAC
=================================================================
See :issue:`106307`
Description
===========
TYPO3 now uses SHA3-256 for HMAC operations across multiple components,
replacing the previously used MD5, SHA1, and SHA256 algorithms. SHA3-256
(Keccak) produces 64-character hexadecimal hashes compared to the 32 or
40 characters of the older algorithms.
The following components have been upgraded:
================================== ============== ===============
Component Previous HMAC New HMAC
================================== ============== ===============
cHash MD5 SHA3-256
Backend password recovery SHA1 SHA3-256
Frontend password recovery SHA1 SHA3-256
File dump controller SHA1 SHA3-256
Show image controller SHA1 SHA3-256
Backend form protection SHA1 SHA3-256
Extbase form request attributes SHA1 SHA3-256
Form extension request attributes SHA1 SHA3-256
Database session backend SHA256 SHA3-256
Redis session backend SHA256 SHA3-256
================================== ============== ===============
Database fields have been extended to accommodate the longer hash values
(and would even support SHA3-512 with 128 hexadecimal characters in the
future):
* `be_users.password_reset_token`: 100 → 128 characters
* `fe_users.felogin_forgotHash`: 80 → 160 characters
(including additional timestamp details)
Impact
======
The algorithm change has the following immediate effects:
**URLs with HMAC tokens become invalid:**
* cHash parameters in frontend URLs are invalidated
* File dump URLs (file downloads) require regeneration
* Show image URLs require regeneration
**Active password reset tokens expire:**
* Backend user password reset links in progress become invalid
* Frontend user password reset links in progress become invalid
* Users must request new password reset emails
**Session handling:**
* Existing session identifiers will be regenerated on next user login
* No immediate session invalidation occurs
**Database schema:**
* Field lengths are automatically updated during upgrade
* No data migration is required for existing records
Affected installations
======================
All installations upgrading to TYPO3 v14 are affected.
The impact varies based on usage:
* **High impact**: installations with active password reset processes or
cached frontend URLs with cHash parameters
* **Medium impact**: installations using file dump or show image
controllers with externally stored URLs
* **Low impact**: all other installations (automatic migration on next
use)
Migration
=========
**Database schema updates:**
Execute the database analyzer in the Install Tool or run
:bash:`vendor/bin/typo3 upgrade:run`.
**URLs and caching:**
* Frontend caches should be cleared to regenerate cHash values
* File dump and show image URLs regenerate automatically on next access
* External references to file or image URLs must be updated
.. important::
Existing links with `&cHash=` URL parameters will become invalid and
respond with an HTTP 404 error. Search engines first need to crawl the
site and discover the new URLs that contain the longer cache hash
value. This likely has an impact on SEO.
:php:`$GLOBALS['TYPO3_CONF_VARS']['FE']['cacheHash']['fallbackToLegacyHash'] = true;`
can be used to still allow the legacy MD5 cache hash during
frontend requests.
**Sessions:**
No manual intervention is required. Sessions are automatically rehashed on
next login.
**Custom extensions:**
If custom code uses :php:`HashService::hmac()` directly, review whether the
default SHA1 algorithm is still appropriate. Consider explicitly passing
:php:`HashAlgo::SHA3_256` for new HMAC operations:
.. code-block:: php
use TYPO3\CMS\Core\Crypto\HashAlgo;
use TYPO3\CMS\Core\Crypto\HashService;
$hash = $hashService->hmac($data, 'my-additional-secret', HashAlgo::SHA3_256);
.. index:: Backend, Database, Frontend, NotScanned, ext:core
@@ -0,0 +1,121 @@
.. include:: /Includes.rst.txt
.. _breaking-106405-1742674605:
=====================================================
Breaking: #106405 - TypolinkBuilder signature changes
=====================================================
See :issue:`106405`
Description
===========
To enable dependency injection for TypolinkBuilder classes, several breaking
changes were introduced to the TypolinkBuilder architecture.
The following breaking changes have been made:
* The constructor of
:php-short:`\TYPO3\CMS\Frontend\Typolink\AbstractTypolinkBuilder` has been
removed. Extending classes can no longer rely on receiving
:php-short:`\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer` and
:php-short:`\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController`
through the constructor.
* All concrete TypolinkBuilder implementations now implement the new
:php-short:`\TYPO3\CMS\Frontend\Typolink\TypolinkBuilderInterface` and use
dependency injection via their constructors instead of extending
:php-short:`\TYPO3\CMS\Frontend\Typolink\AbstractTypolinkBuilder` with
constructor arguments.
* The method signature of the main link-building method has changed from
:php:`build(array &$linkDetails, string $linkText, string $target, array $conf)`
to
:php:`buildLink(array $linkDetails, array $configuration, ServerRequestInterface $request, string $linkText = '')`.
Impact
======
Custom TypolinkBuilder implementations extending
:php-short:`\TYPO3\CMS\Frontend\Typolink\AbstractTypolinkBuilder` will fail
with fatal errors due to the removed constructor and changed method signatures.
Extensions that instantiate TypolinkBuilder classes directly will also fail,
as the constructor signatures have fundamentally changed to use dependency
injection.
Affected installations
======================
TYPO3 installations with extensions that:
* Create custom TypolinkBuilder classes extending
:php-short:`\TYPO3\CMS\Frontend\Typolink\AbstractTypolinkBuilder`
* Directly instantiate TypolinkBuilder classes in PHP code
* Override or extend the :php:`build()` method of TypolinkBuilder classes
Migration
=========
For custom TypolinkBuilder implementations:
1. Implement
:php-short:`\TYPO3\CMS\Frontend\Typolink\TypolinkBuilderInterface`
2. Use dependency injection in the constructor for required services
3. Replace the :php:`build()` method with :php:`buildLink()`
Note: Classes implementing
:php-short:`\TYPO3\CMS\Frontend\Typolink\TypolinkBuilderInterface` are
automatically configured as public services in the dependency injection
container - no manual configuration is required.
Example migration:
.. code-block:: php
:caption: Before (TYPO3 v13 and lower)
use TYPO3\CMS\Frontend\Typolink\AbstractTypolinkBuilder;
class MyCustomLinkBuilder extends AbstractTypolinkBuilder
{
public function build(array &$linkDetails, string $linkText, string $target, array $conf): LinkResultInterface
{
// Custom link building logic
return new LinkResult('news', $linkText);
}
}
.. code-block:: php
:caption: After (TYPO3 v14+)
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Frontend\Typolink\TypolinkBuilderInterface;
class MyCustomLinkBuilder implements TypolinkBuilderInterface
{
public function __construct(
// Inject required dependencies
) {}
public function buildLink(
array $linkDetails,
array $configuration,
ServerRequestInterface $request,
string $linkText = '',
): LinkResultInterface {
// Custom link building logic - access ContentObjectRenderer via:
$contentObjectRenderer = $request->getAttribute('currentContentObject');
return new LinkResult('news', $linkText);
}
}
For code that instantiates TypolinkBuilder classes directly:
It is strongly recommended to use the
:php-short:`\TYPO3\CMS\Frontend\Typolink\LinkFactory` instead of instantiating
TypolinkBuilder classes directly. The
:php-short:`\TYPO3\CMS\Frontend\Typolink\LinkFactory` handles proper
instantiation and dependency injection automatically.
.. index:: PHP-API, NotScanned, ext:frontend
@@ -0,0 +1,56 @@
.. include:: /Includes.rst.txt
.. _breaking-106412-1742592429:
================================================================
Breaking: #106412 - TCA interface settings for list view removed
================================================================
See :issue:`106412`
Description
===========
Each TCA definition previously had an optional section named
:php:`['interface']`, which defined parameters for displaying TCA records.
The last remaining options within this section,
:php:`$GLOBALS['TCA'][$table]['interface']['maxSingleDBListItems']` and
:php:`$GLOBALS['TCA'][$table]['interface']['maxDBListItems']`, have been
removed. As a result, the entire :php:`['interface']` section is no longer
supported and will be ignored.
These settings were used to define the number of table rows displayed within
the :guilabel:`Content > List` backend module.
Impact
======
The :php:`$GLOBALS['TCA'][$table]['interface']` section in TCA definitions is
no longer evaluated.
Setting any values under this key in custom extensions has no effect and will
be automatically removed during build time.
Affected installations
======================
TYPO3 installations with custom TCA settings defining
:php:`$GLOBALS['TCA'][$table]['interface']` are affected.
Migration
=========
Visual display settings can still be overridden on a per-user or per-page
basis via TSconfig. This approach is more flexible, as it allows rendering
different numbers of items per site, page tree, or user group.
The TCA option
:php:`$GLOBALS['TCA'][$table]['interface']['maxSingleDBListItems']` has been
removed in favor of :tsconfig:`mod.web_list.itemsLimitSingleTable`.
The TCA option
:php:`$GLOBALS['TCA'][$table]['interface']['maxDBListItems']` has been removed
in favor of :tsconfig:`mod.web_list.itemsLimitPerTable`.
.. index:: TCA, NotScanned, ext:backend
@@ -0,0 +1,68 @@
.. include:: /Includes.rst.txt
.. _breaking-106427-1742911405:
==========================================================
Breaking: #106427 - File Abstraction Layer related changes
==========================================================
See :issue:`106427`
Description
===========
In TYPO3 v14, the PHP API of the **File Abstraction Layer (FAL)** has undergone
major internal changes that may affect extension authors.
1. Most PHP classes and interfaces within FAL are now strongly typed using
native PHP type declarations.
2. Several methods have been moved from
:php-short:`\TYPO3\CMS\Core\Resource\AbstractFile` to its concrete
implementation :php-short:`\TYPO3\CMS\Core\Resource\File`, since only this
class should provide such behavior. The moved methods are:
- :php:`AbstractFile->rename()`
- :php:`AbstractFile->copyTo()`
- :php:`AbstractFile->moveTo()`
3. The :php-short:`\TYPO3\CMS\Core\Resource\FileInterface` method
:php:`rename()` has been removed, as this operation is only relevant to the
concrete :php-short:`\TYPO3\CMS\Core\Resource\File` implementation.
4. Classes implementing :php-short:`\TYPO3\CMS\Core\Resource\FolderInterface`
must now implement the following methods to stay compatible with the new
:php-short:`\TYPO3\CMS\Core\Resource\Folder` class:
- :php:`getSubFolder()`
- :php:`getReadablePath()`
- :php:`getFiles()`
- :php:`searchFiles()`
Previously, this was not enforced, but it is now required to make
:php:`Folder` more interchangeable across implementations.
Impact
======
Calling PHP classes or methods from the File Abstraction Layer directly may
result in fatal PHP errors if incorrect or missing argument types are used.
Affected installations
======================
TYPO3 installations with third-party extensions that interact with the FAL PHP
API in non-documented ways.
Migration
=========
Ensure that all FAL-related code passes and expects the correct PHP types when
using or extending the API.
If you provide custom implementations of
:php-short:`\TYPO3\CMS\Core\Resource\FolderInterface` or classes extending
:php-short:`\TYPO3\CMS\Core\Resource\AbstractFile`, make sure to implement the
newly required methods accordingly.
.. index:: FAL, PHP-API, NotScanned, ext:core
@@ -0,0 +1,55 @@
.. include:: /Includes.rst.txt
.. _breaking-106503-1743667328:
============================================================
Breaking: #106503 - Removal of fields from sys_file_metadata
============================================================
See :issue:`106503`
Description
===========
The following database fields and corresponding TCA definitions have been
removed from the database table :sql:`sys_file_metadata` without substitution:
- :sql:`visible`
- :sql:`fe_groups`
These fields were added to the table when the system extension
EXT:filemetadata was installed.
Although the field names suggested access control functionality similar to
those found in other TYPO3 tables, they were never configured to restrict
frontend or backend access. Their intended meaning would have depended on
custom implementation and was not supported by the TYPO3 Core.
Additionally, the field :sql:`status` has been moved from the *Access* tab to
the *Metadata* tab to avoid the impression that this field has any restrictive
behavior.
Impact
======
The fields :sql:`visible` and :sql:`fe_groups` in :sql:`sys_file_metadata` are
no longer used. After performing a **Database Compare** in the Install Tool,
these columns will be removed and their data permanently lost.
Accessing these fields in PHP or TypoScript will result in PHP warnings.
Affected installations
======================
Any TYPO3 installation using the fields :sql:`visible` or :sql:`fe_groups`
provided by the system extension EXT:filemetadata is affected.
Migration
=========
No automatic migration is available.
If the fields are still required for custom logic, reintroduce their database
columns and TCA configuration within a custom extension.
.. index:: TCA, NotScanned, ext:filemetadata
@@ -0,0 +1,92 @@
.. include:: /Includes.rst.txt
.. _breaking-106596-1746896335:
================================================
Breaking: #106596 - Remove legacy form templates
================================================
See :issue:`106596`
Description
===========
In earlier TYPO3 versions, the Form Framework provided two template variants
for frontend rendering:
- The initial, legacy templates in
:file:`EXT:form/Resources/Private/Frontend/Templates` and
:file:`EXT:form/Resources/Private/Frontend/Partials`, which were deprecated
in :issue:`95456`
- The newer, Bootstrap 5 compatible and accessible templates in
:file:`EXT:form/Resources/Private/FrontendVersion2/Templates` and
:file:`EXT:form/Resources/Private/FrontendVersion2/Partials`, introduced
with :issue:`94868`
The legacy form templates have now been removed. The rendering option
:yaml:`templateVariant`, which toggled the template and form configuration
variant, has been removed as well.
The newer template variants have been moved to the original file paths of the
legacy templates.
Impact
======
The removal of the legacy templates and the :yaml:`templateVariant`
configuration option simplifies the Form Framework rendering logic.
Developers no longer need to choose between multiple template variants,
reducing complexity and improving maintainability. Projects already using the
newer templates benefit from a cleaner configuration and a unified rendering
approach.
Affected installations
======================
All TYPO3 installations using the Form Framework are affected.
Migration
=========
If you still rely on the legacy templates, you must migrate your templates and
partials to the structure of the newer templates.
Websites that use :yaml:`templateVariant: version2` can simplify their form
configuration. Variants with the condition
:yaml:`'getRootFormProperty("renderingOptions.templateVariant") == "version2"'`
are no longer necessary and can be removed.
**Before:**
.. code-block:: yaml
prototypes:
standard:
formElementsDefinition:
Text:
variants:
-
identifier: template-variant
condition: 'getRootFormProperty("renderingOptions.templateVariant") == "version2"'
properties:
containerClassAttribute: 'form-element form-element-text mb-3'
elementClassAttribute: form-control
elementErrorClassAttribute: ~
labelClassAttribute: form-label
**After:**
.. code-block:: yaml
prototypes:
standard:
formElementsDefinition:
Text:
properties:
containerClassAttribute: 'form-element form-element-text mb-3'
elementClassAttribute: form-control
elementErrorClassAttribute: ~
labelClassAttribute: form-label
.. index:: Frontend, YAML, NotScanned, ext:form
@@ -0,0 +1,48 @@
.. include:: /Includes.rst.txt
.. _breaking-106863-1749629371:
========================================================
Breaking: #106863 - TCA control option is_static removed
========================================================
See :issue:`106863`
Description
===========
The TCA control option
:php:`$GLOBALS['TCA'][$table]['ctrl']['is_static']` has been removed, as it is
no longer evaluated by the TYPO3 Core.
Originally, this option was introduced to mark certain database tables (for
example, from :sql:`static_info_tables`) as containing static, non-editable
reference data. Over time, the TYPO3 ecosystem has evolved, and the original
purpose of `is_static` has become obsolete.
Modern TYPO3 installations rarely rely on static data tables. Better mechanisms
now exist for managing read-only or reference data, such as the TCA options
`readOnly` and `editlock`, or backend access control. Removing this
legacy option improves maintainability and reduces complexity for newcomers.
Impact
======
The option `is_static` is no longer evaluated. It is automatically removed
at runtime by a TCA migration, and a deprecation log entry is generated to
indicate where adjustments are required.
Affected installations
======================
All TYPO3 installations defining
:php:`$GLOBALS['TCA'][$table]['ctrl']['is_static']` in their TCA configuration
are affected.
Migration
=========
Remove the `is_static` option from the `ctrl` section of your TCA
configuration.
.. index:: TCA, FullyScanned, ext:core
@@ -0,0 +1,46 @@
.. include:: /Includes.rst.txt
.. _breaking-106869-1749659916:
=============================================================================
Breaking: #106869 - Remove static function parameter in AuthenticationService
=============================================================================
See :issue:`106869`
Description
===========
The method :php:`\TYPO3\CMS\Core\Authentication\AuthenticationService::processLoginData()`
no longer accepts the parameter :php:`$passwordTransmissionStrategy`.
Additionally, the method now declares a strict return type.
Impact
======
Authentication services extending or overriding
:php-short:`\TYPO3\CMS\Core\Authentication\AuthenticationService`
and its method :php:`processLoginData()` (or a subtype such as
:php:`processLoginDataBE()` or :php:`processLoginDataFE()`) will no longer
receive the :php:`$passwordTransmissionStrategy` parameter.
Affected installations
======================
TYPO3 installations with custom authentication services that extend
:php-short:`\TYPO3\CMS\Core\Authentication\AuthenticationService`
and implement or override :php:`processLoginData()` or one of its subtypes.
Migration
=========
Extensions extending
:php-short:`\TYPO3\CMS\Core\Authentication\AuthenticationService`
must remove the :php:`$passwordTransmissionStrategy` parameter from their
method signature and add the strict return type :php:`bool|int`.
Extensions implementing subtype methods such as
:php:`processLoginDataBE()` or :php:`processLoginDataFE()` must also remove the
parameter, as it is no longer passed to these methods.
.. index:: Backend, NotScanned, ext:core
@@ -0,0 +1,51 @@
.. include:: /Includes.rst.txt
.. _breaking-106949-1750763567:
=======================================================================
Breaking: #106949 - Duplicate doktype restriction configuration removed
=======================================================================
See :issue:`106949`
Description
===========
The TSconfig option :tsconfig:`mod.web_list.noViewWithDokTypes` has been
removed, as it duplicated the existing configuration
:tsconfig:`TCEMAIN.preview.disableButtonForDokType`.
Since :issue:`96861`, the latter has been established as the single source of
truth for disabling the *View* button for specific :sql:`doktype` values.
Impact
======
The option :tsconfig:`mod.web_list.noViewWithDokTypes` is no longer evaluated.
Only the configuration :tsconfig:`TCEMAIN.preview.disableButtonForDokType`
is now respected.
Affected installations
======================
TYPO3 installations that still rely on
:tsconfig:`mod.web_list.noViewWithDokTypes` in Page TSconfig to control the
visibility of the *View* button in backend modules are affected.
Migration
=========
Remove any usage of :tsconfig:`mod.web_list.noViewWithDokTypes` from Page
TSconfig.
Use the existing configuration
:tsconfig:`TCEMAIN.preview.disableButtonForDokType` instead:
.. code-block:: typoscript
:caption: EXT:site_package/Configuration/TSconfig/Page/TCEMAIN.tsconfig
TCEMAIN.preview.disableButtonForDokType = 199, 254
This change ensures consistent behavior and avoids duplicate configuration.
.. index:: TSConfig, NotScanned, ext:backend
@@ -0,0 +1,54 @@
.. include:: /Includes.rst.txt
.. _breaking-106964-1750837443:
==========================================================================================
Breaking: #106964 - Enable "Light/Dark Mode" context awareness for CKEditor RTE by default
==========================================================================================
See :issue:`106964`
Description
===========
With :issue:`105640`, context awareness for the CKEditor Rich Text Editor (RTE)
was introduced, allowing the editor interface to automatically adapt to the
users system-wide light or dark mode preference.
This feature is now enabled by default. The TYPO3 Core stylesheet
:file:`EXT:rte_ckeditor/Resources/Public/Css/contents.css` has been updated to
support light and dark mode variants automatically. Previously fixed white
backgrounds now adapt dynamically based on the editors preferred color scheme.
Note that this change affects only the backend editor interface. The display of
RTE content in the frontend remains unaffected.
Impact
======
The previously fixed *light mode* user interface of the CKEditor RTE is now
context-aware, displaying content in light or dark mode according to the
editors system preference.
Affected installations
======================
TYPO3 installations that rely on a fixed *light mode* presentation of CKEditor
RTE instances in the backend are affected.
Migration
=========
Installations with custom CKEditor modifications should review their
:file:`contents.css` file.
If the TYPO3 Core default stylesheet was previously used, and a fixed *light
mode* appearance is desired, this can be enforced in the RTE YAML
configuration:
.. code-block:: yaml
:caption: EXT:my_extension/Configuration/RTE/MyCKPreset.yaml
editor.config.contentsCss:
- "EXT:my_extension/Resources/Public/Css/CustomContents.css"
.. index:: Backend, NotScanned
@@ -0,0 +1,60 @@
.. include:: /Includes.rst.txt
.. _breaking-106972-1750856858:
===========================================================
Breaking: #106972 - TCA control option searchFields removed
===========================================================
See :issue:`106972`
Description
===========
The TCA control option :php:`$GLOBALS['TCA'][$table]['ctrl']['searchFields']`
has been removed.
With the introduction of the Schema API and the
:php:`\TYPO3\CMS\Core\Schema\SearchableSchemaFieldsCollector` component,
the handling of fields included in searches has changed. By default, all
fields of suitable types, such as `input` or `text`, are now automatically
considered searchable.
To manually define searchable fields, use the new :php:`searchable` field
configuration option within a field's TCA configuration.
See the full list of supported field types
:ref:`here <feature-106972-1750856721>`.
Unsupported field types (such as `file`, `inline`, etc.) are not considered
searchable and do not support the `searchable` option.
.. note::
This change does not affect the Page TSconfig option used by
EXT:linkvalidator: :tsconfig:`mod.linkvalidator.searchFields`.
Impact
======
The `searchFields` option is no longer evaluated. It is automatically
removed at runtime through a TCA migration, and a deprecation log entry is
generated to highlight where adjustments are required.
If :ref:`suitable <feature-106972-1750856721>` fields are detected that were
not listed in the removed :php:`searchFields` option, they are automatically
set to :php:`searchable => false` to preserve previous behavior.
Affected installations
======================
All installations that define `searchFields` in their TCA configuration.
Migration
=========
Remove the `searchFields` option from the `ctrl` section of your TCA
configuration.
If needed, use the `searchable` option in individual field definitions
to control which fields are included in the search functionality.
.. index:: TCA, FullyScanned, ext:core
@@ -0,0 +1,63 @@
.. include:: /Includes.rst.txt
.. _breaking-106976-1750865819:
=====================================================================
Breaking: #106976 - Removal of TCA search field configuration options
=====================================================================
See :issue:`106976`
Description
===========
The following TCA field-level search configuration options have been **removed**:
* :php:`search.case`
* :php:`search.pidonly`
* :php:`search.andWhere`
These options were originally intended to customize backend record search
behavior but have proven to be of little practical value:
- They were not used in the TYPO3 Core,
- They were not used in common third-party extensions,
- Their behavior was unclear and inconsistently supported,
- They were insufficiently documented and hard to validate.
This removal is part of the ongoing effort to simplify and streamline TCA
configuration and reduce unnecessary complexity for integrators.
Impact
======
These options are no longer evaluated. They are automatically removed at
runtime through a TCA migration, and a deprecation log entry is generated to
highlight where adjustments are required.
Affected installations
======================
Any installation or extension that defines one or more of these options in its
TCA field configuration:
.. code-block:: diff
:caption: Example of removed TCA options
'my_field' => [
'config' => [
'type' => 'input',
- 'search' => [
- 'case' => true,
- 'pidonly' => true,
- 'andWhere' => '{#CType}=\'text\'',
- ],
],
],
Migration
=========
Remove the obsolete :php:`search` options from your TCA field configurations.
.. index:: TCA, FullyScanned, ext:core
@@ -0,0 +1,259 @@
.. include:: /Includes.rst.txt
.. _breaking-107047-1751982363:
==================================================================
Breaking: #107047 - Remove pointer field functionality of TCA flex
==================================================================
See :issue:`107047`
Description
===========
One of the main features of TCA is the concept of *record types*. This allows
using a single table for different purposes and in different contexts. The
most well-known examples are the "Page Types" of the :sql:`pages` table and the
"Content Types" of the :sql:`tt_content` table. For every specific type, it is
possible to define which fields to display and to customize their
configuration.
A special case historically has been plugin registration, which for a long
time used the so-called *subtypes* feature of TCA. This was an additional layer
below record types, configured using `subtype_value_field` (commonly
`list_type`), and optionally `subtypes_addlist` and
`subtypes_excludelist` to add or remove fields depending on the selected
subtype.
FlexForms attached to such subtypes were configured using
`ds_pointerField` (typically pointing to `list_type,CType`). This came in
combination with the corresponding `ds` configuration, which was an array
with keys combining the pointer fields, for example:
.. code-block:: php
'ds_pointerField' => 'list_type,CType',
'ds' => [
'news_pi1,list' => 'FILE:EXT:news/Configuration/FlexForm.xml',
'default' => 'FILE:...'
],
Over recent TYPO3 versions, this approach has been deprecated in favor of
using record types exclusively for plugin registration via the `CType` field,
making configuration cleaner and easier to understand.
The special plugin content element (`CType=list`) and the corresponding plugin
subtype field `list_type` have been deprecated in
:ref:`deprecation-105076-1726923626` and removed in
:ref:`breaking-105377-1729513863`.
See also :ref:`important-105538-1730752784` for related information about
:php:`ExtensionUtility::configurePlugin()` and
:php:`ExtensionManagementUtility::addTcaSelectItemGroup()`.
With this change, support for `ds_pointerField` and the multi-entry
`ds` array format has now been removed. The `ds` option now points to
a single FlexForm, either directly or via a `FILE:` reference.
FlexForms must instead be assigned via standard `types` configuration
using `columnsOverrides`.
This also affects the *data structure identifier*, which in the commonly used
`tca` type is the `dataStructureKey`. It is now set to `default` if the
table does not support record types or no record type-specific configuration
exists. Otherwise, the `dataStructureKey` is set to the corresponding
record type value, for example `textpic`.
This change affects the following PSR-14 events:
* :php-short:`\TYPO3\CMS\Core\Configuration\Event\AfterFlexFormDataStructureIdentifierInitializedEvent`
* :php-short:`\TYPO3\CMS\Core\Configuration\Event\AfterFlexFormDataStructureParsedEvent`
* :php-short:`\TYPO3\CMS\Core\Configuration\Event\BeforeFlexFormDataStructureIdentifierInitializedEvent`
* :php-short:`\TYPO3\CMS\Core\Configuration\Event\BeforeFlexFormDataStructureParsedEvent`
A fallback for TYPO3 v14 resolves comma-separated `dataStructureKey`
values (for example, `list_type,CType`) to `CType`. Such comma-separated
keys were used to address flex form fields in page TSconfig overrides via
`TCEFORM.<table>.<field>.<dataStructureKey>` and in backend user exclude-field
definitions via `<table>:<field>;<dataStructureKey>`. This fallback emits a
PHP deprecation notice and is removed in TYPO3 v15, so page TSconfig and
exclude-field addressing then use the data structure key as-is (the record
type value, for example `textpic`).
To address circular dependencies during schema building,
:php-short:`\TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools` now supports
both TCA Schema objects and raw TCA configuration arrays as input. The
following methods accept a union type :php:`array|TcaSchema` for the new
:php:`$schema` parameter:
* :php:`getDataStructureIdentifier()`
* :php:`parseDataStructureByIdentifier()`
* :php:`cleanFlexFormXML()`
Previously, these methods relied on :php:`$GLOBALS['TCA']` internally, which
caused architectural issues. They now operate directly on the provided schema.
All calls to these methods should provide the :php:`$schema` parameter with
either a :php-short:`\TYPO3\CMS\Core\Schema\TcaSchema` instance or a raw TCA
configuration array. Since data structure resolution can be customized by
extensions, the parameter is not strictly mandatory, but it is strongly
recommended to provide it in most cases. An
:php-short:`\TYPO3\CMS\Core\Configuration\FlexForm\Exception\InvalidTcaSchemaException`
will be thrown if schema resolution is required but no schema is passed.
This change also enables components like
:php-short:`\TYPO3\CMS\Core\Schema\RelationMapBuilder` to use
:php-short:`\TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools` during schema
building, even when only raw TCA is available.
For further details on the enhanced FlexFormTools functionality, see
:ref:`feature-107047-1751984817`.
The following class has been removed as it is no longer required:
* :php-short:`\TYPO3\CMS\Core\Configuration\FlexForm\Exception\InvalidCombinedPointerFieldException`
Impact
======
**FlexForm Pointer Field Removal**
Any TCA definition that still uses :php:`ds_pointerField` or a `ds`
array with multiple entries (for example `news_pi1,list`) will no longer work
and might cause rendering errors.
**FlexFormTools Schema Parameter**
All code calling :php-short:`\TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools`
methods (:php:`getDataStructureIdentifier()`,
:php:`parseDataStructureByIdentifier()`, :php:`cleanFlexFormXML()`) must be
updated to provide the required :php:`$schema` parameter.
Affected installations
======================
**FlexForm Pointer Field Removal**
All installations using :php:`ds_pointerField` (as the pointer field
functionality has been removed entirely) or an array-like structure for
`ds` in their TCA field type `flex` configuration.
**FlexFormTools Schema Parameter**
All installations with custom code that directly call
:php-short:`\TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools` methods
without providing the :php:`$schema` parameter.
This includes custom extensions or TYPO3 Core patches using these methods.
A TCA migration automatically converts single-entry `ds` arrays.
Multi-entry definitions require manual migration, as they must be aligned with
the correct record type configuration, which may require additional
configuration changes beforehand.
Example for single-entry migration:
**Before:**
.. code-block:: php
:caption: Migration of single-entry ds configuration (before)
'ds' => [
'default' => '<T3DataStructure>...',
],
**After:**
.. code-block:: php
:caption: Migration of single-entry ds configuration (after)
'ds' => '<T3DataStructure>...',
Migration
=========
**FlexForm Pointer Field Migration**
**Before:**
.. code-block:: php
'ds_pointerField' => 'list_type,CType',
'ds' => [
'news_pi1,list' => 'FILE:EXT:news/Configuration/FlexForm.xml',
'default' => '<T3DataStructure>...',
],
**After:**
.. code-block:: php
'columns' => [
'pi_flexform' => [
'config' => [
'ds' => '<T3DataStructure>...',
],
],
],
'types' => [
'news_pi1' => [
'columnsOverrides' => [
'pi_flexform' => [
'config' => [
'ds' => 'FILE:EXT:news/Configuration/FlexForm.xml',
],
],
],
],
],
If no `columnsOverrides` is defined, the default `ds` value of the
field configuration will be used as before.
**FlexFormTools Schema Parameter Migration**
**Before:**
.. code-block:: php
use TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools;
use TYPO3\CMS\Core\Utility\GeneralUtility;
$flexFormTools = GeneralUtility::makeInstance(FlexFormTools::class);
$identifier = $flexFormTools->getDataStructureIdentifier(
$fieldTca,
'tt_content',
'pi_flexform',
$row
);
**After:**
.. code-block:: php
use TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools;
use TYPO3\CMS\Core\Schema\TcaSchemaFactory;
use TYPO3\CMS\Core\Utility\GeneralUtility;
$flexFormTools = GeneralUtility::makeInstance(FlexFormTools::class);
// Option 1: Using TCA Schema object (recommended for normal usage)
$tcaSchemaFactory = GeneralUtility::makeInstance(TcaSchemaFactory::class);
$tcaSchema = $tcaSchemaFactory->get('tt_content');
$identifier = $flexFormTools->getDataStructureIdentifier(
$fieldTca,
'tt_content',
'pi_flexform',
$row,
$tcaSchema
);
// Option 2: Using raw TCA array (for schema building contexts)
$rawTca = $fullTca['tt_content'];
$identifier = $flexFormTools->getDataStructureIdentifier(
$fieldTca,
'tt_content',
'pi_flexform',
$row,
$rawTca
);
.. index:: Backend, FlexForm, TCA, PartiallyScanned, ext:core
@@ -0,0 +1,119 @@
.. include:: /Includes.rst.txt
.. _breaking-107229-1754602036:
==============================================================
Breaking: #107229 - Removed support for annotations in Extbase
==============================================================
See :issue:`107229`
Description
===========
Extbase no longer supports PHP annotations for models, data transfer objects
(DTOs), and controller actions. Use PHP attributes (for example
:php:`#[Extbase\Validate]`) instead. Attributes provide the same functionality
with better performance and native language support.
.. note::
With this change, the third-party library :composer:`doctrine/annotations`
is no longer required by Extbase.
The library itself recommends switching to PHP attributes since
`version 1.14.0 <https://github.com/doctrine/annotations/commit/cbc5a5188d9eecf2e878a201351d414a1bb3bee3>`__
and has been
`marked as abandoned <https://github.com/doctrine/annotations/commit/a64d7f063e1602bbbc8e70a07b6b5f555b8c98a7>`__.
.. important::
PHPDoc annotations such as :php:`@var`, :php:`@return`, and similar are
unaffected by this change, as they are handled by standard PHPDoc parsing,
not by Doctrine.
Explicit type annotations like :php:`@var ObjectStorage<FileReference>`
remain fully supported.
Extbase previously relied on annotation parsing, typically detected when the
annotation namespace was imported, for example:
.. code-block:: php
use TYPO3\CMS\Extbase\Annotation as Extbase;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
class MyModel extends AbstractEntity
{
/**
* @Extbase\Validate("NotEmpty")
*/
protected string $foo = '';
}
Since TYPO3 now requires PHP 8.2 as the minimum version, the use of native PHP
attributes is preferred. All Extbase-related annotations have been available
as PHP attributes since TYPO3 v12.
Impact
======
By dropping support for Extbase annotations, only PHP attributes are now
supported. This provides more type safety and better integration with PHPs
language features.
Developers benefit from a cleaner, faster, and more reliable implementation
without the need for the deprecated third-party annotation parser.
Affected installations
======================
All Extbase models, *Data Transfer Objects (DTOs)*, and controllers that use
Extbase annotations are affected.
This includes built-in annotations such as :php:`Cascade`, :php:`Lazy`, and
:php:`Validate`, as well as any custom annotation implementations.
.. _breaking-107229-1754602036-migration:
Migration
=========
Switch from Extbase annotations to native PHP attributes.
Before (with annotations)
-------------------------
.. code-block:: php
use TYPO3\CMS\Extbase\Annotation as Extbase;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
class MyModel extends AbstractEntity
{
/**
* @Extbase\Validate("NotEmpty")
*/
protected string $foo = '';
}
After (with PHP attributes)
---------------------------
.. code-block:: php
use TYPO3\CMS\Extbase\Attribute as Extbase;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
class MyModel extends AbstractEntity
{
#[Extbase\Validate(['validator' => 'NotEmpty'])]
protected string $foo = '';
}
.. note::
Attribute class namespaces have moved from
:php:`\TYPO3\CMS\Extbase\Annotation` to :php:`\TYPO3\CMS\Extbase\Attribute`.
A class alias map remains available for backward compatibility, but since
the old namespaces are deprecated, developers should migrate to the new
:php:`Attribute` namespace to prevent issues in the future.
.. index:: PHP-API, FullyScanned, ext:extbase
@@ -0,0 +1,49 @@
.. include:: /Includes.rst.txt
.. _breaking-107310-1755533400:
===========================================================
Breaking: #107310 - Remove FreezableBackendInterface
===========================================================
See :issue:`107310`
Description
===========
The interface :php:`\TYPO3\CMS\Core\Cache\Backend\FreezableBackendInterface`
has been removed from the TYPO3 Core.
It previously defined the following methods:
- :php:`freeze()` — Freezes the cache backend.
- :php:`isFrozen()` — Returns whether the backend is frozen.
Impact
======
Any code implementing or referencing
:php-short:`\TYPO3\CMS\Core\Cache\Backend\FreezableBackendInterface`
will now trigger a PHP fatal error.
Since this interface was never implemented in the TYPO3 Core and had no known
real-world usage, the overall impact is expected to be minimal.
Affected installations
======================
Installations with custom extensions that implement or reference the
:php-short:`\TYPO3\CMS\Core\Cache\Backend\FreezableBackendInterface`
are affected.
Migration
=========
Remove any references to
:php-short:`\TYPO3\CMS\Core\Cache\Backend\FreezableBackendInterface`
from your extension code.
If you require freeze functionality, implement the desired behavior directly
in your custom cache backend class.
.. index:: PHP-API, FullyScanned
@@ -0,0 +1,140 @@
.. include:: /Includes.rst.txt
.. _breaking-107315-1755627000:
==============================================================
Breaking: #107315 - Cache Backend and Frontend related changes
==============================================================
See :issue:`107315`
Description
===========
In TYPO3 v14, the PHP code for the Cache Backend and Cache Frontend has
undergone major changes, which may affect extensions:
* Most PHP code from Cache Backends and Cache Frontends is now strongly
typed using PHP's native typing system
* Method signatures now use proper type declarations for parameters and
return types
* The :php:`mixed` type is now used where appropriate for flexible data
handling
* All string parameters and boolean return types are properly declared
The following interfaces have been updated with strict typing:
* :php:`\TYPO3\CMS\Core\Cache\Backend\BackendInterface`
* :php:`\TYPO3\CMS\Core\Cache\Backend\PhpCapableBackendInterface`
* :php:`\TYPO3\CMS\Core\Cache\Backend\TransientBackendInterface`
* :php:`\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface`
Additionally, backward compatibility for the abstract base class
constructor has been removed:
* :php:`\TYPO3\CMS\Core\Cache\Backend\AbstractBackend`
Impact
======
If you are using or extending the Cache Backend or Cache Frontend, you must
ensure that you are using the correct PHP types. This includes method
parameters, return types, and property types in your classes.
Affected installations
======================
All installations that extend or implement cache backend or frontend
classes are affected. This includes custom cache implementations in
third-party extensions.
Extension authors who have created custom cache backends or frontends
will need to update their class method signatures to match the new type
declarations from the interfaces.
Migration
=========
Update your custom cache backend and frontend implementations to use the
correct PHP types:
1. Ensure all method signatures match the interface declarations exactly
2. Add proper type hints for parameters (e.g., :php:`string
$entryIdentifier`)
3. Add proper return type declarations (e.g., :php:`bool`,
:php:`mixed`, :php:`void`)
4. Update any extending classes to use the same type declarations
Example migration for a custom backend:
.. code-block:: php
use TYPO3\CMS\Core\Cache\Backend\BackendInterface;
// Before (TYPO3 v13)
class MyCustomBackend implements BackendInterface
{
public function get($entryIdentifier)
{
// implementation
}
public function has($entryIdentifier)
{
// implementation
}
}
// After (TYPO3 v14)
class MyCustomBackend implements BackendInterface
{
public function get(string $entryIdentifier): mixed
{
// implementation
}
public function has(string $entryIdentifier): bool
{
// implementation
}
}
Example migration for a custom backend extending AbstractBackend:
.. code-block:: php
use TYPO3\CMS\Core\Cache\Backend\AbstractBackend;
// Before (TYPO3 v13)
class MyCustomBackend extends AbstractBackend
{
public function __construct($context, array $options = [])
{
parent::__construct($context, $options);
}
}
// After (TYPO3 v14)
class MyCustomBackend extends AbstractBackend
{
public function __construct(array $options = [])
{
parent::__construct($options);
}
}
Note for extensions that strive for TYPO3 v13 and v14 compatibility: The
:php:`__construct()` change of
:php:`\TYPO3\CMS\Core\Cache\Backend\AbstractBackend` can be mitigated by
omitting a type for the first argument and checking whether its incoming
value is a string (v13) or an array (v14).
For interface changes that added types to method argument signatures,
implementing services may omit the type to keep backwards compatibility
with TYPO3 v13. For added return value types, they must be added for v14
compatibility, and v13 should accept them. All in all, it *should* be
possible to have a single implementing class for both v13 and v14, but
it may be somewhat tricky. From a code perspective, it may be easier to
have dedicated classes.
.. index:: PHP-API, NotScanned, ext:core
@@ -0,0 +1,54 @@
.. include:: /Includes.rst.txt
.. _breaking-107323-1755864247:
======================================================
Breaking: #107323 - Workspace "Freeze Editing" removed
======================================================
See :issue:`107323`
Description
===========
The workspace record flag *Freeze Editing* has been removed without
replacement, effectively removing this feature.
The functionality had only been partially implemented and exhibited several
usability and conceptual issues. It was therefore decided to remove it entirely
in favor of more reliable and flexible workspace configuration options.
Impact
======
"Freezing" a workspace to prevent editing of records is no longer possible.
Affected installations
======================
Since *Freeze Editing* did not provide any visible feedback to editors, it was
likely used only rarely.
During the database compare, the field `freeze` will be removed from the
table :sql:`sys_workspace`, effectively "unfreezing" all previously frozen
workspaces.
Migration
=========
A more robust alternative to *Freeze Editing* is to configure a **custom
workspace stage** and assign **responsible persons**.
In combination with the following workspace options:
- `Publish only content in publish stage`
- `Restrict publishing to workspace owners`
you can create a workflow in which only designated members or groups are
permitted to move records into the *Ready to publish* stage and/or perform
publishing actions.
While other members can still edit records, such edits will automatically reset
the workspace stage back to *Editing*, restarting the review cycle for those
changes.
.. index:: Backend, NotScanned, ext:workspaces
@@ -0,0 +1,77 @@
.. include:: /Includes.rst.txt
.. _breaking-107324-1755973900:
=============================================================
Breaking: #107324 - Streamline PSR-7 Response Header Handling
=============================================================
See :issue:`107324`
Description
===========
The handling of PSR-7 response headers in TYPO3 Core and Extbase has been
unified. Previously, different mechanisms caused inconsistent behavior:
* **Extbase** only kept the *last* value of a header, discarding all
previous values (e.g. only one `Set-Cookie` header was possible).
* **Core** allowed multiple `Set-Cookie` headers, but merged all other
headers with multiple values into a single comma-separated string.
According to RFC 9110, this is only valid for headers that explicitly
support comma-separated lists.
With this change, TYPO3 now preserves multiple header values by default.
Each value is emitted as a separate header line, while single values remain
a single-line header.
Impact
======
* Multiple header values are now always emitted as multiple header lines.
* Extbase and Core responses can now properly emit multiple headers with the
same name (e.g. `Set-Cookie`, `WWW-Authenticate`, `Link`,
`xkey`).
* Extensions that relied on the old merging or overwriting behavior may need
to be adapted.
Affected installations
======================
Installations are affected if they:
* Relied on headers being merged into a comma-separated string.
* Relied on only the last header value being retained in Extbase responses.
Migration
=========
If your use case requires *merged* header values, you must now implement this
explicitly:
.. code-block:: php
use TYPO3\CMS\Core\Http\Response;
$response = new Response();
$values = ['foo', 'bar', 'baz'];
$response = $response->withHeader('X-Foo-Bar', implode(', ', $values));
If your use case requires that only the *last* header value is retained, you
must also handle this explicitly in your code:
.. code-block:: php
use TYPO3\CMS\Core\Http\Response;
$response = new Response();
$values = ['foo', 'bar', 'baz'];
$response = $response->withHeader('X-Foo-Bar', end($values));
Note: There is another edge case not affected by this change. Multiple Extbase
plugins still cannot set multiple header values with the same name (for
example, two Extbase plugins both setting a `Set-Cookie` header). In this
case, the latter will override the former. Installations affected by this
scenario should resolve it by adding their own middleware.
.. index:: Frontend, PHP-API, ext:core, ext:extbase, ext:frontend, NotScanned
@@ -0,0 +1,43 @@
.. include:: /Includes.rst.txt
.. _breaking-107343-1756559538:
===================================================
Breaking: #107343 - Removed "beforeFormCreate" hook
===================================================
See :issue:`107343`
Description
===========
The hook :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['beforeFormCreate']`
has been removed in favor of the PSR-14 event
:php-short:`\TYPO3\CMS\Form\Event\BeforeFormIsCreatedEvent`, which provides a
more powerful and flexible way to influence form creation.
Impact
======
Any hook implementation registered under
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['beforeFormCreate']`
is no longer executed in TYPO3 v14.0 and later.
Affected installations
======================
TYPO3 installations with custom extensions using this hook are affected.
The Extension Scanner will report such usages as a *weak match*.
Migration
=========
The hook has been removed without prior deprecation.
This allows extensions to remain compatible with both TYPO3 v13 (using the
hook) and v14+ (using the new event) simultaneously.
Use the PSR-14 event :ref:`BeforeFormIsCreatedEvent <feature-107343-1756389242>`
to extend or modify form creation behavior.
.. index:: Backend, ext:form, FullyScanned
@@ -0,0 +1,92 @@
.. include:: /Includes.rst.txt
.. _breaking-107356:
=================================================
Breaking: #107356 - Use Record API in List Module
=================================================
See :issue:`107356`
Description
===========
The :guilabel:`Content > List` backend module has been refactored to use the
:php-short:`\TYPO3\CMS\Backend\Record\RecordInterface` and related Record API
internally instead of working with raw database row arrays.
This modernization introduces stricter typing and improves data consistency.
As a result, several public method signatures have been updated.
The following public methods in
:php-short:`\TYPO3\CMS\Backend\RecordList\DatabaseRecordList` have changed
their signatures:
- :php:`renderListRow()` now expects a :php:`RecordInterface` object instead
of an array as the second parameter.
- :php:`makeControl()` now expects a :php:`RecordInterface` object instead of
an array as the second parameter.
- :php:`makeCheckbox()` now expects a :php:`RecordInterface` object instead of
an array as the second parameter.
- :php:`languageFlag()` now expects a :php:`RecordInterface` object instead of
an array as the second parameter.
- :php:`makeLocalizationPanel()` now expects a :php:`RecordInterface` object
instead of an array as the second parameter.
- :php:`linkWrapItems()` now expects a :php:`RecordInterface` object instead
of an array as the fourth parameter.
- :php:`getPreviewUriBuilder()` now expects a :php:`RecordInterface` object
instead of an array as the second parameter.
- :php:`isRecordDeletePlaceholder()` now expects a :php:`RecordInterface`
object instead of an array.
- :php:`isRowListingConditionFulfilled()` has dropped the first parameter
:php:`$table` and now expects a :php:`RecordInterface` object instead of an
array.
These changes enable the List module to operate on structured Record objects,
providing better type safety, consistency, and a foundation for further
modernization of the backend record handling.
Impact
======
Code that calls these methods directly must be updated to pass
:php-short:`\TYPO3\CMS\Backend\Record\RecordInterface` objects instead of
database row arrays.
Affected installations
======================
TYPO3 installations with custom extensions that:
- Extend or XCLASS
:php-short:`\TYPO3\CMS\Backend\RecordList\DatabaseRecordList` and override
any of the affected methods.
- Call the affected methods directly with array-based record data.
Migration
=========
When calling affected methods, use the Record API to create a Record object
from a database row:
**Before:**
.. code-block:: php
:caption: Migrating from array-based record handling to the Record API (before)
$databaseRecordList->renderListRow($table, $rowArray, $indent, $translations, $enabled);
**After:**
.. code-block:: php
:caption: Migrating from array-based record handling to the Record API (after)
use TYPO3\CMS\Backend\RecordList\DatabaseRecordList;
use TYPO3\CMS\Backend\Record\RecordFactory;
use TYPO3\CMS\Core\Utility\GeneralUtility;
$recordFactory = GeneralUtility::makeInstance(RecordFactory::class);
$record = $recordFactory->createResolvedRecordFromDatabaseRow($table, $rowArray);
$databaseRecordList->renderListRow($table, $record, $indent, $translations, $enabled);
.. index:: Backend, PHP-API, FullyScanned, ext:backend
@@ -0,0 +1,42 @@
.. include:: /Includes.rst.txt
.. _breaking-107380-1756896552:
======================================================
Breaking: #107380 - Removed "beforeFormDuplicate" hook
======================================================
See :issue:`107380`
Description
===========
The hook
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['beforeFormDuplicate']`
has been removed in favor of the more powerful PSR-14 event
:php-short:`\TYPO3\CMS\Form\Event\BeforeFormIsDuplicatedEvent`.
Impact
======
Implementations of the removed hook are no longer executed in TYPO3 v14.0
and later.
Affected installations
======================
TYPO3 installations with custom extensions using this hook. The extension
scanner reports any usage as a weak match.
Migration
=========
The hook has been removed without deprecation to allow extensions to remain
compatible with both TYPO3 v13 (using the hook) and TYPO3 v14+ (using the new
event). When implementing the event as well, no further deprecations will
occur.
Use the :ref:`PSR-14 Event <feature-107380-1756896691>` to achieve the same
or greater functionality.
.. index:: Backend, ext:form, FullyScanned
@@ -0,0 +1,42 @@
.. include:: /Includes.rst.txt
.. _breaking-107382-1756901681:
===================================================
Breaking: #107382 - Removed "beforeFormDelete" hook
===================================================
See :issue:`107382`
Description
===========
The hook
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['beforeFormDelete']`
has been removed in favor of the more powerful PSR-14 event
:php:`\TYPO3\CMS\Form\Event\BeforeFormIsDeletedEvent`.
Impact
======
Implementations of the removed hook are no longer executed in TYPO3 v14.0
and later.
Affected installations
======================
TYPO3 installations with custom extensions using this hook. The extension
scanner reports any usage as a weak match.
Migration
=========
The hook has been removed without deprecation to allow extensions to remain
compatible with both TYPO3 v13 (using the hook) and TYPO3 v14+ (using the new
event). When implementing the event as well, no further deprecations will
occur.
Use the :ref:`PSR-14 Event <feature-107382-1756901428>` to achieve the same
or greater functionality.
.. index:: Backend, ext:form, FullyScanned
@@ -0,0 +1,42 @@
.. include:: /Includes.rst.txt
.. _breaking-107388-1756971206:
=================================================
Breaking: #107388 - Removed "beforeFormSave" hook
=================================================
See :issue:`107388`
Description
===========
The hook
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['beforeFormSave']`
has been removed in favor of the more powerful PSR-14 event
:php:`\TYPO3\CMS\Form\Event\BeforeFormIsSavedEvent`.
Impact
======
Implementations of the removed hook are no longer executed in TYPO3 v14.0
and later.
Affected installations
======================
TYPO3 installations with custom extensions using this hook. The extension
scanner reports any usage as a weak match.
Migration
=========
The hook has been removed without deprecation to allow extensions to remain
compatible with both TYPO3 v13 (using the hook) and TYPO3 v14+ (using the new
event). When implementing the event as well, no further deprecations will
occur.
Use the :ref:`PSR-14 Event <feature-107388-1756971278>` to achieve the same
or greater functionality.
.. index:: Backend, ext:form, FullyScanned
@@ -0,0 +1,125 @@
.. include:: /Includes.rst.txt
.. _breaking-107397-1756543200:
==============================================================================
Breaking: #107397 - Circular dependency between ProcessedFile and Task removed
==============================================================================
See :issue:`107397`
Description
===========
The circular dependency between
:php:`\TYPO3\CMS\Core\Resource\ProcessedFile` and File Processing Task
classes has been resolved to improve the architecture and maintainability of
the File Abstraction Layer (FAL) processing system.
The following changes have been made to
:php-short:`\TYPO3\CMS\Core\Resource\ProcessedFile`:
- The public method :php:`getTask()` has been removed.
- The public method :php:`generateProcessedFileNameWithoutExtension()` has been
removed.
The following changes have been made to
:php-short:`\TYPO3\CMS\Core\Resource\ProcessedFileRepository`:
- Method :php:`add()` now requires a :php:`TaskInterface` parameter.
- Method :php:`update()` now requires a :php:`TaskInterface` parameter.
Additionally, the checksum validation logic has been moved from
:php-short:`\TYPO3\CMS\Core\Resource\ProcessedFile` to
:php-short:`\TYPO3\CMS\Core\Resource\Processing\AbstractTask`.
Impact
======
Any code that calls the following methods will cause PHP fatal errors:
- :php:`ProcessedFile->getTask()`
- :php:`ProcessedFile->generateProcessedFileNameWithoutExtension()`
Any code that calls :php:`ProcessedFileRepository->add()` or
:php:`ProcessedFileRepository->update()` without the new
:php:`TaskInterface` parameter will cause PHP fatal errors.
Code that relied on ::php-short:`\TYPO3\CMS\Core\Resource\ProcessedFile` objects
having Task objects available internally will no longer work, as Task objects
are now created externally by
:php-short:`\TYPO3\CMS\Core\Resource\Service\FileProcessingService` when
needed.
Affected installations
======================
Installations with custom file processing extensions or custom Task
implementations that directly interact with the
:php:`ProcessedFile->getTask()` method are affected. The extension scanner will
report any usage of :php:`ProcessedFile->getTask()` and
:php:`ProcessedFile->generateProcessedFileNameWithoutExtension()` as weak
matches.
Extensions that manually call :php:`ProcessedFileRepository->add()` or
:php:`ProcessedFileRepository->update()` are also affected. The extension
scanner will not report usages of these methods due to too many weak matches.
Migration
=========
Replace calls to :php:`ProcessedFile->getTask()` with direct creation of Task
objects through the :php-short:`\TYPO3\CMS\Core\Resource\Processing\TaskTypeRegistry`:
**Before:**
.. code-block:: php
$task = $processedFile->getTask();
**After:**
.. code-block:: php
use TYPO3\CMS\Core\Resource\Processing\TaskTypeRegistry;
use TYPO3\CMS\Core\Utility\GeneralUtility;
$taskTypeRegistry = GeneralUtility::makeInstance(TaskTypeRegistry::class);
$task = $taskTypeRegistry->getTaskForType(
$processedFile->getTaskIdentifier(),
$processedFile,
$processedFile->getProcessingConfiguration()
);
It is recommended to implement your own alternative to
:php:`ProcessedFile->generateProcessedFileNameWithoutExtension()` if similar
logic is still needed.
Update calls to :php:`ProcessedFileRepository->add()` and
:php:`ProcessedFileRepository->update()` to include the new
:php-short:`\TYPO3\CMS\Core\Resource\Processing\TaskInterface` parameter:
.. code-block:: php
:caption: Updated calls to ProcessedFileRepository
use TYPO3\CMS\Core\Resource\Processing\TaskTypeRegistry;
use TYPO3\CMS\Core\Resource\ProcessedFileRepository;
use TYPO3\CMS\Core\Utility\GeneralUtility;
// Before
$processedFileRepository->add($processedFile);
$processedFileRepository->update($processedFile);
// After
$taskTypeRegistry = GeneralUtility::makeInstance(TaskTypeRegistry::class);
$task = $taskTypeRegistry->getTaskForType(
$processedFile->getTaskIdentifier(),
$processedFile,
$processedFile->getProcessingConfiguration()
);
$processedFileRepository = GeneralUtility::makeInstance(ProcessedFileRepository::class);
$processedFileRepository->add($processedFile, $task);
$processedFileRepository->update($processedFile, $task);
.. index:: PHP-API, PartiallyScanned
@@ -0,0 +1,61 @@
.. include:: /Includes.rst.txt
.. _breaking-107403-1757082780:
========================================================================
Breaking: #107403 - Remove LocalPreviewHelper + LocalCropScaleMaskHelper
========================================================================
See :issue:`107403`
Description
===========
The helper classes for preview and CropScaleMask (CSM) image generation
prevented further unification of the File Abstraction Layer (FAL) image
processing API.
The two helper classes
:php:`\TYPO3\CMS\Core\Resource\Processing\LocalPreviewHelper` and
:php:`\TYPO3\CMS\Core\Resource\Processing\LocalCropScaleMaskHelper`
have been removed. Their functionality has been merged into
:php:`\TYPO3\CMS\Core\Resource\Processing\LocalImageProcessor`.
These helper classes existed for historical reasons and were never intended
to be part of the public API.
Impact
======
Any code that extends or references
:php-short:`\TYPO3\CMS\Core\Resource\Processing\LocalPreviewHelper` or
:php-short:`\TYPO3\CMS\Core\Resource\Processing\LocalCropScaleMaskHelper`
will now trigger PHP fatal errors.
Affected installations
======================
Installations with custom extensions that extend or reference either
:php-short:`\TYPO3\CMS\Core\Resource\Processing\LocalPreviewHelper` or
:php-short:`\TYPO3\CMS\Core\Resource\Processing\LocalCropScaleMaskHelper`
are affected and will cause PHP fatal errors.
These helper classes were meant to be internal but were never declared as
such. Implementations using them directly instead of the
:php-short:`\TYPO3\CMS\Core\Resource\Processing\LocalImageProcessor` should
be very rare.
Migration
=========
Remove all references to
:php-short:`\TYPO3\CMS\Core\Resource\Processing\LocalPreviewHelper` or
:php-short:`\TYPO3\CMS\Core\Resource\Processing\LocalCropScaleMaskHelper`
from your code.
Use the
:php-short:`\TYPO3\CMS\Core\Resource\Processing\LocalImageProcessor`
directly instead, or implement a custom image processor that executes before
this processor to apply additional functionality.
.. index:: PHP-API, FullyScanned
@@ -0,0 +1,135 @@
.. include:: /Includes.rst.txt
.. _breaking-107436-1736639846:
============================================================
Breaking: #107436 - Localization system architecture changes
============================================================
See :issue:`107436`
Description
===========
The TYPO3 localization system has been migrated to use the Symfony Translation
components internally (see :ref:`feature-107436-1736639846`), which introduces
several breaking changes to the internal API and configuration handling.
This change affects only the internal processing of translation ("locallang")
files. The public API of the localization system remains unchanged.
**Method Signature Changes**
The method
:php:`\TYPO3\CMS\Core\Localization\LocalizationFactory::getParsedData()`
has a modified signature and behavior:
**Before:**
.. code-block:: php
public function getParsedData(
$fileReference,
$languageKey,
$_ = null,
$__ = null,
$isLocalizationOverride = false
)
**After:**
.. code-block:: php
public function getParsedData(string $fileReference, string $languageKey): array
It now only returns the parsed and combined localization data instead of both
the default and the localized data. To obtain the default (English) data, call
:php:`getParsedData($fileReference, 'en')`.
**Language Key Changes**
Internally, the fallback language key has been changed from `default` to `en`.
This does not affect public API usage, where `default` can still represent any
configured language key other than English.
**Configuration Changes**
Custom parser configuration is no longer supported.
The global configuration option
:php:`$GLOBALS['TYPO3_CONF_VARS']['SYS']['lang']['parser']` has been removed,
and any custom parser registered through it will be ignored.
Several configuration options have been moved or renamed:
* :php:`$GLOBALS['TYPO3_CONF_VARS']['SYS']['lang']['parser']`
* :php:`$GLOBALS['TYPO3_CONF_VARS']['SYS']['lang']['requireApprovedLocalizations']`
:php:`$GLOBALS['TYPO3_CONF_VARS']['LANG']['requireApprovedLocalizations']`
* :php:`$GLOBALS['TYPO3_CONF_VARS']['SYS']['lang']['format']`
:php:`$GLOBALS['TYPO3_CONF_VARS']['LANG']['format']`
* :php:`$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['lang']['availableLanguages']`
:php:`$GLOBALS['TYPO3_CONF_VARS']['LANG']['availableLocales']`
* :php:`$GLOBALS['TYPO3_CONF_VARS']['SYS']['locallangXMLOverride']`
:php:`$GLOBALS['TYPO3_CONF_VARS']['LANG']['resourceOverrides']`
Impact
======
Code calling
:php-short:`\TYPO3\CMS\Core\Localization\LocalizationFactory::getParsedData()`
with the old signature or expecting a multi-dimensional array structure will
break:
* The method now enforces strict parameter types.
* The method returns `en` instead of `default` for English translations.
* Unused parameters have been removed.
Extensions that register custom localization parsers using
:php:`$GLOBALS['TYPO3_CONF_VARS']['SYS']['lang']['parser']` will no longer have
their parsers executed, potentially leading to missing translations.
Instances using the moved configuration options must update their configuration
to the new paths. The old options are no longer recognized and will be ignored.
Affected installations
======================
Installations that:
* Call :php:`LocalizationFactory::getParsedData()` directly.
* Register custom localization parsers via the removed configuration option.
* Use any of the renamed or moved configuration options listed above.
Migration
=========
**Method Call Updates**
Update all calls to :php:`getParsedData()` to use the new signature and ensure
parameter types are correct:
**Before:**
.. code-block:: php
:caption: Updated getParsedData() usage
$data = $factory->getParsedData(
$fileReference,
$languageKey,
null,
null,
false
)[$languageKey];
**After:**
.. code-block:: php
$data = $factory->getParsedData($fileReference, $languageKey);
**Custom Parser Migration**
Replace any custom localization parser with a Symfony Translation loader.
See :ref:`feature-107436-1736639846` for detailed migration instructions to the
new loader system.
.. index:: PHP-API, LocalConfiguration, NotScanned
@@ -0,0 +1,100 @@
.. include:: /Includes.rst.txt
.. _breaking-107438-1736592000:
============================================================================
Breaking: #107438 - Default parseFunc configuration for Fluid Styled Content
============================================================================
See :issue:`107438`
Description
===========
Since TYPO3 v13, the basic :typoscript:`lib.parseFunc` and
:typoscript:`lib.parseFunc_RTE` configurations are always available through
:file:`EXT:frontend/ext_localconf.php`.
The default parseFunc configuration previously provided by
EXT:fluid_styled_content has been removed to avoid duplicated and outdated
settings. This unifies the parseFunc behavior between EXT:frontend and
EXT:fluid_styled_content.
The :typoscript:`allowTags` syntax is no longer set by default, as HTML
sanitization has been handled properly by the HTML Sanitizer for some time.
All HTML tags are now allowed by default in frontend output, while the
HTML Sanitizer controls which tags and attributes are ultimately permitted.
Note that the :typoscript:`allowTags` directive itself has **not** been
removed. It can still be set to restrict frontend output where desired.
The conceptual approach is:
* The backend (RTE and its HTML parser/processing) already cleans unwanted
content and controls what is stored in the database.
* The frontend output (parseFunc) should only add additional restrictions
through :typoscript:`allowTags` when content comes from external or
untrusted sources (for example, custom Extbase output).
Impact
======
Custom TypoScript configurations using :typoscript:`allowTags` syntax may no
longer work as expected. Specifically:
* :typoscript:`allowTags := addToList(wbr)` no longer appends `wbr`.
Instead, it limits allowed tags to only `wbr`.
* Default CSS classes on HTML elements (for example
:html:`<table class="contenttable">`) are no longer automatically added by
the parseFunc configuration.
* The parseFunc configuration in EXT:fluid_styled_content no longer
provides custom link-handling options such as `extTarget` and `keep`.
Affected installations
======================
TYPO3 installations that use:
* Custom TypoScript configurations relying on prior default
:typoscript:`allowTags` behavior.
* Extensions or sites depending on the specific parseFunc configuration
previously provided by EXT:fluid_styled_content.
* Configurations expecting automatic CSS class additions to HTML elements.
* Sites relying on the old external link-handling behavior from the
Fluid Styled Content parseFunc.
Migration
=========
If you need to allow specific HTML tags, explicitly configure
:typoscript:`allowTags` instead of extending a former default.
**Before (no longer works):**
.. code-block:: typoscript
lib.parseFunc_RTE.allowTags := addToList(wbr)
**After:**
.. code-block:: typoscript
lib.parseFunc_RTE.allowTags = b,span,i,em,wbr,...
For custom CSS classes on HTML elements, use custom CSS or add them through
Fluid templates or TypoScript processing instead.
If you require the previous link-handling behavior, configure it explicitly:
.. code-block:: typoscript
lib.parseFunc_RTE {
makelinks {
http {
extTarget = _blank
keep = path
}
}
}
.. index:: TypoScript, ext:fluid_styled_content, ext:frontend, NotScanned
@@ -0,0 +1,198 @@
.. include:: /Includes.rst.txt
.. _breaking-107443-1761040245:
===========================================================================
Breaking: #107443 - Migrate Modal component from Bootstrap to native dialog
===========================================================================
See :issue:`107443`
Description
===========
The TYPO3 Modal component has been migrated from Bootstrap's modal
implementation to use the native HTML :html:`<dialog>` element. This improves
accessibility, reduces bundle size, and removes the dependency on Bootstrap's
JavaScript for modal functionality.
As part of this migration, Bootstrap's native modal events (such as
:js:`show.bs.modal`, :js:`shown.bs.modal`, :js:`hide.bs.modal`, and
:js:`hidden.bs.modal`) are no longer dispatched.
Likewise, direct Bootstrap modal API usage (for example :js:`new Modal()` from
Bootstrap or :js:`$(element).modal()`) is no longer supported.
Impact
======
Bootstrap modal events (:js:`*.bs.modal`) are no longer available.
Extensions listening to these events must migrate to TYPO3's custom modal
events.
The Modal component now uses the native :html:`<dialog>` element with updated
CSS classes and DOM structure.
Any direct manipulation of Bootstrap modal APIs will no longer work.
Extensions using :js:`data-bs-toggle="modal"`, :js:`data-bs-content="..."`, or
:js:`data-bs-target` attributes to trigger modals must migrate to TYPO3's
Modal API.
Affected installations
======================
All installations with custom extensions that:
- Listen to Bootstrap modal events (:js:`show.bs.modal`, :js:`shown.bs.modal`,
:js:`hide.bs.modal`, :js:`hidden.bs.modal`)
- Use Bootstrap's modal JavaScript API directly
(for example :js:`new bootstrap.Modal()`)
- Use jQuery to control modals (for example :js:`$(element).modal('show')`)
- Use :js:`data-bs-toggle="modal"` or :js:`data-bs-content="..."` attributes
- Manipulate modal DOM structures or classes expecting Bootstrap markup
Migration
=========
Event migration
---------------
Replace Bootstrap modal event listeners with TYPO3's custom modal events.
Event listeners must be attached to the modal instance returned by the Modal
API, not queried from the DOM.
**Before:**
.. code-block:: javascript
const modalElement = document.querySelector('.modal');
modalElement.addEventListener('show.bs.modal', (event) => {
console.log('Modal is about to be shown');
});
modalElement.addEventListener('shown.bs.modal', (event) => {
console.log('Modal is now visible');
});
modalElement.addEventListener('hide.bs.modal', (event) => {
console.log('Modal is about to be hidden');
});
modalElement.addEventListener('hidden.bs.modal', (event) => {
console.log('Modal is now hidden');
});
**After:**
.. code-block:: javascript
import Modal from '@typo3/backend/modal';
import Severity from '@typo3/backend/severity';
const modal = Modal.show(
'My Modal Title',
'This is the modal content',
Severity.info
);
modal.addEventListener('typo3-modal-show', (event) => {
console.log('Modal is about to be shown');
});
modal.addEventListener('typo3-modal-shown', (event) => {
console.log('Modal is now visible');
});
modal.addEventListener('typo3-modal-hide', (event) => {
console.log('Modal is about to be hidden');
});
modal.addEventListener('typo3-modal-hidden', (event) => {
console.log('Modal is now hidden');
});
Bootstrap API migration
-----------------------
Replace Bootstrap modal API calls with TYPO3's Modal API.
Do not instantiate Bootstrap modals or manipulate modal DOM elements directly.
**Before:**
.. code-block:: javascript
import { Modal } from 'bootstrap';
const modalElement = document.querySelector('.modal');
const bsModal = new Modal(modalElement);
bsModal.show();
bsModal.hide();
**After:**
.. code-block:: javascript
import Modal from '@typo3/backend/modal';
import Severity from '@typo3/backend/severity';
// Show a simple modal
Modal.show(
'My Modal Title',
'This is the modal content',
Severity.info,
[
{
text: 'Close',
btnClass: 'btn-default',
trigger: (event, modal) => modal.hideModal()
}
]
);
// Dismiss the current modal
Modal.dismiss();
Data attribute migration
------------------------
Replace Bootstrap's :js:`data-bs-toggle` and :js:`data-bs-target` attributes
with TYPO3's modal trigger API.
**Before:**
.. code-block:: html
<button type="button"
data-bs-toggle="modal"
data-bs-target="#myModal"
data-bs-content="Are you sure?">
Open Modal
</button>
**After:**
.. code-block:: html
<button type="button"
class="t3js-modal-trigger"
data-title="Confirmation"
data-content="Are you sure?"
data-severity="warning"
data-button-close-text="Cancel"
data-button-ok-text="Confirm">
Open Modal
</button>
Alternatively, use the JavaScript API directly:
.. code-block:: javascript
import Modal from '@typo3/backend/modal';
import Severity from '@typo3/backend/severity';
document.querySelector('button').addEventListener('click', (event) => {
Modal.confirm(
'Confirmation',
'Are you sure?',
Severity.warning
);
});
.. index:: Backend, JavaScript, NotScanned, ext:backend
@@ -0,0 +1,53 @@
.. include:: /Includes.rst.txt
.. _breaking-107473-1758113238:
===================================================================
Breaking: #107473 - TypoScript condition function getTSFE() removed
===================================================================
See :issue:`107473`
Description
===========
The TypoScript condition function :typoscript:`getTSFE()` has been removed.
After various properties like :typoscript:`getTSFE().type` were already removed
in TYPO3 v13, the remaining parts of this functionality have now been removed
in TYPO3 v14.
The most common remaining use was accessing the current page ID via
:typoscript:`getTSFE().id`, which can be replaced with
:typoscript:`request.getPageArguments().getPageId()`.
Impact
======
Conditions using :typoscript:`getTSFE()` will no longer evaluate to true and
must be updated.
Affected installations
======================
Instances with TypoScript conditions that use the function
:typoscript:`getTSFE()` are affected.
Migration
=========
Replace :typoscript:`getTSFE()` with an equivalent condition. For example:
**Before:**
.. code-block:: typoscript
[getTSFE() && getTSFE().id == 42]
**After:**
.. code-block:: typoscript
[request?.getPageArguments()?.getPageId() == 42]
.. index:: TypoScript, NotScanned, ext:frontend
@@ -0,0 +1,52 @@
.. include:: /Includes.rst.txt
.. _breaking-107482-1758143015:
======================================================================
Breaking: #107482 - Environment::getComposerRootPath method removed
======================================================================
See :issue:`107482`
Description
===========
The following method in :php:`\TYPO3\CMS\Core\Core\Environment` has been
removed in TYPO3 v14.0:
* :php:`Environment::getComposerRootPath()`
Since composer installers v4/v5 (which are required since TYPO3 v12),
:php:`getComposerRootPath()` and :php:`getProjectPath()` return the same
value, because the project path can no longer be changed through
configuration.
Therefore, the method :php:`Environment::getComposerRootPath()` has been
removed. It was marked as internal from the beginning.
Impact
======
Calling this method will result in a PHP error.
Affected installations
======================
TYPO3 installations with custom extensions or custom code that directly
call the removed method are affected:
* :php:`Environment::getComposerRootPath()`
The extension scanner will report any usage as a strong match.
Migration
=========
Instead of calculating relative paths manually, use absolute paths or
the appropriate TYPO3 APIs for path handling.
Use the following replacement:
* :php:`Environment::getProjectPath()`
.. index:: PHP-API, FullyScanned, ext:core
@@ -0,0 +1,100 @@
.. include:: /Includes.rst.txt
.. _breaking-107488-1758106735:
============================================================
Breaking: #107488 - Scheduler frequency options moved to TCA
============================================================
See :issue:`107488`
Description
===========
The global configuration array
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['frequencyOptions']`,
which was used to define frequency options for scheduler tasks, has been
removed.
Frequency options are now configured directly in the TCA using the
:php:`overrideFieldTca` mechanism on the
:php:`tx_scheduler_task.execution_details` field.
This change improves consistency with TYPO3s configuration patterns and
provides better extensibility for scheduler task timing options.
Impact
======
Extensions that previously added custom frequency options through the global
:php:`frequencyOptions` array will no longer see their custom options in the
scheduler task frequency field.
Code that relied on reading the global :php:`frequencyOptions` configuration
will no longer work as expected.
Affected installations
======================
All installations with extensions providing custom scheduler frequency options
through the global configuration array are affected.
Migration
=========
Extensions should migrate their frequency options from the global configuration
to TCA overrides.
**Before (no longer working):**
.. code-block:: php
// EXT:my_extension/ext_localconf.php
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['frequencyOptions']['0 2 * * *'] =
'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:daily_2am';
**After (recommended approach):**
.. code-block:: php
// EXT:my_extension/Configuration/TCA/Overrides/tx_scheduler_task.php
$GLOBALS['TCA']['tx_scheduler_task']['columns']['execution_details']['config']['overrideFieldTca']['frequency']['config']['valuePicker']['items'][] = [
'value' => '0 2 * * *',
'label' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:daily_2am',
];
**Migration for multiple options:**
.. code-block:: php
// EXT:my_extension/Configuration/TCA/Overrides/tx_scheduler_task.php
$customFrequencyOptions = [
[
'value' => '0 2 * * *',
'label' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:daily_2am',
],
[
'value' => '0 */6 * * *',
'label' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:every_6_hours',
],
[
'value' => '0 0 1 * *',
'label' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:monthly_first',
],
];
$GLOBALS['TCA']['tx_scheduler_task']['columns']['execution_details']['config']['overrideFieldTca']['frequency']['config']['valuePicker']['items'] = array_merge(
$GLOBALS['TCA']['tx_scheduler_task']['columns']['execution_details']['config']['overrideFieldTca']['frequency']['config']['valuePicker']['items'] ?? [],
$customFrequencyOptions
);
Related features
================
See :ref:`feature-107488-1758106735` for details about the new extensible
timing options functionality.
.. index:: Backend, TCA, NotScanned, ext:scheduler
@@ -0,0 +1,54 @@
.. include:: /Includes.rst.txt
.. _breaking-107507-1758376090:
========================================================================================
Breaking: #107507 - Removed EXT:form AbstractFinisher->getTypoScriptFrontendController()
========================================================================================
See :issue:`107507`
Description
===========
The method
:php:`\TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher->getTypoScriptFrontendController()`
has been removed.
Since the entire :php-short:`TypoScriptFrontendController` class is being phased out,
this abstract helper method has been removed as part of that cleanup.
Impact
======
Calling this method in a custom EXT:form finisher will result in a fatal PHP
error.
Affected installations
======================
TYPO3 instances using EXT:form with custom finishers that call this method are
affected. The extension scanner is configured to detect such usages.
Migration
=========
Migration depends on what the finisher previously did with the returned class
instance. The :php:`TypoScriptFrontendController` properties and helper methods
have been modernized, with most data now available as request attributes.
For example, accessing the :php:`cObj` property can be replaced like this:
.. code-block:: php
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
$cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
$cObj->setRequest($request);
$cObj->start(
$request->getAttribute('frontend.page.information')->getPageRecord(),
'pages'
);
.. index:: PHP-API, FullyScanned, ext:form
@@ -0,0 +1,42 @@
.. include:: /Includes.rst.txt
.. _breaking-107518-1758539663:
========================================================
Breaking: #107518 - Removed "initializeFormElement" hook
========================================================
See :issue:`107518`
Description
===========
The hook
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['initializeFormElement']`
has been removed in favor of the PSR-14 event
:php:`\TYPO3\CMS\Form\Event\BeforeRenderableIsAddedToFormEvent`.
Impact
======
Hook implementations registered under
`initializeFormElement` are no longer executed in TYPO3 v14.0 and later.
Affected installations
======================
TYPO3 installations with custom extensions using this hook are affected.
The extension scanner reports any usage as a weak match.
Migration
=========
The hook was removed without a deprecation phase to allow extensions to work
with both TYPO3 v13 (using the hook) and TYPO3 v14+ (using the new event)
simultaneously.
Use the :ref:`PSR-14 event <feature-107518-1758539757>` instead to influence
form element initialization. Since the event is dispatched at a later point,
it allows more extensive modifications than the previous hook.
.. index:: Backend, ext:form, FullyScanned
@@ -0,0 +1,44 @@
.. include:: /Includes.rst.txt
.. _breaking-107528-1758703683:
===================================================================
Breaking: #107528 - Removed "beforeRemoveFromParentRenderable" hook
===================================================================
See :issue:`107528`
Description
===========
The hook
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['beforeRemoveFromParentRenderable']`
has been removed in favor of the PSR-14 event
:php:`\TYPO3\CMS\Form\Event\BeforeRenderableIsRemovedFromFormEvent`.
Impact
======
Hook implementations registered under
:php:`beforeRemoveFromParentRenderable` are no longer executed in
TYPO3 v14.0 and later.
Affected installations
======================
TYPO3 installations with custom extensions using this hook are affected.
The extension scanner reports any usage as a weak match.
Migration
=========
The hook was removed without a deprecation phase to allow extensions to
work with both TYPO3 v13 (using the hook) and TYPO3 v14+ (using the new
event) simultaneously.
Use the :ref:`PSR-14 event <feature-107528-1758703683>` instead to allow
greater influence over the form processing workflow. Since the event is
dispatched at a later point, it allows more extensive modifications than
the previous hook.
.. index:: Backend, ext:form, FullyScanned
@@ -0,0 +1,191 @@
.. include:: /Includes.rst.txt
.. _breaking-107537-1760339938:
=================================================================
Breaking: #107537 - Changes in URL generation of system resources
=================================================================
See :issue:`107537`
Description
===========
The following changes are considered breaking, although their impact is
expected to be very low.
* TypoScript getData function :typoscript:`path` previously returned a
relative URL and now returns an absolute URL (prepended with
:typoscript:`absRefPrefix`).
* Access to FAL storages via relative path (`fileadmin/templates/main.css`)
is limited to the default storage defined in :php:`$GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir']`.
* All generated system resource URLs now include cache busting.
* Adding custom query strings to resource identifiers no longer disables cache
busting — both are now applied.
.. _breaking-107537-gettext-path:
getText "path" in TypoScript
----------------------------
.. code-block:: typoscript
:caption: EXT:my_extension/Configuration/TypoScript/setup.typoscript
:emphasize-lines: 3
page.20 = TEXT
page.20 {
data = path : EXT:core/Resources/Public/Icons/Extension.svg
}
.. code-block:: text
:caption: Result (TYPO3 classic mode note the leading "/")
"path" result before: typo3/sysext/core/Resources/Public/Icons/Extension.svg
"path" result now: /typo3/sysext/core/Resources/Public/Icons/Extension.svg
.. code-block:: text
:caption: Result (TYPO3 Composer mode note the leading "/")
"path" result before: _assets/5f237792cbcdc97cfceade1e16ea33d7/Icons/Extension.svg
"path" result now: /_assets/5f237792cbcdc97cfceade1e16ea33d7/Icons/Extension.svg
.. _breaking-107537-relative-fal-resource:
Relative path to FAL Storage
----------------------------
Referencing resources via relative path does only work for the default FAL storage
defined in :php:`$GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir']`.
This means if you have other local FAL storages configured, you need to use the FAL resource syntax
(e.g. `FAL:42:/path/to/file.css`) to reference files in such storage instead of using relative paths
(e.g. `my-other-fileadmin/path/to/file.css`).
It is generally recommended to use explicit resource identifiers (App resources or FAL resources),
instead of relative paths.
.. _breaking-107537-cachebusting:
All generated URLs now contain cache busting
--------------------------------------------
All generated resource URLs now include cache busting.
For example, icon URLs that previously had no cache busting will now contain a
cache-busting query string.
.. _breaking-107537-querystrings:
Additional query strings applied to the resource identifier
-----------------------------------------------------------
When adding custom query strings to resource identifiers, TYPO3 previously
disabled cache busting.
Now, both the custom query string and the cache-busting parameter are applied.
If custom query strings were used as manual cache busters, you can now remove
them safely.
.. code-block:: typoscript
:caption: EXT:my_extension/Configuration/TypoScript/setup.typoscript
:emphasize-lines: 3
page.20 = TEXT
page.20 {
data = asset : EXT:core/Resources/Public/Icons/Extension.svg?v=1234
}
.. code-block:: text
:caption: Result
result before: /typo3/sysext/core/Resources/Public/Icons/Extension.svg?v=1234
result now: /typo3/sysext/core/Resources/Public/Icons/Extension.svg?v=1234&1709051481
Impact
======
.. _breaking-107537-impact-gettext-path:
getText "path" in TypoScript
----------------------------
All usages of :typoscript:`path` in TypoScript :typoscript:`data` now resolve
to absolute URLs instead of relative ones.
.. _breaking-107537-impact-relative-fal-resource:
Relative path to FAL Storage
----------------------------
In installations referencing resources in additional local FAL storages using
a relative path syntax, an exception is thrown.
.. _breaking-107537-impact-cachebusting:
All generated URLs now contain cache busting
--------------------------------------------
Generated URLs differ slightly from previous TYPO3 versions, especially when
cache busting was not applied before.
.. _breaking-107537-impact-querystrings:
Additional query strings applied to the resource identifier
-----------------------------------------------------------
URLs now include both the original query string and the cache-busting
parameter, resulting in different output compared to earlier TYPO3 versions.
Affected installations
======================
.. _breaking-107537-affected-gettext-path:
getText "path" in TypoScript
----------------------------
All installations using :typoscript:`path` in TypoScript :typoscript:`data`.
.. _breaking-107537-affected-relative-fal-resource:
Relative path to FAL Storage
----------------------------
All installations referencing resources in additional local FAL storages using
a relative path syntax (e.g. `my-other-fileadmin/path/to/file.css`).
.. _breaking-107537-affected-cachebusting:
All generated URLs now contain cache busting
--------------------------------------------
All installations having third party code, that misuses generated URLs
to assume file system paths from them.
.. _breaking-107537-affected-querystrings:
Additional query strings applied to the resource identifier
-----------------------------------------------------------
All installations using resource identifiers with custom query strings, for
example:
`EXT:foo/Resources/Public/rte.css?v=123`
Migration
=========
Relative path to FAL Storage
----------------------------
Either convert the relative path to a FAL resource like so:
`FAL:1:/path/to/file.css`
Alternatively it is possible to convert it to a resource URI:
`URI:/my-other-fileadmin/path/to/file.css`
The first will add cache busting, the latter will use the URI as is.
.. index:: Frontend, NotScanned, ext:frontend
@@ -0,0 +1,44 @@
.. include:: /Includes.rst.txt
.. _breaking-107566-1759226580:
=============================================================
Breaking: #107566 - Removed "afterInitializeCurrentPage" hook
=============================================================
See :issue:`107566`
Description
===========
The hook
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['afterInitializeCurrentPage']`
has been removed in favor of the PSR-14 event
:php:`\TYPO3\CMS\Form\Event\AfterCurrentPageIsResolvedEvent`.
Impact
======
Hook implementations registered under `afterInitializeCurrentPage` are
no longer executed in TYPO3 v14.0 and later.
Affected installations
======================
TYPO3 installations with custom extensions using this hook are affected.
The extension scanner reports any usage as a weak match.
Migration
=========
The hook was removed without a deprecation phase to allow extensions to work
with both TYPO3 v13 (using the hook) and TYPO3 v14+ (using the new event)
simultaneously.
Use the :ref:`PSR-14 event <feature-107566-1759226649>` instead to allow
greater influence over the form rendering process. Since the event is
dispatched at a later point, it allows more extensive modifications than the
previous hook.
.. index:: Backend, ext:form, FullyScanned
@@ -0,0 +1,44 @@
.. include:: /Includes.rst.txt
.. _breaking-107568-1759325068:
==============================================
Breaking: #107568 - Removed "afterSubmit" hook
==============================================
See :issue:`107568`
Description
===========
The hook
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['afterSubmit']`
has been removed in favor of the PSR-14 event
:php:`\TYPO3\CMS\Form\Event\BeforeRenderableIsValidatedEvent`.
Impact
======
Hook implementations registered under :php:`afterSubmit` are no longer executed
in TYPO3 v14.0 and later.
Affected installations
======================
TYPO3 installations with custom extensions using this hook are affected.
The extension scanner reports any usage as a weak match.
Migration
=========
The hook was removed without a deprecation phase to allow extensions to work
with both TYPO3 v13 (using the hook) and TYPO3 v14+ (using the new event)
simultaneously.
Use the :ref:`PSR-14 event <feature-107568-1759326362>` instead to allow
greater influence over the form submission process. Since the event is
dispatched at a later point, it allows more extensive modifications than the
previous hook.
.. index:: Backend, ext:form, FullyScanned
@@ -0,0 +1,44 @@
.. include:: /Includes.rst.txt
.. _breaking-107569-1759906416:
==================================================
Breaking: #107569 - Removed "beforeRendering" hook
==================================================
See :issue:`107569`
Description
===========
The hook
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['beforeRendering']`
has been removed in favor of the PSR-14 event
:php:`\TYPO3\CMS\Form\Event\BeforeRenderableIsRenderedEvent`.
Impact
======
Hook implementations registered under :php:`beforeRendering` are no longer
executed in TYPO3 v14.0 and later.
Affected installations
======================
TYPO3 installations with custom extensions using this hook are affected.
The extension scanner reports any usage as a weak match.
Migration
=========
The hook was removed without a deprecation phase to allow extensions to work
with both TYPO3 v13 (using the hook) and TYPO3 v14+ (using the new event)
simultaneously.
Use the :ref:`PSR-14 event <feature-107569-1759906422>` instead to allow
greater influence over the rendering process. Since the event is dispatched
at a later point, it allows more extensive modifications than the previous
hook.
.. index:: Backend, ext:form, FullyScanned
@@ -0,0 +1,111 @@
.. include:: /Includes.rst.txt
.. _breaking-107578-1759400756:
=======================================================================
Breaking: #107578 - Event AfterCacheableContentIsGeneratedEvent changed
=======================================================================
See :issue:`107578`
Description
===========
The frontend rendering event
:php:`\TYPO3\CMS\Frontend\Event\AfterCacheableContentIsGeneratedEvent`
has been adjusted due to the removal of the
:php-short:`\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController` class.
The method :php:`getController()` has been removed and replaced by two new
methods: :php:`getContent()` and :php:`setContent()`.
Impact
======
Event listeners that call :php:`getController()` will trigger a fatal PHP
error and must be adapted.
Affected installations
======================
This event is commonly used in frontend renderingrelated extensions, since
it provides an opportunity to access and manipulate the fully rendered
response body content at a late point in the rendering chain.
Instances with extensions listening to
:php-short:`\TYPO3\CMS\Frontend\Event\AfterCacheableContentIsGeneratedEvent` may be
affected. The extension scanner will detect such usages.
Migration
=========
In most cases, :php:`AfterCacheableContentIsGeneratedEvent->getController()` was
used within event listeners to get and modify the
:php:`TypoScriptFrontendController->content` property at the end of the
rendering process.
The event now provides :php:`getContent()` and :php:`setContent()` methods
to achieve the same goal more directly.
**Before:**
.. code-block:: php
#[\TYPO3\CMS\Core\Attribute\AsEventListener('my-extension')]
public function indexPageContent(
\TYPO3\CMS\Frontend\Event\AfterCacheableContentIsGeneratedEvent $event
): void {
$tsfe = $event->getController();
$content = $tsfe->content;
// ... $content is manipulated here
$tsfe->content = $content;
}
**After:**
.. code-block:: php
use TYPO3\CMS\Core\Attribute\AsEventListener;
use TYPO3\CMS\Frontend\Event\AfterCacheableContentIsGeneratedEvent;
#[AsEventListener('my-extension')]
public function indexPageContent(AfterCacheableContentIsGeneratedEvent $event): void
{
$content = $event->getContent();
// ... $content is manipulated here
$event->setContent($content);
}
**Version check for TYPO3 v13/v14 compatibility:**
.. code-block:: php
use TYPO3\CMS\Core\Attribute\AsEventListener;
use TYPO3\CMS\Core\Information\Typo3Version;
use TYPO3\CMS\Frontend\Event\AfterCacheableContentIsGeneratedEvent;
#[AsEventListener('my-extension')]
public function indexPageContent(
AfterCacheableContentIsGeneratedEvent $event
): void {
$version = new Typo3Version();
if ($version->getMajorVersion() < 14) {
// @todo: Remove if() when TYPO3 v13 compatibility is dropped
$tsfe = $event->getController();
$content = $tsfe->content;
} else {
$content = $event->getContent();
}
// ... $content is manipulated here
if ($version->getMajorVersion() < 14) {
// @todo: Remove if() when TYPO3 v13 compatibility is dropped
$tsfe = $event->getController();
$tsfe->content = $content;
} else {
$event->setContent($content);
}
}
.. index:: PHP-API, FullyScanned, ext:frontend
@@ -0,0 +1,91 @@
.. include:: /Includes.rst.txt
.. _breaking-107578-1759326054:
=======================================================================
Breaking: #107578 - Prepare EXT:adminpanel DataProviderInterface change
=======================================================================
See :issue:`107578`
Description
===========
The :composer:`typo3/cms-adminpanel` system extension provides the interface
:php:`\TYPO3\CMS\Adminpanel\ModuleApi\DataProviderInterface`. It can be used by
extensions that extend the Admin Panel with custom modules and allows storing
additional request-related data in the Admin Panelspecific data store.
The signature of the interface method :php:`getDataToStore()` has changed.
Impact
======
Extension authors may benefit from the additional argument passed with TYPO3
v14, but implementations must be adjusted accordingly.
Affected installations
======================
Most installations are not affected, as few extensions extend the Admin Panel.
Instances with classes implementing
:php-short:`\TYPO3\CMS\Adminpanel\ModuleApi\DataProviderInterface` are affected.
Migration
=========
**Interface until TYPO3 v13:**
.. code-block:: php
namespace TYPO3\CMS\Adminpanel\ModuleApi;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Adminpanel\ModuleApi\ModuleData;
interface DataProviderInterface
{
public function getDataToStore(
ServerRequestInterface $request
): ModuleData;
}
The :php:`getDataToStore()` method is called by the Admin Panel after the
:php:`Response` has been created by the TYPO3 Core.
Starting with TYPO3 v14, the method receives the :php:`ResponseInterface`
as an additional argument:
.. code-block:: php
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Adminpanel\ModuleApi\ModuleData;
public function getDataToStore(
ServerRequestInterface $request,
ResponseInterface $response
): ModuleData;
**Compatibility example for TYPO3 v13 and v14:**
.. code-block:: php
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Adminpanel\ModuleApi\ModuleData;
public function getDataToStore(
ServerRequestInterface $request,
?ResponseInterface $response = null
): ModuleData {
// TYPO3 v13: $response is null
// TYPO3 v14: $response is an instance of ResponseInterface
}
TYPO3 v13 does not pass the second argument, so it must be nullable, and
extensions should not expect to receive an instance of
:php-short:`\Psr\Http\Message\ResponseInterface`.
TYPO3 v14, however, provides the response instance automatically.
.. index:: PHP-API, NotScanned, ext:adminpanel
@@ -0,0 +1,97 @@
.. include:: /Includes.rst.txt
.. _breaking-107654-1728554192:
====================================================================
Breaking: #107654 - Remove random subpage option of doktype=shortcut
====================================================================
See :issue:`107654`
Description
===========
The *random subpage* option for shortcut pages has been removed from TYPO3
Core.
This option allowed shortcut pages to redirect to a random subpage, which was
problematic for caching and resulted in unpredictable behavior - a "random"
page was not truly random, as the page linking to this shortcut was cached.
The following changes have been made:
* The class constant
:php:`\TYPO3\CMS\Core\Domain\Repository\PageRepository::SHORTCUT_MODE_RANDOM_SUBPAGE`
has been removed.
* The method signature of
:php:`\TYPO3\CMS\Core\Domain\Repository\PageRepository::resolveShortcutPage()`
has changed from
:php:`resolveShortcutPage(array $page, bool $resolveRandomSubpages = false, bool $disableGroupAccessCheck = false)`
to
:php:`resolveShortcutPage(array $page, bool $disableGroupAccessCheck = false)`.
* The TCA configuration for :sql:`pages.shortcut_mode` no longer includes the
option *Random subpage of selected/current page*.
Impact
======
Code using the removed constant
:php:`\TYPO3\CMS\Core\Domain\Repository\PageRepository::SHORTCUT_MODE_RANDOM_SUBPAGE`
will fail with a PHP fatal error.
Code calling :php:`PageRepository::resolveShortcutPage()` with three parameters,
where the second parameter was :php:`$resolveRandomSubpages`, will fail. The
second parameter is now :php:`$disableGroupAccessCheck`.
Shortcut pages configured to use *random subpage* mode will now behave as if
they were configured for *first subpage* mode.
Affected installations
======================
TYPO3 installations with:
* Extensions using the constant :php:`PageRepository::SHORTCUT_MODE_RANDOM_SUBPAGE`
* Extensions calling :php:`PageRepository::resolveShortcutPage()` with the
:php:`$resolveRandomSubpages` parameter
* Extensions extending :php-short:`\TYPO3\CMS\Core\Domain\Repository\PageRepository`
and overriding :php:`getPageShortcut()`
* Shortcut pages configured with *random subpage* mode in the database
Migration
=========
Remove any usage of :php:`PageRepository::SHORTCUT_MODE_RANDOM_SUBPAGE`.
Update calls to :php:`PageRepository::resolveShortcutPage()` to remove the
:php:`$resolveRandomSubpages` parameter:
.. code-block:: php
:caption: Before (TYPO3 v13 and lower)
use TYPO3\CMS\Core\Domain\Repository\PageRepository;
$pageRepository = GeneralUtility::makeInstance(PageRepository::class);
$page = $pageRepository->resolveShortcutPage($page, false, true);
.. code-block:: php
:caption: After (TYPO3 v14+)
use TYPO3\CMS\Core\Domain\Repository\PageRepository;
$pageRepository = GeneralUtility::makeInstance(PageRepository::class);
$page = $pageRepository->resolveShortcutPage($page, true);
For shortcut pages configured with *random subpage* mode, update the database
records to use a different shortcut mode (for example, *first subpage* or a
specific target page):
.. code-block:: sql
UPDATE pages
SET shortcut_mode = 1
WHERE shortcut_mode = 2;
.. index:: PHP-API, TCA, Frontend, FullyScanned, ext:core
@@ -0,0 +1,66 @@
.. include:: /Includes.rst.txt
.. _breaking-107677-1760339783:
===========================================================================
Breaking: #107677 - Drop `prepend` and `append` modes from TCA value picker
===========================================================================
See :issue:`107677`
Description
===========
The *prepend* and *append* modes of the value picker specified in TCA and used
in FormEngine (for example
:php:`$GLOBALS['TCA']['tx_example']['columns']['example']['config']['valuePicker']['mode']`)
have been removed.
These modes were designed to insert predefined values before or after the
existing input value, but they served only niche use cases and caused
inconsistent behavior across different input types.
Maintaining these modes introduced unnecessary complexity in both
implementation and accessibility. Prepending or appending content dynamically
to user input fields could easily lead to unexpected results, break input
validation, and interfere with assistive technologies such as screen readers.
Additionally, this approach mixed presentation and data logic in ways that are
not consistent with modern form handling patterns.
Future improvements to the value picker will focus on a consistent
*mode=replace* behavior and may be implemented as new form input types to
provide a more robust and accessible user experience.
Impact
======
Any value picker TCA configuration using the `mode` options `prepend` or
`append` will no longer have any effect. TYPO3 ignores these settings, and the
picker defaults to the standard *replace* behavior.
Affected installations
======================
Installations using custom field wizard configurations or integrations that
rely on the value picker with :php:`mode = prepend` or :php:`mode = append`
are affected.
Migration
=========
There is no direct replacement for the removed modes.
If your implementation depends on prepending or appending content to existing
values, implement a **custom input type** or **custom form element** to handle
this behavior explicitly. This allows you to maintain full control over the
user interface, data handling, and accessibility.
For most use cases, it is recommended to replace prepend or append logic with
the standard *replace* value picker behavior or use dedicated UI controls that
clearly indicate how values are modified.
If the value picker was used to suggest combinable values, consider listing
these elements in the field description instead so that users can copy and
paste them manually into the input field.
.. index:: TCA, FullyScanned, ext:backend
@@ -0,0 +1,65 @@
.. include:: /Includes.rst.txt
.. _breaking-107712-1760548718:
===============================================================================
Breaking: #107712 - New method hasSubmoduleOverview() in ModuleInterface
===============================================================================
See :issue:`107712`
Description
===========
The interface :php:`\TYPO3\CMS\Backend\Module\ModuleInterface` has been extended
with a new method :php:`hasSubmoduleOverview()` to support the new card-based
submodule overview feature introduced in
:ref:`feature-107712-1760548718`.
Impact
======
All custom implementations of
:php:`\TYPO3\CMS\Backend\Module\ModuleInterface` must now implement the new
method :php:`hasSubmoduleOverview(): bool`.
Existing implementations that do not implement this method will trigger a PHP
fatal error.
Affected installations
======================
TYPO3 installations with custom PHP code that directly implement the
:php-short:`\TYPO3\CMS\Backend\Module\ModuleInterface` are affected.
This is uncommon, as most backend modules use the provided
:php:`\TYPO3\CMS\Backend\Module\Module` class or extend from
:php:`\TYPO3\CMS\Backend\Module\BaseModule`.
Migration
=========
Add the :php:`hasSubmoduleOverview()` method to your custom implementation of
:php-short:`\TYPO3\CMS\Backend\Module\ModuleInterface`.
The method should typically return the configured value rather than a fixed
boolean:
.. code-block:: php
use TYPO3\CMS\Backend\Module\ModuleInterface;
class MyCustomModule implements ModuleInterface
{
protected array $configuration = [];
public function hasSubmoduleOverview(): bool
{
// Return the configured value, defaulting to false
return $this->configuration['showSubmoduleOverview'] ?? false;
}
}
This allows the behavior to be controlled through the module's configuration.
.. index:: Backend, PHP-API, NotScanned, ext:backend
@@ -0,0 +1,37 @@
.. include:: /Includes.rst.txt
.. _breaking-107777-1760887464:
================================================================
Breaking: #107777 - Use strict types in Extbase class `Argument`
================================================================
See :issue:`107777`
Description
===========
All properties, method arguments, and return types in
:php:`\TYPO3\CMS\Extbase\Mvc\Controller\Argument` are now strictly typed.
Impact
======
Classes extending :php-short:`\TYPO3\CMS\Extbase\Mvc\Controller\Argument` must now
ensure that all overridden properties, method arguments, and return types
declare strict types accordingly.
Affected installations
======================
TYPO3 installations with custom classes extending
:php-short:`\TYPO3\CMS\Extbase\Mvc\Controller\Argument`.
Migration
=========
Ensure all subclasses of
:php-short:`\TYPO3\CMS\Extbase\Mvc\Controller\Argument` use strict type
declarations for overridden properties, method parameters, and return types.
.. index:: Backend, Frontend, NotScanned, ext:extbase
@@ -0,0 +1,58 @@
.. include:: /Includes.rst.txt
.. _breaking-107783-1760945127:
=======================================================================================
Breaking: #107783 - Registration of metadata extractors via `registerExtractionService`
=======================================================================================
See :issue:`107783`
Description
===========
The method
:php:`\TYPO3\CMS\Core\Resource\Index\ExtractorRegistry::registerExtractionService()`
has been removed in favor of automatic registration via the interface
:php:`\TYPO3\CMS\Core\Resource\Index\ExtractorInterface`.
Registration of metadata extractors now happens automatically when a class
implements the required interface
:php-short:`\TYPO3\CMS\Core\Resource\Index\ExtractorInterface`. No further
registration is necessary.
Impact
======
Any call to :php:`ExtractorRegistry::registerExtractionService()` is now a
no-op and has no effect in TYPO3 v14.0+. Metadata extractors are automatically
registered via the interface.
Affected installations
======================
TYPO3 installations with custom extensions that register metadata extractor
classes via the mentioned method in :file:`ext_localconf.php`.
The extension scanner will report such usages.
Migration
=========
The method has been removed without deprecation in order to allow extensions
to work with TYPO3 v13 (using the registration method) and v14+ (using automatic
interface-based registration) without additional deprecations.
Remove the manual registration from :file:`ext_localconf.php`:
.. code-block:: diff
:caption: EXT:my_ext/ext_localconf.php
- $extractorRegistry = GeneralUtility::makeInstance(ExtractorRegistry::class);
- $extractorRegistry->registerExtractionService(MyExtractor::class);
Since custom extractors already implement the required interface
:php-short:`\TYPO3\CMS\Core\Resource\Index\ExtractorInterface`, no further
changes are required inside the extractor class itself.
.. index:: FAL, PHP-API, FullyScanned, ext:core
@@ -0,0 +1,90 @@
.. include:: /Includes.rst.txt
.. _breaking-107784-1760947244:
===================================================================================
Breaking: #107784 - Remove backend layout data provider registration via `$GLOBALS`
===================================================================================
See :issue:`107784`
Description
===========
The possibility to register backend layout data providers via
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['BackendLayoutDataProvider']`
has been replaced by autoconfiguration using the service tag
:yaml:`page_layout.data_provider`.
The tag is automatically added when a class implements
:php:`\TYPO3\CMS\Backend\View\BackendLayout\DataProviderInterface`. Manual
configuration via :file:`Services.yaml` remains possible, especially when
autoconfiguration is disabled.
Developers need to adapt existing implementations by adding the new method
:php:`getIdentifier()`, as outlined in
:ref:`feature-107784-1760946896`.
Additionally, the possibility to dynamically add backend layout data providers
to the global :php:`DataProviderCollection` via its :php:`add()` method has been
removed. Developers should register their data providers as service definitions
in the container as described above.
Impact
======
Using the global array
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['BackendLayoutDataProvider']`
to register backend layout data providers has no effect in TYPO3 v14.0 and
later.
Affected installations
======================
All installations that use
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['BackendLayoutDataProvider']`
for backend layout data provider registration are affected.
This registration is typically done in an :file:`ext_localconf.php` file.
The extension scanner will report such usages.
Migration
=========
Migrate existing registrations to the new autoconfiguration-based approach.
**Before:**
.. code-block:: php
:caption: EXT:my_extension/ext_localconf.php
use Vendor\MyExtension\View\BackendLayout\MyLayoutDataProvider;
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['BackendLayoutDataProvider']['my_provider']
= MyLayoutDataProvider::class;
**After:**
.. code-block:: php
:caption: EXT:my_extension/Classes/View/BackendLayout/MyLayoutDataProvider.php
use TYPO3\CMS\Backend\View\BackendLayout\DataProviderInterface;
final class MyLayoutDataProvider implements DataProviderInterface
{
// ...
public function getIdentifier(): string
{
return 'my_provider';
}
}
If you need to support multiple TYPO3 versions, you can implement both
registration methods (via :php:`$GLOBALS` and via autoconfiguration).
Ensure that :php:`getIdentifier()` is implemented, which is backward compatible
with older TYPO3 versions even if unused.
.. index:: Backend, PHP-API, FullyScanned, ext:backend
@@ -0,0 +1,358 @@
.. include:: /Includes.rst.txt
.. _breaking-107789-1729603200:
=========================================================================================
Breaking: #107789 - Core TCA and user settings showitem strings use short form references
=========================================================================================
See :issue:`107789`
Description
===========
TYPO3 Core TCA and user settings (:php:`$GLOBALS['TYPO3_USER_SETTINGS']`)
configurations have been updated to use short form
translation reference formats (e.g., `core.form.tabs:*`) instead of
the full `LLL:EXT:` path format in `showitem` strings.
This change affects all core TCA `showitem` definitions that previously
used full `LLL:EXT:` paths for labels. The most prominent updates are
tab labels using the `--div--` syntax, though this pattern may be applied
to other TCA elements in the future.
Examples of changed references in tab labels:
.. code-block:: php
// Before (TYPO3 v13)
'--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general'
'--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access'
'--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language'
.. code-block:: php
// After (TYPO3 v14)
'--div--;core.form.tabs:general'
'--div--;core.form.tabs:access'
'--div--;core.form.tabs:language'
Impact
======
Custom extensions that programmatically manipulate TCA or
:php:`$GLOBALS['TYPO3_USER_SETTINGS']` `showitem` strings
from core tables and expect the full `LLL:EXT:` path format will break.
This particularly affects code that:
- Uses string search/replace operations on `showitem` strings to find or
modify specific labels (tabs, palettes, or other elements)
- Parses `showitem` strings using regular expressions expecting the
`LLL:EXT:` pattern
- Extracts translation keys from TCA configurations for analysis or
documentation purposes
- Builds custom TCA configurations by copying and modifying core
`showitem` strings
Currently, the following label categories have been migrated to short-form:
**Tab labels (--div--):**
- `LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:*`
`core.form.tabs:*`
- `LLL:EXT:filemetadata/Resources/Private/Language/locallang_tca.xlf:tabs.*`
`core.form.tabs:*`
- `LLL:EXT:seo/Resources/Private/Language/locallang_tca.xlf:pages.tabs.*`
`core.form.tabs:*`
**Tab labels (--div--) in TYPO3_USER_SETTINGS:**
- `LLL:EXT:setup/Resources/Private/Language/locallang.xlf:personal_data`
`core.form.tabs:personaldata`
- `LLL:EXT:setup/Resources/Private/Language/locallang.xlf:accountSecurity`
`core.form.tabs:account_security`
- `LLL:EXT:setup/Resources/Private/Language/locallang.xlf:opening`
`core.form.tabs:backend_appearance`
- `LLL:EXT:setup/Resources/Private/Language/locallang.xlf:personalization`
`core.form.tabs:personalization`
- `LLL:EXT:setup/Resources/Private/Language/locallang.xlf:resetTab`
`core.form.tabs:reset_configuration`
**Palette labels (palette definitions):**
- `LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_users.palettes.*`
`core.form.palettes:*`
- `LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.palettes.*`
`core.form.palettes:*`
- `LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.*`
`core.form.palettes:*`
- `LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.*`
`core.form.palettes:*`
- `LLL:EXT:filemetadata/Resources/Private/Language/locallang_tca.xlf:palette.*`
`core.form.palettes:*`
- `LLL:EXT:seo/Resources/Private/Language/locallang_tca.xlf:pages.palettes.*`
`core.form.palettes:*`
**Replaced hardcoded palette label:**
- Removed the hardcoded palette name in string `--palette--;Capabilities;capabilities`
in table :sql:`sys_file_storage` in favor of a label attached directly to
the palette using the short syntax `core.form.palettes:*`.
**Field label overrides removed in showitem definitions:**
Field labels can be overridden in showitem definitions for types or palettes, but
should rather be kept in the field definition itself. The following field label
overrides have been removed from showitem strings in favor of using the field's
own label definition:
- `bodytext;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:bodytext_formlabel`
`bodytext`
- `bodytext;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:field.table.bodytext`
`bodytext`
- `CType;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:CType_formlabel`
`CType`
- `colPos;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:colPos_formlabel`
`colPos`
- `header;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:header_formlabel`
`header`
- `header_layout;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:header_layout_formlabel`
`header_layout`
- `header_link;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:header_link_formlabel`
`header_link`
- `header_position;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:header_position_formlabel`
`header_position`
- `subheader;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:subheader_formlabel`
`subheader`
- `date;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:date_formlabel`
`date`
- `file_collections;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:file_collections.ALT.uploads_formlabel`
`file_collections`
- `filelink_size;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:filelink_size_formlabel`
`filelink_size`
- `image_zoom;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:image_zoom_formlabel`
`image_zoom`
- `imageborder;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.mediaAdjustments.imageborder`
`imageborder`
- `image*;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:imageborder_formlabel`
`frontend.db.tt_content:imageborder`
- `imagecols;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:imagecols_formlabel`
`imagecols`
- `imageorient;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:imageorient_formlabel`
`imageorient`
- `imageheight;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.mediaAdjustments.imageheight`
`imageheight`
- `imagewidth;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.mediaAdjustments.imagewidth`
`imagewidth`
- `frame_class;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:frame_class_formlabel`
`frame_class`
- `starttime;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.starttime_formlabel`
`starttime`
- `endtime;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.endtime_formlabel`
`endtime`
- `fe_group;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.fe_group_formlabel`
`fe_group`
- `media;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:media.ALT.uploads_formlabel`
`media`
- `sectionIndex;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:sectionIndex_formlabel`
`sectionIndex`
- `linkToTop;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:linkToTop_formlabel`
`linkToTop`
- `layout;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:layout_formlabel`
`layout`
- `space_before_class;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:space_before_class_formlabel`
`space_before_class`
- `space_after_class;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:space_after_class_formlabel`
`space_after_class`
- `doktype;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.doktype_formlabel`
`doktype`
- `shortcut_mode;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.shortcut_mode_formlabel`
`shortcut_mode`
- `shortcut;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.shortcut_formlabel`
`shortcut`
- `mount_pid_ol;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.mount_pid_ol_formlabel`
`mount_pid_ol`
- `mount_pid;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.mount_pid_formlabel`
`mount_pid`
- `url;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.url_formlabel`
`url`
- `title;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.title_formlabel`
`title`
- `nav_title;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.nav_title_formlabel`
`nav_title`
- `subtitle;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.subtitle_formlabel`
`subtitle`
- `nav_hide;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:pages.nav_hide_toggle_formlabel`
`nav_hide`
- `extendToSubpages;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.extendToSubpages_formlabel`
`extendToSubpages`
- `abstract;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.abstract_formlabel`
`abstract`
- `keywords;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.keywords_formlabel`
`keywords`
- `author;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.author_formlabel`
`author`
- `author_email;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.author_email_formlabel`
`author_email`
- `lastUpdated;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.lastUpdated_formlabel`
`lastUpdated`
- `newUntil;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.newUntil_formlabel`
`newUntil`
- `backend_layout;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.backend_layout_formlabel`
`backend_layout`
- `backend_layout_next_level;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.backend_layout_next_level_formlabel`
`backend_layout_next_level`
- `module;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.module_formlabel`
`module`
- `content_from_pid;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.content_from_pid_formlabel`
`content_from_pid`
- `cache_timeout;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.cache_timeout_formlabel`
`cache_timeout`
- `l18n_cfg;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.l18n_cfg_formlabel`
`l18n_cfg`
- `is_siteroot;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.is_siteroot_formlabel`
`is_siteroot`
- `no_search;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.no_search_formlabel`
`no_search`
- `php_tree_stop;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.php_tree_stop_formlabel`
`php_tree_stop`
- `editlock;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.editlock_formlabel`
`editlock`
- `media;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.media_formlabel`
`media`
- `tsconfig_includes;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tsconfig_includes`
`tsconfig_includes`
- `TSconfig;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.TSconfig_formlabel`
`TSconfig`
**Field label overrides changed in palette definitions:**
- `hidden;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:pages.hidden_toggle_formlabel`
`hidden;core.db.pages:hidden`
- `hidden;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:field.default.hidden`
`hidden;frontend.db.tt_content:hidden`
- `hidden;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.hidden_formlabel`
`hidden;core.db.pages:hidden`
- `starttime;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:starttime_formlabel`
`starttime;core.db.general:starttime`
- `endtime;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:endtime_formlabel`
`endtime;core.db.general:endtime`
- `fe_group;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:fe_group_formlabel`
`fe_group;core.db.general:fe_group`
- `target;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.target_formlabel`
`target;core.db.pages:link.target`
Affected installations
======================
Installations with custom extensions that:
- Programmatically read and manipulate TCA `showitem` strings from
:php:`$GLOBALS['TCA']` or :php:`$GLOBALS['TYPO3_USER_SETTINGS']`.
- Override core TCA or TYPO3_USER_SETTINGS by copying and modifying
existing `showitem` configurations
- Perform string operations on `showitem` definitions expecting
specific `LLL:EXT:` path formats
- Generate documentation or analysis tools based on TCA label path references
The extension scanner will not detect these usages, as they involve runtime
string manipulation rather than direct PHP API usage.
**Note:**
Additional TCA elements beyond tab labels may follow this pattern in future
TYPO3 versions, further extending the use of short-form references in
`showitem` strings.
Migration
=========
TCA Migration
-------------
Extension developers should review their :file:`Configuration/TCA/Overrides/`
files and any PHP code that manipulates TCA `showitem` strings
programmatically.
**Option 1: Support both formats in string operations**
Update your code to handle both the old `LLL:EXT:` path format and the
new short-form references:
.. code-block:: php
// Before - hardcoded search for old format
if (str_contains($showitem, 'LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general')) {
// Will not work in TYPO3 v14+
}
.. code-block:: php
// After - handle new format
if (str_contains($showitem, 'core.form.tabs:general') ||
str_contains($showitem, 'LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general')) {
// Works in both versions
}
**Option 2: Use the TCA API instead of string manipulation**
Rather than manipulating `showitem` strings directly, use TYPO3's TCA
manipulation APIs:
.. code-block:: php
// Instead of string manipulation
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
// Add fields using the API
ExtensionManagementUtility::addToAllTCAtypes(
'tx_myext_domain_model_foo',
'my_field',
'',
'after:title'
);
**Recommended action for all extension developers**
Scan your extension's :file:`Configuration/TCA/Overrides/` directory and any
PHP code that interacts with `showitem` strings for patterns such as:
- :php:`str_contains()`, :php:`str_replace()`, :php:`preg_match()` or similar
string functions operating on `showitem` values
- String operations looking for `'LLL:EXT:'` patterns in TCA
configurations
- Custom parsing of :php:`$GLOBALS['TCA']` `showitem` strings expecting
specific path formats
This review is especially important since future TYPO3 versions may further
expand the use of short-form references across additional TCA elements.
TYPO3_USER_SETTINGS migrations
------------------------------
Update your code to handle the new short form references:
**Before:**
.. code-block:: php
:caption: EXT:my_extension/ext_tables.php
// Before - hardcoded search for old format
$showitem = $GLOBALS['TYPO3_USER_SETTINGS']['showitem'];
if (str_contains($showitem, 'LLL:EXT:setup/Resources/Private/Language/locallang.xlf:personal_data')) {
// Will not work in TYPO3 v14+
}
**After:**
.. code-block:: php
:caption: EXT:my_extension/ext_tables.php
// After - handle new format
$showitem = $GLOBALS['TYPO3_USER_SETTINGS']['showitem'];
if (str_contains($showitem, 'core.form.tabs:personaldata')
|| str_contains($showitem, 'LLL:EXT:setup/Resources/Private/Language/locallang.xlf:personal_data')) {
// Works in both versions
}
.. index:: TCA, NotScanned, ext:core
@@ -0,0 +1,76 @@
.. include:: /Includes.rst.txt
.. _breaking-107791-1234567890:
=============================================
Breaking: #107791 - Report interfaces removed
=============================================
See :issue:`107791`
Description
===========
The Reports module has been refactored to use native backend submodules instead
of dynamic service-based report registration. Individual reports are now
registered as proper backend submodules in :file:`Configuration/Backend/Modules.php`.
As a result, the following public interfaces have been removed:
* :php:`\TYPO3\CMS\Reports\ReportInterface`
* :php:`\TYPO3\CMS\Reports\RequestAwareReportInterface`
Impact
======
Extensions that register custom reports by implementing
:php:`\TYPO3\CMS\Reports\ReportInterface` or
:php:`\TYPO3\CMS\Reports\RequestAwareReportInterface` will no longer work.
These reports will no longer appear in the backend Reports module.
Affected installations
======================
TYPO3 installations with custom extensions that provide reports by implementing
:php-short:`\TYPO3\CMS\Reports\ReportInterface` or
:php-short:`\TYPO3\CMS\Reports\RequestAwareReportInterface`.
Migration
=========
Custom reports must be migrated to backend submodules.
**Register as a submodule under `system_reports`:**
.. code-block:: php
:caption: EXT:my_extension/Configuration/Backend/Modules.php
use Vendor\MyExtension\Controller\MyReportController;
return [
'system_reports_myreport' => [
'parent' => 'system_reports',
'access' => 'admin',
'path' => '/module/system/reports/myreport',
'iconIdentifier' => 'module-reports',
'labels' => [
'title' => 'my_extension.messages:myreport.title',
'description' => 'my_extension.messages:myreport.description',
],
'routes' => [
'_default' => [
'target' => MyReportController::class . '::handleRequest',
],
],
],
];
The controller should implement a standard PSR-7 request handler that returns a
:php:`\Psr\Http\Message\ResponseInterface` instance.
Alternatively, you can create a standalone module with
`showSubmoduleOverview` enabled if you need to group multiple reports
under your own container module.
.. index:: Backend, PHP-API, NotScanned, ext:reports
@@ -0,0 +1,205 @@
.. include:: /Includes.rst.txt
.. _breaking-107823-1730000000:
================================================================================
Breaking: #107823 - Strict typing and API cleanup in backend template components
================================================================================
See :issue:`107823`
Description
===========
The backend template components system (buttons, dropdown items, and menus) has
been modernized with strict type hints, consistent return types, and improved
architecture to enhance type safety and developer experience.
Impact
======
Extensions that implement or extend backend template components must verify
their type declarations and update any usage of changed methods.
New ComponentInterface
----------------------
A new :php:`\TYPO3\CMS\Backend\Template\Components\ComponentInterface`
has been introduced as the parent interface for both
:php-short:`\TYPO3\CMS\Backend\Template\Components\ButtonInterface` and
:php-short:`\TYPO3\CMS\Backend\Template\Components\DropDownItemInterface`.
This unifies the common contract for all renderable backend components.
Both interfaces now extend
:php-short:`\TYPO3\CMS\Backend\Template\Components\ComponentInterface`,
which defines:
* :php:`isValid(): bool`
* :php:`getType(): string`
* :php:`render(): string`
Custom implementations of :php-short:`\TYPO3\CMS\Backend\Template\Components\ButtonInterface`
or :php-short:`\TYPO3\CMS\Backend\Template\Components\DropDownItemInterface` will
now trigger a :php:`\TypeError` if these return types are missing.
PositionInterface enforced
--------------------------
The :php:`\TYPO3\CMS\Backend\Template\Components\PositionInterface` now enforces
strict type hints:
* :php:`getPosition(): string`
* :php:`getGroup(): int`
This interface allows buttons to define their own fixed position and group,
which automatically override the position and group parameters passed to
:php:`ButtonBar::addButton()`.
Icon nullability
----------------
Icons are now consistently nullable across all button types. The
:php:`AbstractButton::$icon` property and related getter/setter methods now use
:php:`?Icon` instead of :php:`Icon`.
This affects classes extending
:php-short:`\TYPO3\CMS\Backend\Template\Components\Buttons\AbstractButton`, including
:php-short:`\TYPO3\CMS\Backend\Template\Components\Buttons\LinkButton`,
:php-short:`\TYPO3\CMS\Backend\Template\Components\Buttons\InputButton`, and
:php-short:`\TYPO3\CMS\Backend\Template\Components\Buttons\SplitButton`.
.. note::
While icons are technically optional at the type level, validation methods
may still require icons for buttons to be considered valid.
Method signature changes
------------------------
Several methods now have stricter parameter types or modified signatures:
* :php:`MenuItem::isValid()` and :php:`Menu::isValid()` no longer accept
parameters
* :php:`AbstractDropDownItem::render()` now declares a :php:`string` return
type
* Various setter methods now require strict type hints for their parameters
Return type consistency
-----------------------
Abstract classes now use :php:`static` return types for better inheritance
support, while concrete implementations may use :php:`self` or :php:`static`
depending on extensibility requirements.
SplitButton API improvement
---------------------------
The :php:`SplitButton::getButton()` method has been replaced with
:php:`getItems()`, which returns a type-safe
:php-short:`\TYPO3\CMS\Backend\Template\Components\Buttons\SplitButtonItems` DTO
instead of an untyped array.
**Old (removed):**
.. code-block:: php
public function getButton(): array // Returns array with magic keys 'primary' and 'options'
**New:**
.. code-block:: php
public function getItems(): SplitButtonItems // Returns typed DTO
The :php:`SplitButtonItems` DTO provides:
* :php:`public readonly AbstractButton $primary` - The primary action button
* :php:`public readonly array $options` - Array of option buttons
This change improves type safety and prevents runtime errors from accessing
non-existent array keys.
Affected installations
======================
All TYPO3 instances with custom backend components, such as buttons, menus, or
dropdown items, that extend or implement the affected interfaces are impacted.
Migration
=========
Extension authors should:
1. **Verify custom button implementations** have correct return types on
interface methods.
2. **Check custom classes extending abstract buttons** use proper strict types.
3. **Update `isValid()` calls** on :php:`MenuItem` and :php:`Menu` objects
(remove the parameter).
4. **Handle nullable icons** when working with :php:`getIcon()` methods.
Example: implementing ButtonInterface
-------------------------------------
.. code-block:: php
use TYPO3\CMS\Backend\Template\Components\ButtonInterface;
// Before
class CustomButton implements ButtonInterface {
public function isValid() { ... }
public function render() { ... }
public function getType() { ... }
}
.. code-block:: php
use TYPO3\CMS\Backend\Template\Components\ButtonInterface;
// After
class CustomButton implements ButtonInterface {
public function isValid(): bool { ... }
public function render(): string { ... }
public function getType(): string { return static::class; }
}
Example: working with MenuItem/Menu
-----------------------------------
.. code-block:: php
// Before
if ($menuItem->isValid($menuItem)) { ... }
.. code-block:: php
// After
if ($menuItem->isValid()) { ... }
Example: nullable icons
-----------------------
.. code-block:: php
// Handle nullable icon return
$icon = $button->getIcon(); // Now returns ?Icon
$html = $icon?->render() ?? '';
Example: using SplitButton with typed DTO
-----------------------------------------
If you were directly accessing the :php:`getButton()` method:
.. code-block:: php
// Before
$items = $splitButton->getButton();
$primary = $items['primary']; // Magic string key
$options = $items['options']; // Magic string key
.. code-block:: php
// After
$items = $splitButton->getItems();
$primary = $items->primary; // Type-safe property access
$options = $items->options; // Type-safe property access
.. index:: Backend, PHP-API, NotScanned, ext:backend
@@ -0,0 +1,47 @@
.. include:: /Includes.rst.txt
.. _breaking-107831-1761307146:
===================================================================================================
Breaking: #107831 - AfterCachedPageIsPersistedEvent no longer receives TypoScriptFrontendController
===================================================================================================
See :issue:`107831`
Description
===========
The frontend rendering related event
:php:`\TYPO3\CMS\Frontend\Event\AfterCachedPageIsPersistedEvent` has been
modified due to the removal of the class
:php:`\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController`.
The method :php:`getController()` has been removed.
Impact
======
Event listeners that call :php:`getController()` will now trigger a fatal
PHP error and and must be adapted.
Affected installations
======================
Instances with extensions listening for the event
:php-short:`\TYPO3\CMS\Frontend\Event\AfterCachedPageIsPersistedEvent` may be
affected.
The extension scanner will detect and report such usages.
Migration
=========
In most cases, data that was previously retrieved from the
:php-short:`\TYPO3\CMS\Frontend\Controller\`TypoScriptFrontendController`
instance can now be accessed through the request object, available via
:php:`$event->getRequest()`.
See :ref:`breaking-102621-1701937690` for further details about accessing
frontend-related data via the PSR-7 request.
.. index:: Frontend, NotScanned, ext:frontend
@@ -0,0 +1,80 @@
.. include:: /Includes.rst.txt
.. _breaking-107831-1761307521:
==========================================================
Breaking: #107831 - Removed `TypoScriptFrontendController`
==========================================================
See :issue:`107831`
Description
===========
All remaining properties have been removed from
:php:`\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController`, making the
class a readonly internal service used by the TYPO3 Core only.
The class will be fully removed in a later TYPO3 v14 release.
The following instance access patterns have been removed:
* `$GLOBALS['TSFE']`
* `$request->getAttribute('frontend.controller')`
* `$contentObjectRenderer->getTypoScriptFrontendController()`
All API methods that returned an instance of
:php-short:`\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController` -
usually named :php:`getTypoScriptFrontendController()` or similar - have been
removed as well.
Impact
======
Any remaining direct or indirect usage of
:php-short:`\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController` will
now result in a fatal PHP error.
Affected installations
======================
Extensions that still relied on properties or methods of
:php-short:`\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController` are
affected.
The class was already marked *internal* and *breaking* in TYPO3 v13.
In particular, extensions that used
:php:`AbstractContentObject->getTypoScriptFrontendController()` can now access
the relevant data from the PSR-7 request object, for example:
.. code-block:: php
$pageInformation = $request->getAttribute('frontend.page.information');
Migration
=========
See :ref:`breaking-102621-1701937690` for a detailed list of removed properties
and their replacements.
As a specific example, old code that added additional header data like this:
.. code-block:: php
$frontendController = $request->getAttribute('frontend.controller');
$frontendController->additionalHeaderData[] = $myAdditionalHeaderData;
should now use:
.. code-block:: php
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Utility\GeneralUtility;
$pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
$pageRenderer->addHeaderData($myAdditionalHeaderData);
The same approach applies to :php:`additionalFooterData`.
.. index:: Frontend, NotScanned, ext:frontend
@@ -0,0 +1,55 @@
.. include:: /Includes.rst.txt
.. _breaking-107856-1763715381:
=========================================================================================================================
Breaking: #107856 - DataHandler: Remove internal property `copyWhichTables`and properties `neverHideAtCopy`and `copyTree`
=========================================================================================================================
See :issue:`107856`
Description
===========
The following public properties of the PHP class `TYPO3\CMS\Core\DataHandling\DataHandler` have been removed:
* `copyWhichTables`
* `neverHideAtCopy`
* `copyTree`
Impact
======
Accessing or setting the properties will throw a PHP warning and have no effect anymore.
Affected installations
======================
Any installation working with the public properties in a third-party extension.
Migration
=========
The configuration values `neverHideAtCopy ` and `copyTree` are directly read from the
backend user :php:`BE_USER` object. To modify them, use the following values instead:
.. code-block:: php
// Before
DataHandler->neverHideAtCopy
// After
DataHandler->BE_USER->uc['neverHideAtCopy']
// Before
DataHandler->copyTree
// After
DataHandler->BE_USER->uc['copyLevels']
To retain database consistency, the list of tables to be copied now only relied on permissions
of the given backend user. If the user has admin access, all tables will be copied if needed.
If not, all tables with access will be copied.
.. index:: PHP-API, FullyScanned, ext:core
@@ -0,0 +1,78 @@
.. include:: /Includes.rst.txt
.. _breaking-107871-1761597102:
===================================================================================
Breaking: #107871 - Remove backend avatar provider registration via :php:`$GLOBALS`
===================================================================================
See :issue:`107871`
Description
===========
Registering backend avatar providers via
:php:`$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['backend']['avatarProviders']`
has been replaced by autoconfiguration using the :yaml:`backend.avatar_provider`
service tag. This tag is added automatically when the PHP attribute
:php:`#[AsAvatarProvider]` is applied. Manual configuration in
:file:`Services.yaml` is still possible, particularly if autoconfiguration is
disabled.
Impact
======
Using the :php:`$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['backend']['avatarProviders']`
array has no effect in TYPO3 v14.0 and later.
Affected installations
======================
All installations that use
:php:`$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['backend']['avatarProviders']`
to register backend avatar providers are affected. This registration is
typically performed in an :file:`ext_localconf.php` file. The extension
scanner will report any such usages.
Migration
=========
Migrate existing registrations to the new autoconfiguration-based approach.
**Before:**
.. code-block:: php
:caption: EXT:my_extension/ext_localconf.php
use MyVendor\MyExtension\Backend\Avatar\MyAvatarProvider;
$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['backend']
['avatarProviders']['my_provider'] = [
'provider' => MyAvatarProvider::class,
'before' => ['provider-1'],
'after' => ['provider-2'],
];
**After:**
.. code-block:: php
:caption: EXT:my_extension/Classes/Backend/Avatar/MyAvatarProvider.php
use TYPO3\CMS\Backend\Attribute\AsAvatarProvider;
use TYPO3\CMS\Backend\Backend\Avatar\AvatarProviderInterface;
#[AsAvatarProvider(
'my_provider',
before: ['provider-1'],
after: ['provider-2']
)]
final class MyAvatarProvider implements AvatarProviderInterface
{
// ...
}
If you need to support multiple TYPO3 Core versions simultaneously, ensure that
both registration methods are implemented: the legacy :php:`$GLOBALS` based
registration as well as the new tag-based approach.
.. index:: Backend, PHP-API, FullyScanned, ext:backend
@@ -0,0 +1,339 @@
.. include:: /Includes.rst.txt
.. _breaking-107884-1730135000:
=====================================================================
Breaking: #107884 - Rework actions to use Buttons API with Components
=====================================================================
See :issue:`107884`
Description
===========
The record list and file list action system (the "button bar" in every
row of the table-like display) has been completely reworked to use
the Buttons API, utilizing proper component objects instead of plain HTML strings.
This modernization improves type safety, provides better extensibility, and
enables more structured manipulation of action buttons through PSR-14 events.
The following components have been affected by this change:
- :php:`\TYPO3\CMS\Backend\RecordList\Event\ModifyRecordListRecordActionsEvent`
- :php:`\TYPO3\CMS\Filelist\Event\ProcessFileListActionsEvent`
- :php:`\TYPO3\CMS\Backend\RecordList\DatabaseRecordList::makeControl()`
Buttons can now be placed into *ActionGroups*, which are identified by the
PHP enum :php:`\TYPO3\CMS\Backend\Template\Components\ActionGroup` and
distinguish between a "primary" and a "secondary" group.
In addition, :php:`\TYPO3\CMS\Backend\Template\Components\ComponentGroup`
enhances the ability to group multiple Button API Components into a single data
object and manage their state.
Impact
======
Extensions that listen to the
:php-short:`\TYPO3\CMS\Backend\RecordList\Event\ModifyRecordListRecordActionsEvent`
or :php-short:`\TYPO3\CMS\Filelist\Event\ProcessFileListActionsEvent` to modify
record or file actions need to be updated.
The events no longer work with HTML strings but with
:php-short:`\TYPO3\CMS\Backend\Template\Components\ComponentInterface` objects
(see :issue:`107823`).
Extensions that directly call :php:`DatabaseRecordList::makeControl()` must
update their code, as the :php:`$table` parameter has been removed.
ModifyRecordListRecordActionsEvent
----------------------------------
The method :php:`setAction()` now requires a
:php-short:`\TYPO3\CMS\Backend\Template\Components\ComponentInterface` object, and
:php:`getAction()` now returns either `null` or a
:php-short:`\TYPO3\CMS\Backend\Template\Components\ComponentInterface` instance.
The following methods now expect an
:php-short:`\TYPO3\CMS\Backend\Template\Components\ActionGroup` enum value as the
:php:`$group` parameter:
- :php:`hasAction()`
- :php:`getAction()`
- :php:`removeAction()`
- :php:`getActionGroup()`
The method :php:`getRecord()` no longer returns a raw array but an instance of
the Record API.
A new method :php:`getRequest()` has been added to access the current PSR-7
request context.
**Removed methods:**
- :php:`getActions()`
- :php:`setActions()`
- :php:`getTable()`
ProcessFileListActionsEvent
---------------------------
The :php:`\TYPO3\CMS\Filelist\Event\ProcessFileListActionsEvent` has received
identical API changes to
:php-short:`\TYPO3\CMS\Backend\RecordList\Event\ModifyRecordListRecordActionsEvent`,
allowing manipulation of items in both supported
:php-short:`\TYPO3\CMS\Backend\Template\Components\ActionGroup` contexts
(*primary* and *secondary*).
**New methods:**
- :php:`setAction()`
- :php:`getAction()`
- :php:`removeAction()`
- :php:`moveActionTo()`
- :php:`getActionGroup()`
- :php:`getRequest()`
Buttons can now also be repositioned or inserted at specific before/after
locations within an action group.
**Removed methods:**
- :php:`getActionItems()`
- :php:`setActionItems()`
Affected installations
======================
TYPO3 installations with custom PHP code that modifies record or file list
actions, or utilizes the mentioned PSR-14 events, are affected.
Migration
=========
DatabaseRecordList::makeControl()
---------------------------------
.. code-block:: php
// Before
public function makeControl($table, RecordInterface $record): string
// After
public function makeControl(RecordInterface $record): string
The :php:`$table` parameter has been removed, as the table name can now be
retrieved from the :php:`RecordInterface` via
:php:`$record->getMainType()`.
Adjust calls accordingly:
.. code-block:: diff
:caption: EXT:my_extension/Classes/ViewHelper/MyControlViewHelper.php
// ...
public function render(): string
{
$row = BackendUtility::getRecord($table, $someRowUid);
$databaseRecordList = GeneralUtility::makeInstance(DatabaseRecordList::class);
- return $databaseRecordList->makeControl($table, $row);
+ return $databaseRecordList->makeControl($row);
}
ProcessFileListActionsEvent
---------------------------
Event listeners must now compose buttons via the Button API and add each
component using the events :php:`setAction()` method.
Internally, buttons are placed into an
:php-short:`\TYPO3\CMS\Backend\Template\Components\ActionGroup` container,
retrieved via :php:`ActionGroup::primary` or :php:`ActionGroup::secondary`.
The previous :php:`getActionItems()` logic is replaced with
:php:`getActionGroup()` to fetch the corresponding button group.
Instead of manipulating raw HTML, you must now create components using the
:php-short:`\TYPO3\CMS\Backend\Template\Components\ComponentFactory`.
.. code-block:: php
// Before
use TYPO3\CMS\Filelist\Event\ProcessFileListActionsEvent;
class ProcessFileListActionsEventListener
{
public function __invoke(ProcessFileListActionsEvent $event): void
{
$items = $event->getActionItems();
$items['my-own-action'] = '<a href="..." class="btn btn-default">...</a>';
unset($items['some-other-action']);
$event->setActionItems($items);
}
}
.. code-block:: php
// After
use TYPO3\CMS\Backend\Template\Components\ActionGroup;
use TYPO3\CMS\Backend\Template\Components\ComponentFactory;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Filelist\Event\ProcessFileListActionsEvent;
class ProcessFileListActionsEventListener
{
public function __construct(
private readonly ComponentFactory $componentFactory,
private readonly IconFactory $iconFactory,
) {}
public function __invoke(ProcessFileListActionsEvent $event): void
{
$viewButton = $this->componentFactory->createGenericButton()
->setIcon($this->iconFactory->getIcon('actions-view'))
->setTitle('My title');
$event->setAction($viewButton, 'my-own-action', ActionGroup::primary);
$event->removeAction('some-other-action', ActionGroup::primary);
}
}
ModifyRecordListRecordActionsEvent
----------------------------------
This event now behaves identically to the file list event:
actions must be created via the Button API and added as
:php:`ComponentInterface` instances using :php:`setAction()`.
The :php:`setActions()` and :php:`getActions()` methods are removed and must be
replaced by distinct calls to :php:`setAction()` or use
:php:`getActionGroup()` to access existing actions.
The :php:`getRecord()` method now returns a Record API object instead of an
array.
:php:`getTable()` can be replaced with
:php:`getRecord()->getMainType()`.
**Modifying actions example:**
.. code-block:: php
// Before
use TYPO3\CMS\Backend\RecordList\Event\ModifyRecordListRecordActionsEvent;
class ModifyRecordListRecordActionsEventListener
{
public function __invoke(ModifyRecordListRecordActionsEvent $event): void
{
$items = $event->getActions();
unset($items['my-own-action']);
$items['my-own-action'] = '<a href="..." class="btn btn-default">...</a>';
unset($existing['some-other-action']);
$event->setActions($items);
$event->setAction('<button ...></button>', 'my-other-own-action', 'secondary');
}
}
.. code-block:: php
// After
use TYPO3\CMS\Backend\RecordList\Event\ModifyRecordListRecordActionsEvent;
use TYPO3\CMS\Backend\Template\Components\ActionGroup;
use TYPO3\CMS\Backend\Template\Components\ComponentFactory;
use TYPO3\CMS\Backend\RecordList\Event\ModifyRecordListRecordActionsEvent;
use TYPO3\CMS\Core\Imaging\IconFactory;
class ModifyRecordListRecordActionsEventListener
{
public function __construct(
private readonly ComponentFactory $componentFactory,
private readonly IconFactory $iconFactory,
) {}
public function __invoke(ModifyRecordListRecordActionsEvent $event): void
{
$viewButton = $this->componentFactory->createGenericButton()
->setIcon($this->iconFactory->getIcon('actions-view'))
->setTitle('My title');
$event->setAction($viewButton, 'my-own-action', ActionGroup::primary);
$event->removeAction('some-other-action', ActionGroup::primary);
$inputButton = $this->componentFactory->createInputButton()
->setTitle('My Button');
$event->setAction($inputButton, 'my-other-own-action', ActionGroup::secondary);
}
}
Accessing groups
^^^^^^^^^^^^^^^^
.. code-block:: php
// Before
$event->getAction('my-button', 'primary');
$event->hasAction('my-button', 'primary');
$event->removeAction('my-button', 'primary');
$event->getActionGroup('primary');
.. code-block:: php
// After
use TYPO3\CMS\Backend\Template\Components\ActionGroup;
$event->getAction('my-button', ActionGroup::primary);
$event->hasAction('my-button', ActionGroup::primary);
$event->removeAction('my-button', ActionGroup::primary);
$event->getActionGroup(ActionGroup::primary);
Accessing record
^^^^^^^^^^^^^^^^
.. code-block:: php
// Before
$uid = $event->getRecord()['uid'];
$title = $event->getRecord()['title'];
.. code-block:: php
// After
$uid = $event->getRecord()->getUid();
$title = $event->getRecord()->getRawRecord()['title'];
Dual-version compatibility
--------------------------
To support both TYPO3 v13 and v14, extensions can use a version check within
event listeners:
.. code-block:: php
use TYPO3\CMS\Backend\RecordList\Event\ModifyRecordListRecordActionsEvent;
use TYPO3\CMS\Backend\Template\Components\ActionGroup;
use TYPO3\CMS\Core\Information\Typo3Version;
class ModifyRecordListRecordActionsEventListener
{
public function __invoke(ModifyRecordListRecordActionsEvent $event): void
{
if ((new Typo3Version())->getMajorVersion() >= 14) {
$viewButton = $this->componentFactory->createGenericButton()
->setIcon($this->iconFactory->getIcon('actions-view'))
->setTitle('My title');
$event->setAction($viewButton, 'my-own-action', ActionGroup::primary);
$event->removeAction('some-other-action', ActionGroup::primary);
} else {
$items = $event->getActions();
unset($items['my-own-action']);
$items['my-own-action'] = '<a href="..." class="btn btn-default">...</a>';
unset($existing['some-other-action']);
$event->setActions($items);
}
}
}
.. index:: Backend, PHP-API, PartiallyScanned, ext:backend, ext:filelist
@@ -0,0 +1,91 @@
.. include:: /Includes.rst.txt
.. _breaking-107927-1763052738:
=========================================================================================
Breaking: #107927 - Remove "external" property / option from TypoScript and AssetRenderer
=========================================================================================
See :issue:`107927`
Description
===========
The :typoscript:`resource` property :typoscript:`external` in the :typoscript:`PAGE` properties
:typoscript:`includeCSS`, :typoscript:`includeCSSLibs`, :typoscript:`includeJS`,
:typoscript:`includeJSFooter`, :typoscript:`includeJSFooterlibs` and :typoscript:`includeJSLibs`
is now obsolete.
This also obsoletes the :ref:`External option in AssetRenderer <feature-102255-1726090749>`.
Both are removed in favor of the new unified :ref:`URI resource definition <feature-107537-1759136314>`.
Instead of marking URIs as URIs with an additional option, prefix the URI, that shall be used with `URI:`,
or simply use absolute URLs starting with `http(s)://`, where the prefix is not required.
This URI resource definition will work across the system, not only in TypoScript or `AssetCollector`/ `AssetRenderer`.
Impact
======
Using the `external` property in TypoScript or the `external` option in `AssetCollector`
will have no effect any more. If absolute URLs have been used as resources, everything
will work as before. Relative URIs **must** be prefixed with `URI:` from now on, otherwise
an exception is thrown.
Additionally, the string after the `URI:` keyword **must** be a valid URI, otherwise an exception
is thrown as well. Before this change, invalid URIs (marked as external) would have been rendered
to HTML, without any obvious feedback for developers or integrators. Browsers then ignored
such invalid references.
Affected installations
======================
TYPO3 installations using the `external` property in TypoScript or the `external` option in `AssetCollector`.
Migration
=========
TypoScript before:
.. code-block:: typoscript
page = PAGE
page.includeCSS {
main = https://example.com/styles/main.css
main.external = 1
other = /styles/main.css
other.external = 1
}
TypoScript after:
.. code-block:: typoscript
page = PAGE
page.includeCSS {
main = https://example.com/styles/main.css
other = URI:/styles/main.css
}
PHP Code before:
.. code-block:: php
$assetCollector->addStyleSheet(
'myCssFile',
'/styles/main.css',
[],
['external' => true]
);
PHP Code after:
.. code-block:: php
$assetCollector->addStyleSheet(
'myCssFile',
'URI:/styles/main.css',
);
.. index:: Frontend, NotScanned, ext:frontend
@@ -0,0 +1,68 @@
.. include:: /Includes.rst.txt
.. _breaking-107943-1761860828:
==========================================================================
Breaking: #107943 - Frontend and backend HTTP response compression removed
==========================================================================
See :issue:`107943`
Description
===========
The TYPO3 frontend and backend applications previously allowed compressing
their HTTP responses using the configuration options
:php:`$GLOBALS['TYPO3_CONF_VARS']['FE']['compressionLevel']` and
:php:`$GLOBALS['TYPO3_CONF_VARS']['BE']['compressionLevel']`.
This feature, which was always disabled by default, has now been removed.
TYPO3 will no longer compress its HTTP responses itself.
Response compression should be handled by the web server rather than the
application layer.
Removing this feature avoids potential conflicts when both TYPO3 and the web
server attempt to compress responses and allows modern web servers to use
advanced compression algorithms such as brotli or zStandard when supported by
the client.
Impact
======
TYPO3 can no longer compress its HTTP responses.
This responsibility is now fully delegated to the web server.
HTTP response compression had to be explicitly enabled before, so most
installations will not notice a change unless they relied on this setting.
Affected installations
======================
Instances that configured
:php:`$GLOBALS['TYPO3_CONF_VARS']['FE']['compressionLevel']` or
:php:`$GLOBALS['TYPO3_CONF_VARS']['BE']['compressionLevel']` to non-zero values
are affected.
Administrators should verify that the web server applies HTTP compression by
checking for a response header such as:
:code:`Content-Encoding: gzip`
when requesting frontend or backend documents with a header like:
:code:`Accept-Encoding: gzip, deflate`
All commonly used web servers enable this feature by default.
Migration
=========
The configuration toggles for the backend :php:`$GLOBALS['TYPO3_CONF_VARS']['BE']['compressionLevel']`
and the frontend :php:`$GLOBALS['TYPO3_CONF_VARS']['FE']['compressionLevel']` are
obsolete, existing settings in :file:`settings.php` configuration files are
actively removed when first using the install tool after upgrade to TYPO3 v14.
.. index:: Backend, Frontend, LocalConfiguration, NotScanned, ext:core
@@ -0,0 +1,52 @@
.. include:: /Includes.rst.txt
.. _breaking-107944-1761867359:
===========================================================================================
Breaking: #107944 - Frontend CSS file processing no longer removes comments and whitespaces
===========================================================================================
See :issue:`107944`
Description
===========
When the TYPO3 frontend was configured to compress included CSS assets, it also
attempted to minify CSS by removing comments and certain whitespace characters.
This behavior has now been removed. The previous implementation was brittle,
especially with modern CSS syntax, and provided no measurable performance
benefit in either file transfer or client-side parsing.
Impact
======
CSS asset files included in frontend pages may become slightly larger if they
contain many comments. TYPO3s internal CSS parsing was disabled by default and
only active when explicitly enabled using
:php:`$GLOBALS['TYPO3_CONF_VARS']['FE']['compressionLevel']`
along with additional TypoScript configuration.
In most cases, this change has minimal or no practical impact.
Affected installations
======================
Instances that actively used TYPO3's built-in CSS parsing feature for frontend
asset management are affected.
Migration
=========
If minimizing CSS file size is important, consider one of the following options:
- Optimize or minify CSS files manually during deployment.
- Accept that comments and whitespace are retained (usually negligible impact).
- Preferably, integrate a dedicated frontend build chain to handle CSS and
JavaScript minification.
Modern frontend build tools provide many additional advantages, such as
linting, syntax validation, and advanced optimizations, which are beyond the
scope of the TYPO3 Core.
.. index:: Frontend, NotScanned, ext:frontend
@@ -0,0 +1,75 @@
.. include:: /Includes.rst.txt
.. _breaking-107945-1761875852:
===================================================================
Breaking: #107945 - Class FlexFormService merged into FlexFormTools
===================================================================
See :issue:`107945`
Description
===========
The class :php:`\TYPO3\CMS\Core\Service\FlexFormService` has been merged into
:php:`\TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools`.
The following methods are affected:
* :php:`FlexFormService->convertFlexFormContentToArray($flexFormContent, $languagePointer = 'lDEF', $valuePointer = 'vDEF'): array`
is now :php:`FlexFormTools->convertFlexFormContentToArray(string $flexFormContent): array`.
The method name is unchanged, but the method signature has been simplified.
* :php:`FlexFormService->convertFlexFormContentToSheetsArray(string $flexFormContent, string $languagePointer = 'lDEF', string $valuePointer = 'vDEF'): array`
is now :php:`FlexFormTools->convertFlexFormContentToSheetsArray(string $flexFormContent): array`.
Again, the name is identical, but the parameters have been reduced.
* The helper method :php:`FlexFormService->walkFlexFormNode()` has been made a
private method within :php:`FlexFormTools`.
Impact
======
Instantiating or injecting :php-short:`\TYPO3\CMS\Core\Service\FlexFormService`
remains possible in TYPO3 v14 due to a maintained class alias for backward
compatibility.
This alias will be **removed in TYPO3 v15**.
Affected installations
======================
Any extensions or TYPO3 installations using
:php-short:`\TYPO3\CMS\Core\Service\FlexFormService` are affected.
The extension scanner will automatically detect these usages.
Migration
=========
Extensions typically did not use the now internal helper method
:php:`walkFlexFormNode()`.
In the unlikely case this private method was used, its functionality must now be
implemented within the consuming extension.
The methods :php:`convertFlexFormContentToArray()` and
:php:`convertFlexFormContentToSheetsArray()` have lost their second and third
arguments.
These parameters (:php:`lDEF` and :php:`vDEF`) were already fixed internally in
TYPO3 and could no longer be changed, so their removal has no functional impact.
To continue using these methods, extensions should inject
:php-short:`\TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools` instead of
:php:`FlexFormService`.
For extensions that need to remain compatible with both TYPO3 v13 and v14, it is
still possible to use :php-short:`\TYPO3\CMS\Core\Service\FlexFormService` for
now.
However, when adding compatibility for TYPO3 v15 (and dropping TYPO3 v13),
extensions must switch fully to
:php-short:`\TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools`.
.. index:: FlexForm, PHP-API, FullyScanned, ext:core
@@ -0,0 +1,125 @@
.. include:: /Includes.rst.txt
.. _breaking-108054-1762881326:
=============================================================================
Breaking: #108054 - Enforce explicit opt-in for TypoScript/TSconfig callables
=============================================================================
See :issue:`108054`
Description
===========
To strengthen TYPO3's security posture and implement defense-in-depth
principles, a new hardening mechanism has been introduced that requires
explicit opt-in for methods and functions that can be invoked through
TypoScript configuration.
The new PHP attribute
:php:`#[\TYPO3\CMS\Core\Attribute\AsAllowedCallable]` must be applied to
any method that should be callable via:
* TypoScript :typoscript:`userFunc` processing (including the
:typoscript:`USER` and :typoscript:`USER_INT` content objects)
* TypoScript :typoscript:`stdWrap` functions
:typoscript:`preUserFuncInt`, :typoscript:`postUserFunc` and
:typoscript:`postUserFuncInt`
* TypoScript constant comment user functions
* TSconfig :typoscript:`renderFunc` in suggest wizard configuration
This security enhancement implements strong defaults through explicit
configuration, following the principle of least privilege.
Implementation details:
* New :php:`\TYPO3\CMS\Core\Attribute\AsAllowedCallable` PHP attribute
* New :php:`\TYPO3\CMS\Core\Security\AllowedCallableAssertion` service
for validation
* Enhanced
:php:`\TYPO3\CMS\Core\Utility\GeneralUtility::callUserFunction()`
* Enhanced
:php:`\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::callUserFunction()`
Impact
======
Extension code that provides custom processing methods callable from
TypoScript or TSconfig will fail with a
:php:`\TYPO3\CMS\Core\Security\AllowedCallableException` if the target
method is not explicitly marked with the :php:`#[AsAllowedCallable]`
attribute.
The error message will be:
.. code-block:: text
Attribute TYPO3\CMS\Core\Attribute\AsAllowedCallable required for
callback reference: ["VendorName\\ExtensionName\\ClassName","methodName"]
Affected installations
======================
Scenarios using:
* custom processing via TypoScript `userFunc`
* custom processing via TypoScript constant comments
* custom suggest wizard rendering via TSconfig `renderFunc`
Migration
=========
Add the :php:`#[AsAllowedCallable]` attribute to all methods that should
be callable from TypoScript or TSconfig.
**TypoScript userFunc example:**
.. code-block:: php
:caption: EXT:my_extension/Classes/UserFunc/CustomProcessor.php
use TYPO3\CMS\Core\Attribute\AsAllowedCallable;
class CustomProcessor
{
#[AsAllowedCallable]
public function process(
string $content,
array $conf
): string {
return $content;
}
}
The attribute may be applied to:
* public instance methods
* public static methods
* public :php:`__invoke()` methods
* custom functions in the global namespace
Native PHP functions in the global namespace must be wrapped explicitly.
**Example for custom functions in the global namespace:**
.. code-block:: php
namespace {
use TYPO3\CMS\Core\Attribute\AsAllowedCallable;
#[AsAllowedCallable]
function customGlobalUserFunction(): string
{
return '...';
}
#[AsAllowedCallable]
function nativePhpHashWrapper(
string $algo,
string $data,
bool $binary = false
): string {
return \hash($algo, $data, $binary);
}
}
.. index:: TSConfig, TypoScript, NotScanned, ext:core
@@ -0,0 +1,276 @@
.. include:: /Includes.rst.txt
.. _breaking-108055-1762346705:
========================================================================
Breaking: #108055 - Removed frontend asset concatenation and compression
========================================================================
See :issue:`108055`
Description
===========
Introduction
------------
The implementation of CSS and JavaScript asset concatenation and
pre-compression has been removed from the TYPO3 Core in v14.
The following TypoScript options are now obsolete:
* Config property :typoscript:`config.compressCss`
* Config property :typoscript:`config.compressJs`
* Config property :typoscript:`config.concatenateCss`
* Config property :typoscript:`config.concatenateJs`
* The :typoscript:`resource` properties
:typoscript:`disableCompression` and
:typoscript:`excludeFromConcatenation` in the
:typoscript:`PAGE` properties :typoscript:`includeCSS`,
:typoscript:`includeCSSLibs`, :typoscript:`includeJS`,
:typoscript:`includeJSFooter`, :typoscript:`includeJSFooterlibs`
and :typoscript:`includeJSLibs`.
Example:
.. code-block:: typoscript
page = PAGE
page.includeCSS {
main = EXT:site_package/Resources/Public/Css/main.css
# obsolete
main.disableCompression = 1
# obsolete
main.excludeFromConcatenation = 1
}
The configuration option
:php:`$GLOBALS['TYPO3_CONF_VARS']['FE']['compressionLevel']` is obsolete
in combination with :ref:`breaking-107943-1761860828`. Existing settings
in :file:`settings.php` configuration files are automatically removed
when the install tool is first used after upgrading to TYPO3 v14.
The PHP class :php:`\TYPO3\CMS\Core\Resource\ResourceCompressor` has
been removed.
Feature rundown
---------------
In TYPO3 versions prior to v14, the system included a built-in mechanism
to compile multiple registered CSS and JavaScript files into single files
and to prepare compressed versions of those concatenated files for
direct delivery by the web server.
This functionality had to be explicitly enabled by setting the global
configuration option
:php:`$GLOBALS['TYPO3_CONF_VARS']['FE']['compressionLevel']` and the
TypoScript options :php:`config.concatenate*` and optionally
:php:`config.compress*`. CSS and JavaScript files registered in the
frontend using the :typoscript:`PAGE.include*` options were then
concatenated and optionally compressed into a single file.
The implementation also concatenated external asset resources referenced
via :code:`http` and :code:`https`, which were fetched server-side using
:php:`GeneralUtility::getUrl()` and merged with local resources.
Concatenation was designed to be as transparent as possible: hashes were
created from all referenced file names and their contents (including
external content) for each TYPO3 frontend page request, generating
unique file names that changed whenever an included file or its content
was modified. The resulting concatenated files were then referenced in
the generated HTML page instead of the original resource links.
Pre-compression operated on top of concatenation: if enabled, a gzip-
compressed :file:`.gz` file was created and referenced in the HTML page
response.
Configuration was handled via TypoScript, while asset registration could
be performed using TypoScript or PHP with the :php:`PageRenderer`. The
Fluid asset ViewHelpers :html:`f:asset.css` and :html:`f:asset.script`
register assets using the :php:`AssetCollector`, introduced in TYPO3
v10. This implementation never supported concatenation or compression,
as it was developed independently from the PageRenderer's asset handling
and did not use the :php:`ResourceCompressor`.
Concatenation and compression removal reasoning
-----------------------------------------------
A closer look at the concatenation and compression functionality reveals
several reasons for its removal:
* **HTTP/2 and HTTP/3**: Modern HTTP versions allow multiple resource
requests in parallel ("multiplexing"), making server-side asset
concatenation obsolete. These versions also provide significant
performance improvements on both the server and client sides compared
to HTTP/1.1 with concatenation. HTTP/2 and HTTP/3 are only available
via SSL (HTTPS), which is now the standard for all serious websites.
All major web servers and browsers have supported at least HTTP/2 for
years.
* **Fragile implementation**: Concatenating multiple CSS files within
the application caused path and encoding issues. The resulting files
had to be stored in writable public directories, and relative paths in
CSS files (such as those in :css:`@import` rules) had to be parsed and
adjusted. Additionally, the CSS statement :css:`@charset` had to be
parsed since it must appear only once per CSS file, leading to
potential collisions that have never been resolved.
* **Parallel systems**: Concatenation and compression were supported
only for assets registered via TypoScript :typoscript:`page.include*`
or the :php:`PageRenderer` in PHP. The Fluid ViewHelpers
:html:`f:asset.css` and :html:`f:asset.script` operated independently
and never supported these features. Removing concatenation and
compression simplifies future unification of both asset systems.
* **Performance issues with external assets**: To create as few asset
resources as possible, external assets (example:
:code:`https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js`)
were by default (if :typoscript:`excludeFromConcatenation = 1` was not
explicitly set) fetched by TYPO3 when creating the page. The hashed
resource path and the file content were part of the created
concatenation filename. This ensured that the server-side created file
was always current. TYPO3 therefore fetched external resources for
*each* uncached page request. Worse, it fetched those external
resources for *each request* that contained a non-cached content
element ("INT" elements), and also for *each request* when an instance
enabled CSP handling. This could easily lead to severe performance
degradation.
* **Compression dependency**: Pre-compression (gzip) was only available
when concatenation was enabled, adding further complexity and
limitations.
* **HTTP violations with caching**: When TYPO3 cached a page that
referenced pre-compressed assets, it stored the version based on the
clients :code:`Accept-Encoding` header. Subsequent requests from
clients not supporting gzip would still receive references to
compressed assets, violating HTTP standards.
* **Double compression risk**: Web servers might automatically re-
compress already compressed files. TYPO3 tried to prevent this with an
Apache-specific :file:`.htaccess` configuration, but other servers
like nginx required custom setups, often confusing integrators.
* **Modern compression standards**: Modern web servers and browsers
support more efficient algorithms such as Brotli and Zstandard, which
TYPO3 never implemented due to the complexity of its existing system.
* **Minimal performance gain**: The benefit of pre-compression was
minor. Modern web servers can compress small assets (like typical CSS
or JS files) on the fly with negligible overhead. As a rough ballpark
estimation, a single CPU core can compress hundreds of MB per second,
while a large JavaScript library like jQuery is usually below 100 KB.
CPU time is rarely the bottleneck.
In summary, asset concatenation and pre-compression are no longer needed
and should not be handled at the application level. The implementation
was riddled with issues over the years and integrators struggled to
reach working solutions. The Core team closed issues in this area for
years with "Won't fix, use a different solution."
Alternatives
------------
Most TYPO3 instances can operate perfectly well without the removed
asset concatenation and compression features. Modern browsers, web
servers, and HTTP protocol versions provide efficient alternatives that
make the previous TYPO3-internal implementation unnecessary.
If your instance still relies on concatenated or pre-built asset bundles
for specific use cases, consider the following alternatives:
* **Use a modern bundler**: Tools such as `Vite <https://vitejs.dev/>`_
or Webpack can handle asset concatenation, minification, and
optimization during the build process. A TYPO3-specific integration is
available as an extension:
`Vite AssetCollector <https://extensions.typo3.org/extension/
vite_asset_collector>`_.
* **Consider the `sgalinski/scriptmerger` extension**: This community
extension provides an alternative approach to script and stylesheet
merging and compression. It may be useful for projects that cannot yet
switch to build-time bundling.
* **Enable HTTP/2 or HTTP/3**: Modern HTTP versions support
multiplexing, allowing browsers to download multiple assets
simultaneously from a single connection, eliminating the need for
server-side concatenation.
Example **Apache** configuration:
.. code-block:: plaintext
<IfModule http2_module>
Protocols h2 http/1.1
</IfModule>
# Optional: enable pre-compressed asset delivery
AddEncoding gzip .gz
AddType "text/javascript" .js.gz
AddType "text/css" .css.gz
<FilesMatch "\.(js|css)\.gz$">
ForceType text/plain
Header set Content-Encoding gzip
</FilesMatch>
Example **nginx** configuration:
.. code-block:: plaintext
# Enable HTTP/2 on your SSL virtual host
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/ssl/certs/example.crt;
ssl_certificate_key /etc/ssl/private/example.key;
# Serve pre-compressed assets if available
gzip_static on;
# Optionally also enable on-the-fly compression
gzip on;
gzip_types text/css application/javascript;
[...]
}
Both configurations ensure that compressed versions of static assets
(e.g., :file:`.js.gz` or :file:`.css.gz`) are automatically delivered
to clients that support gzip encoding.
Both Apache and nginx can also cache the compressed output in memory
or on disk to avoid runtime overhead. The keywords to look for are
:code:`mod_deflate` with :code:`mod_cache` for Apache, and
:code:`proxy_cache` for nginx.
* **Use a Content Delivery Network (CDN)**: For TYPO3 instances
experiencing heavy frontend traffic or high asset load, a CDN can
serve static resources such as CSS, JavaScript, and images directly
from distributed edge servers. This offloads delivery from the main
web server, reduces latency, and improves caching efficiency.
In summary, most TYPO3 setups can safely rely on HTTP/2, modern build
pipelines, and proper web server or CDN configuration to achieve optimal
frontend performance without any TYPO3-internal concatenation or
compression.
Impact
======
The configuration toggles mentioned above are now obsolete, and TYPO3
will no longer concatenate or compress included assets.
Affected installations
======================
Instances that configured
:php:`$GLOBALS['TYPO3_CONF_VARS']['FE']['compressionLevel']` to non-zero
values and enabled the TypoScript settings described above for asset
concatenation or compression are affected.
Migration
=========
Consider one or more of the alternatives outlined above.
.. index:: Frontend, LocalConfiguration, TypoScript, NotScanned, ext:frontend
@@ -0,0 +1,117 @@
.. include:: /Includes.rst.txt
.. _breaking-108055-1762951248:
==================================================================
Breaking: #108055 - Removed PageRenderer related hooks and methods
==================================================================
See :issue:`108055`
Description
===========
The removal of frontend asset concatenation and compression as described in
:ref:`breaking-108055-1762346705` has some impact on the PHP API as well,
mainly due to removed code.
The following methods have been removed from the class
:php-short:`\TYPO3\CMS\Core\Page\PageRenderer`:
* :php:`disableConcatenateCss()`
* :php:`enableConcatenateCss()`
* :php:`getConcatenateCss()`
* :php:`disableCompressCss()`
* :php:`enableCompressCss()`
* :php:`getCompressCss()`
* :php:`disableConcatenateJavascript()`
* :php:`enableConcatenateJavascript()`
* :php:`getConcatenateJavascript()`
* :php:`disableCompressJavascript()`
* :php:`enableCompressJavascript()`
* :php:`getCompressJavascript()`
The following global configuration registry points have been removed:
* :php:`$GLOBALS['TYPO3_CONF_VARS']['FE']['cssConcatenateHandler']`
* :php:`$GLOBALS['TYPO3_CONF_VARS']['FE']['cssCompressHandler']`
* :php:`$GLOBALS['TYPO3_CONF_VARS']['FE']['jsConcatenateHandler']`
* :php:`$GLOBALS['TYPO3_CONF_VARS']['FE']['jsCompressHandler']`
The following hook has been removed:
* :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['minifyJavaScript']`
The following methods of :php-short:`\TYPO3\CMS\Core\Page\PageRenderer` changed
their signature. The noted arguments are now unused:
* :php:`addJsInlineCode()`: third argument unused
* :php:`addCssInlineBlock()`: third argument unused
* :php:`addJsFile()`: third and sixth argument unused
* :php:`addJsFooterInlineCode()`: third argument unused
* :php:`addJsFooterFile()`: third and sixth argument unused
* :php:`addJsLibrary()`: fourth and seventh argument unused
* :php:`addJsFooterLibrary()`: fourth and seventh argument unused
* :php:`addCssFile()`: fifth and eighth argument unused
* :php:`addCssLibrary()`: fifth and eighth argument unused
Additionally, registered hooks for:
* :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-preProcess']`
* :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postTransform']`
* :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postProcess']`
no longer receive the array keys :php:`compress` or
:php:`excludeFromConcatenation` inside the following data array keys:
* :php:`jsFiles`
* :php:`jsInline`
* :php:`jsLibs`
* :php:`cssFiles`
* :php:`cssInline`
* :php:`cssLibs`
Impact
======
Calling any of the removed methods listed above will raise PHP fatal errors.
Registrations for removed hooks are no longer executed. Submitting ignored
arguments has no effect anymore, and hook consumers receive slightly different
data from the TYPO3 Core due to removed TypoScript configuration values.
Affected installations
======================
Instances with extensions dealing with low level asset manipulation may be
affected. The extension scanner will find affected extensions when they call
removed methods or hooks.
Migration
=========
There is no direct one-to-one migration in this case.
In general, extensions must no longer expect the existence of code related to
the TypoScript configuration options :typoscript:`config.compressCss`,
:typoscript:`config.compressJs`, :typoscript:`config.concatenateCss`,
:typoscript:`config.concatenateJs`, and the :typoscript:`resource` properties
:typoscript:`disableCompression` and :typoscript:`excludeFromConcatenation`.
The removed hooks and "handlers" can be turned into listeners of:
* :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-preProcess']`
* :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postTransform']`
* :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postProcess']`
depending on their needs.
Existing hook registrations of these three should check whether the
implementations access the array keys :php:`compress` and
:php:`excludeFromConcatenation` and avoid doing so. If required, affected code
may need to determine TypoScript options from the :php:`$GLOBALS['TYPO3_REQUEST']`
request attribute :php:`frontend.typoscript` directly.
Another alternative is to avoid hook usage altogether by turning the
implementations into PSR-15 middlewares instead.
.. index:: PHP-API, PartiallyScanned, ext:core
@@ -0,0 +1,68 @@
.. include:: /Includes.rst.txt
.. _breaking-108084-1763033071:
==============================================================
Breaking: #108084 - Allow rootless paths in URI implementation
==============================================================
See :issue:`108084`
Description
===========
Previously, the TYPO3 implementation of :php-short:`\Psr\Http\Message\UriInterface`
always prefixed rootless paths (paths without a preceding slash) with a slash.
With this normalization in place, it was impossible to represent rootless
paths. This has now changed so that a slash is only prepended to the path
when an authority (host name) is present.
Example
-------
Input: `rootless/path/`
.. code-block:: php
:caption: Examples with different URIs
use TYPO3\CMS\Core\Http\Uri;
$uri = new Uri('rootless/path/');
$uriAsString = (string)$uri;
// before: /rootless/path/
// after: rootless/path/
// Same behavior with authority
$uri = (new Uri('https://example.com'))->withPath('rootless/path/');
$uriAsString = (string)$uri;
// before: https://example.com/rootless/path/
// after: https://example.com/rootless/path/
// Colon in first path segment
$uri = new Uri('rootless:path/to/resource');
$uriAsString = (string)$uri;
// before: /rootless:path/to/resource/
// after: ./rootless:path/to/resource/
Impact
======
Regarding top level TYPO3 API and functionality, nothing has changed. Required
TYPO3 code has been adapted.
Third party code that uses the :php-short:`\TYPO3\CMS\Core\Http\Uri` class
directly will get different results when representing rootless paths without
authority. Code that relied on the normalization done by TYPO3 before is
likely to break.
Since TYPO3 is always dealing with absolute paths, due to URL rewriting in the
backend and the frontend, it is unlikely that much third party code relies on
relative paths, so the impact is expected to be low.
Affected installations
======================
Third party code that is using the :php-short:`\TYPO3\CMS\Core\Http\Uri` class
directly and that is representing rootless paths without authority.
.. index:: PHP-API, NotScanned, ext:core
@@ -0,0 +1,43 @@
.. include:: /Includes.rst.txt
.. _breaking-108093-1763042697:
=================================================================================
Breaking: #108093 - Add respectSubmittedDataValue argument in password ViewHelper
=================================================================================
See :issue:`108093`
Description
===========
The :fluid:`<f:form.password>` ViewHelper now provides the argument
:php:`respectSubmittedDataValue`, which allows configuration of whether a
submitted field value will be put into the HTML response of the form on
validation errors after submission. The default value of the new argument is
set to :php:`false`, resulting in a submitted field value being cleared on
validation errors of the form.
Impact
======
A submitted password will not remain as the value for the password field if
form validation fails.
Affected installations
======================
TYPO3 instances using the :fluid:`<f:form.password>` ViewHelper.
Migration
=========
If the submitted field value of the :php:`f:form.password` ViewHelper must
remain on validation errors of the form, users must adapt the password
ViewHelper usage as shown below:
.. code-block:: php
<f:form.password name="myPassword" respectSubmittedDataValue="1" />
.. index:: Fluid, FullyScanned, ext:fluid
@@ -0,0 +1,78 @@
.. include:: /Includes.rst.txt
.. _breaking-108097-1763046431:
===============================================
Breaking: #108097 - MailMessage->send() removed
===============================================
See :issue:`108097`
Description
===========
Class :php:`\TYPO3\CMS\Core\Mail\MailMessage` is a data object that
should not contain service methods like :php:`send()`. The following methods
have been removed from this class:
* :php:`send()`
* :php:`isSent()`
Impact
======
Using the removed methods on instances of this class will raise fatal PHP
errors.
Affected installations
======================
Instances that create :php-short:`\TYPO3\CMS\Core\Mail\MailMessage` objects
and call :php:`send()` or :php:`isSent()` are affected. The extension scanner
is not configured to find affected code since the method names are too generic.
Migration
=========
The service (usually a controller class) that sends emails should be
reconfigured to get an instance of :php-short:`\TYPO3\CMS\Core\Mail\MailerInterface`
injected and should use that service to call :php:`send()`.
Example before:
.. code-block:: php
use TYPO3\CMS\Core\Mail\MailMessage;
final readonly class MyController
{
public function sendMail()
{
$email = new MailMessage();
$email->subject('Some subject');
$email->send();
}
}
Example after:
.. code-block:: php
use TYPO3\CMS\Core\Mail\MailMessage;
use TYPO3\CMS\Core\Mail\MailerInterface;
final readonly class MyController
{
public function __construct(
private MailerInterface $mailer
) {}
public function sendMail()
{
$email = new MailMessage();
$email->subject('Some subject');
$this->mailer->send($email);
}
}
.. index:: PHP-API, NotScanned, ext:core
@@ -0,0 +1,86 @@
.. include:: /Includes.rst.txt
.. _breaking-108113-1763081388:
====================================================================================
Breaking: #108113 - Globals _GET and _POST not reset to current Request data anymore
====================================================================================
See :issue:`108113`
Description
===========
The frontend and backend application chain roughly splits like this:
1. Bootstrap
2. Create Request object from globals
3. Start application
4. Run middleware chain
5. Run RequestHandler to create a Response by calling controllers (backend) or
:php-short:`\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer`
(frontend)
There was old compatibility code in :php-short:`\TYPO3\CMS\Core\Http\RequestHandler`
that reset the PHP global variables :php:`_GET`, :php:`_POST`,
:php:`HTTP_GET_VARS` and :php:`HTTP_POST_VARS` to values that may have been
written to their Request object counterparts by middlewares.
This backwards compatibility layer has been removed.
Additionally, in frontend rendering, the global variable
:php:`$GLOBALS['TYPO3_REQUEST']` is no longer populated within the
:php-short:`\TYPO3\CMS\Frontend\Middleware\PrepareTypoScriptFrontendRendering`
middleware. It is now set later in :php-short:`\TYPO3\CMS\Core\Http\RequestHandler`.
:php:`$GLOBALS['TYPO3_REQUEST']` itself is another compatibility layer that the
TYPO3 Core aims to phase out over time.
Impact
======
The impact is twofold:
* Some TYPO3 Core middlewares manipulate the Request object's "GET"
parameter list (:php:`$request->getQueryParams()`) to, for example,
resolve the frontend slug into the page uid. This is itself a
backwards compatibility layer. Frontend-related code can no longer
expect these manipulated variables to exist in the globals
:php:`_GET`, :php:`_POST`, :php:`HTTP_GET_VARS` and
:php:`HTTP_POST_VARS`.
* Middlewares that are executed *after*
:php-short:`\TYPO3\CMS\Frontend\Middleware\PrepareTypoScriptFrontendRendering`
(middleware key :code:`typo3/cms-frontend/prepare-tsfe-rendering`)
can no longer rely on :php:`$GLOBALS['TYPO3_REQUEST']` being set.
Affected installations
======================
Instances running code that relies on the removed compatibility layers
may fail or lead to unexpected results.
Migration
=========
Middlewares receive the Request object directly and should use it instead
of fetching it from :php:`$GLOBALS['TYPO3_REQUEST']`. Services triggered by
middlewares that rely on the Request should have it passed in explicitly.
One example frequently used in middlewares is
:php-short:`\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer`:
.. code-block:: php
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
$cor = GeneralUtility::makeInstance(ContentObjectRenderer::class);
$cor->setRequest($request);
$result = $cor->doSomething();
Code should in general never rely on the globals :php:`_GET`,
:php:`_POST`, :php:`HTTP_GET_VARS` and :php:`HTTP_POST_VARS`. Request-related
state should always be fetched from the Request object. Note that the helper
method :php:`GeneralUtility::getIndpEnv()` will also be phased out once the
TYPO3 Core has removed its last remaining usages.
.. index:: PHP-API, NotScanned, ext:core
@@ -0,0 +1,54 @@
.. include:: /Includes.rst.txt
.. _breaking-108114-1763085569:
==================================================================
Breaking: #108114 - Global frontend content link prefixing removed
==================================================================
See :issue:`108114`
Description
===========
The frontend rendering contained logic that searched for links to resources
within the generated Response content to globally replace them with the
configured URL prefix (TypoScript :typoscript:`config.absRefPrefix`).
This solution has always been brittle and has now been obsoleted with the
introduction of the :ref:`System Resource API <feature-107537-1759136314>`.
The global search and replace code has been removed, which also obsoletes
setting :php:`$GLOBALS['TYPO3_CONF_VARS']['FE']['additionalAbsRefPrefixDirectories']`.
Impact
======
Generated content can no longer expect links to resources to be globally
"fixed". They must create the final URL themselves.
The obsolete
:php:`$GLOBALS['TYPO3_CONF_VARS']['FE']['additionalAbsRefPrefixDirectories']`
will be automatically removed from :file:`settings.php` after upgrading to
TYPO3 v14 and accessing the install tool.
Affected installations
======================
The System Resource API is integrated into TYPO3 in a way that extensions
usually create proper links automatically as long as the provided Core API is
used.
Instances with extensions that hard code link generation may be affected.
Migration
=========
Instances should check the rendered frontend for broken links after upgrading
to TYPO3 v14 and update hard coded link generation to use proper API calls,
for example based on the various URL, URI and asset-related Fluid ViewHelpers.
This change depends heavily on the specific extension code. There is no general
advice that covers all possible cases for extension developers.
.. index:: Frontend, PHP-API, NotScanned, ext:frontend
@@ -0,0 +1,42 @@
.. include:: /Includes.rst.txt
.. _breaking-108148-1763289953:
=======================================================================
Breaking: #108148 - CDATA sections in Fluid templates no longer removed
=======================================================================
See :issue:`108148`
Description
===========
Previous versions of Fluid and TYPO3 removed code wrapped in `<![CDATA[ ]]>`
from template files altogether. This meant that it was possible to use CDATA
to comment out template code. This is no longer possible, since CDATA
sections are now interpreted by Fluid in a different way; see
`Feature: #108148 - Alternative Fluid Syntax for CDATA Sections <https://docs.typo3.org/permalink/changelog:feature-108148-1763288461>`_.
Impact
======
`<![CDATA[ ]]>` can no longer be used to comment out code in Fluid template
files.
Affected installations
======================
Installations that contain Fluid templates using `<![CDATA[ ]]>` to comment
out code are affected. A deprecation has been written to the deprecation log
since TYPO3 13.4.21 if this construct is encountered in a Fluid template
during rendering.
Migration
=========
To comment out code in Fluid templates, the
`Comment ViewHelper <f:comment> <https://docs.typo3.org/permalink/t3viewhelper:typo3fluid-fluid-comment>`_
should be used. Since TYPO3 v13, potential Fluid syntax errors are ignored by
this ViewHelper, which allows commenting out invalid Fluid syntax safely.
.. index:: Fluid, NotScanned, ext:fluid
@@ -0,0 +1,45 @@
.. include:: /Includes.rst.txt
.. _breaking-108148-1766234207:
=============================
Breaking: #108148 - Fluid 5.0
=============================
See :issue:`108148`
Description
===========
Fluid 5.0 removes pre-announced deprecations that were introduced with Fluid 2.x
and 4.x.
Impact
======
Installations that use methods that were deprecated with Fluid 2.x or Fluid 4.x
will now encounter PHP errors.
Affected installations
======================
Breaking changes are listed in the Fluid documentation:
`Changelog 5.x <https://docs.typo3.org/permalink/fluid:changelog-5-x>`_
Migration
=========
Noteworthy deprecations and mitigations have already been communicated with
TYPO3 changelog entries in 13.x:
* `Deprecation: #104223 - Fluid standalone methods <https://docs.typo3.org/permalink/changelog:deprecation-104223-1721383576>`_
* `Deprecation: #104463 - Fluid standalone overrideArgument <https://docs.typo3.org/permalink/changelog:deprecation-104463-1721754926>`_
* `Deprecation: #104789 - renderStatic() for Fluid ViewHelpers <https://docs.typo3.org/permalink/changelog:deprecation-104789-1725195584>`_
Deprecation items in Fluid changelogs might contain additional hints:
* `Fluid Changelog 2.x <https://docs.typo3.org/permalink/fluid:changelog-2-x>`_
* `Fluid Changelog 4.x <https://docs.typo3.org/permalink/fluid:changelog-4-x>`_
.. index:: Fluid, PartiallyScanned, ext:fluid
@@ -0,0 +1,105 @@
.. include:: /Includes.rst.txt
.. _breaking-108148-1763288414:
========================================================================
Breaking: #108148 - Disallow Fluid variable names with underscore prefix
========================================================================
See :issue:`108148`
Description
===========
With Fluid 5, it is no longer possible to define custom template variables
that start with an underscore (`_`). These variable names are reserved for
future internal use by Fluid itself, similarly to the already existing
`{_all}`.
Impact
======
This change affects ViewHelpers that define new variables, such as:
* `<f:variable> <https://docs.typo3.org/permalink/t3viewhelper:typo3fluid-fluid-variable>`_
* `<f:for> <https://docs.typo3.org/permalink/t3viewhelper:typo3fluid-fluid-for>`_
* `<f:render> <https://docs.typo3.org/permalink/t3viewhelper:typo3-fluid-render>`_
It also affects Fluid's PHP APIs, namely :php:`$view->assign()` and
:php:`$view->assignMultiple()`.
Affected installations
======================
Installations with Fluid templates that use custom variable names starting
with an underscore (`_`) will encounter exceptions when such a template is
rendered. A deprecation has been written to the deprecation log since
TYPO3 13.4.21 if this is encountered in a Fluid template during rendering.
For template files already using the new `*.fluid.*` file extension, the built-in
template analyse command will discover affected template files:
.. code-block:: sh
vendor/bin/typo3 fluid:analyse
For each affected template, the command will output an error like this:
.. code-block::
[ERROR] packages/myext/Resources/Private/Templates/Test.fluid.html: Variable identifiers cannot start with a "_": _myvariable
Migration
=========
The following examples no longer work with Fluid 5:
.. code-block:: html
<f:variable name="_temp" value="a temporary value" />
{_temp}
.. code-block:: html
<f:for each="{myArray}" as="_item">
{_item}
</f:for>
.. code-block:: html
<f:render partial="Footer" arguments="{_data: myData}" />
.. code-block:: php
$view->assign('_data', $myData);
$view->assignMultiple([
'_data' => $myData,
]);
All examples lead to the following exception:
.. code-block::
#1756622558 TYPO3Fluid\Fluid\Core\Variables\InvalidVariableIdentifierException
Variable identifiers cannot start with a "_": _myVariable
In all cases, the variable name must be changed to no longer start with an
underscore (`_`).
Note that this only affects variable names, not property names in objects or
array keys that are accessed within a Fluid template. The following examples
are **not** affected by this change:
.. code-block:: html
{myArray._myKey}
{myObject._myProperty}
Also note that the existing `{_all}` (and any further internal variables added
by Fluid) are **not affected**. This code will continue to work:
.. code-block:: html
<f:render partial="Footer" arguments="{_all}"/>
.. index:: Fluid, NotScanned, ext:fluid
@@ -0,0 +1,149 @@
.. include:: /Includes.rst.txt
.. _breaking-108148-1763288349:
=====================================================
Breaking: #108148 - Strict Types in Fluid ViewHelpers
=====================================================
See :issue:`108148`
Description
===========
With Fluid 5, various changes have been made to use stricter types in the
context of ViewHelpers. This has consequences in three areas:
* Validation of arguments passed to ViewHelpers
(see `#1194 on GitHub <https://github.com/TYPO3/Fluid/pull/1194>`_)
* Passing `null` values to ViewHelpers that generate a HTML tag, also
known as tag-based ViewHelpers
(see `#1233 on GitHub <https://github.com/TYPO3/Fluid/pull/1233>`_)
* Required type declarations for custom ViewHelper implementations
(see `#1219 on GitHub <https://github.com/TYPO3/Fluid/pull/1219>`_)
Impact
======
ViewHelper argument validation
------------------------------
Fluid ViewHelpers now use stricter validation for their arguments by default.
The previous argument validation had numerous blind spots, which meant that
ViewHelper implementations couldn't really rely on the type requirements
specified in the ViewHelper's API. The new implementation performs a stricter
validation, which means that Fluid might reject arguments passed to ViewHelpers
that were previously considered *valid* (but which the ViewHelper in question
usually didn't know how to handle). The new implementation does however deal
with simple type conversions automatically, so that a ViewHelper that requires
a :php:`string` still can receive an :php:`int` as input.
For integrators, this change might reject certain ViewHelper arguments that
were previously *valid*, but not covered by the ViewHelper's specified API.
For developers of custom ViewHelpers, this change allows to get rid of custom
validation logic that was previously necessary due to Fluid's spotty
validation.
Note that the
`Argument ViewHelper <f:argument> <https://docs.typo3.org/permalink/t3viewhelper:typo3fluid-fluid-argument>`_,
which can be used to define an API for a template, is **not** affected by this
change, as it already used the improved validation from the beginning.
Passing :php:`null` to tag-based ViewHelpers
--------------------------------------------
Previously, Fluid's :php:`TagBuilder` class, which is used to create HTML tags
in tag-based ViewHelpers, treated :php:`null` values as empty strings, leading
to an HTML tag with an empty HTML attribute. With Fluid 5, :php:`null` values lead
to the HTML attribute being omitted from the resulting HTML tag.
Example:
.. code-block:: html
<f:form.textfield name="myTextBox" placeholder="{variableThatMightBeNull}" />
If the variable is :php:`null` (the PHP value), Fluid 4 and below generated
the following output:
.. code-block:: html
<input type="text" name="myTextBox" placeholder="" />
Fluid 5 omits the :html:`placeholder=""`:
.. code-block:: html
<input type="text" name="myTextBox" />
In most cases, the impact of this change is non-existent. However, there are
some edge cases where this change is relevant. In TYPO3 Core, the :html:`<f:image>`
ViewHelper needed to be adjusted to always render the :html:`alt` attribute,
even if its internal value is :php:`null`, to match the previous output and
to produce valid HTML code.
TYPO3 Core ships with the following tag-based ViewHelpers:
* :html:`<f:media>` and :html:`<f:image>`
* :html:`<f:asset.css>` and :html:`<f:asset.script>`
* :html:`<f:form>` and :html:`<f:form.*>`
* :html:`<f:link.*>`, except for `<f:link.typolink>`, which uses TypoScript internally
* :html:`<f:be.link>`
* :html:`<be:link.*>`
* :html:`<be:thumbnail>`
Type declarations in ViewHelper classes
---------------------------------------
Fluid's `ViewHelperInterface` now requires proper return types for all ViewHelper
methods. Thus, custom ViewHelper implementations need to be adjusted accordingly.
This is backwards-compatible to previous TYPO3 versions.
Affected installations
======================
All installations need to verify that
* ViewHelpers aren't called with invalid argument types
* :php:`null` values passed to tag-based ViewHelpers don't lead to unexpected
HTML output
* Custom ViewHelper implementations specify proper return types
Migration
=========
Custom ViewHelper implementations need to make sure that they declare
proper return types in the ViewHelper class to conform to Fluid 5's
interface changes, for example:
* `initializeArguments()` must specify `void` as return type
* `render()` should specify a return type other than `void`. Even though a
specific type is recommended, it is not required, and `mixed` can be used as well.
Note that properties in ViewHelper classes are **not** affected.
The following example doesn't need to be adjusted, no types can/should
be specified for these properties:
.. code-block:: php
class MyViewHelper extends AbstractViewHelper
{
protected $escapeOutput = false;
protected $escapeChildren = false;
}
Unfortunately, the other changes concern runtime characteristics of
Fluid templates, as they depend on the concrete values of variables that
are passed to a template. Thus, it is not possible to scan for affected
templates automatically.
However, the majority of issues these changes in Fluid might uncover in
existing projects would have already been classified as a bug
(in the template or extension code) before this Fluid change, such as
passing an array to a ViewHelper that expects a string.
.. index:: Fluid, NotScanned, ext:fluid
@@ -0,0 +1,66 @@
.. include:: /Includes.rst.txt
.. _breaking-108277-1763903595:
=========================================================================
Breaking: #108277 - Remove superfluous CacheHashCalculator public methods
=========================================================================
See :issue:`108277`
Description
===========
The following superfluous public methods have been removed:
* :php:`\TYPO3\CMS\Frontend\Page\CacheHashCalculator::setConfiguration()`
* :php:`\TYPO3\CMS\Frontend\Page\CacheHashConfiguration::with()`
Impact
======
Calling the removed methods will result in a fatal PHP error.
Both methods were only used internally for testing purposes and were not part
of the public API contract.
Affected installations
======================
TYPO3 installations that used these methods directly in custom code are
affected. However, this is highly unlikely as they were intended for internal
testing only.
Migration
=========
Instead of modifying configuration after instantiation using the removed
:php:`setConfiguration()` method, merge configuration arrays before creating
the :php:`CacheHashConfiguration` instance, then pass it to the
:php:`CacheHashCalculator` constructor.
Example:
.. code-block:: php
// Before (removed approach):
$subject = new CacheHashCalculator(
new CacheHashConfiguration($baseConfiguration),
$hashService
);
$subject->setConfiguration([
'cachedParametersWhiteList' => ['whitep1', 'whitep2'],
]);
// After (correct approach):
$configuration = new CacheHashConfiguration(
array_merge($baseConfiguration, [
'cachedParametersWhiteList' => ['whitep1', 'whitep2'],
])
);
$subject = new CacheHashCalculator($configuration, $hashService);
.. index:: Frontend, FullyScanned, ext:core
@@ -0,0 +1,71 @@
.. include:: /Includes.rst.txt
.. _breaking-108304-1764058005:
===============================================================
Breaking: #108304 - Populate extension title from composer.json
===============================================================
See :issue:`108304`
Description
===========
To avoid reading the legacy `ext_emconf.php` file even in
Composer mode, the extension title is now optionally pulled
from the composer.json description. If the character sequence
` - ` (space, dash, space) is present in description field
in composer.json, then everything before this sequence
is used as title of the extension and the second part
is used as extension description. Note that only the first
occurrence of this sequence is evaluated, so it remains
possible to have this inside the extension description if required.
Impact
======
Extensions not having their title incorporated in the
composer.json description field, will be shown with the
full description in extension manager and from command
line with `typo3 extension:list` command.
Affected installations
======================
Installations having custom extensions, where the title
is not part of the description in composer.json
Migration
=========
Put the desired extension title into the composer.json description field
and separate it from the description with ` - ` (space, dash, space),
or use the extension manager "Composer Support of Extensions" to get
a suggestion for updating composer.json files accordingly.
All TYPO3 core extensions have set their description in composer.json
accordingly already.
Example of description with title in composer.json:
.. code-block:: php
:caption: ext_emconf.php
<?php
$EM_CONF[$_EXTKEY] = [
'title' => 'TYPO3 CMS Backend User',
'description' => 'TYPO3 backend module System>Backend Users for managing backend users and groups.',
// ...
];
.. code-block:: json
:caption: composer.json
{
"name": "typo3/cms-beuser",
"type": "typo3-cms-framework",
"description": "TYPO3 CMS Backend User - TYPO3 backend module System>Backend Users for managing backend users and groups.",
}
.. index:: PHP-API, NotScanned, ext:core
@@ -0,0 +1,56 @@
.. include:: /Includes.rst.txt
.. _breaking-108310-1732545123:
=========================================================
Breaking: #108310 - Require composer.json in classic mode
=========================================================
See :issue:`108310`
Description
===========
Extension detection in classic mode now requires a valid :file:`composer.json`
file instead of :file:`ext_emconf.php`. The :file:`composer.json` file must
include :json:`"type": "typo3-cms-*"` and the extension key in
:json:`extra.typo3/cms.extension-key`.
Impact
======
Extensions without a valid :file:`composer.json` are no longer detected
and loaded in classic mode installations.
Affected installations
======================
All classic mode installations must verify that every extension contains
a :file:`composer.json` with:
* :json:`"type"` starting with :json:`"typo3-cms-"`
* :json:`"extra.typo3/cms.extension-key"` containing the extension key
Composer-based installations are not affected.
Migration
=========
Extension authors must ensure their extensions include a valid
:file:`composer.json`. TER extensions have required this since 2021.
Example :file:`composer.json`:
.. code-block:: json
{
"name": "vendor/extension-name",
"type": "typo3-cms-extension",
"extra": {
"typo3/cms": {
"extension-key": "extension_name"
}
}
}
.. index:: PHP-API, NotScanned, ext:core
@@ -0,0 +1,88 @@
.. include:: /Includes.rst.txt
.. _breaking-17406-1762953718:
================================================================
Breaking: #17406 - Field "url" in table "pages" has been removed
================================================================
See :issue:`17406`
Description
===========
The former page type "External link" has been renamed to "Link" and now fully
supports all typolink capabilities. It now uses the field :sql:`link`.
Since the field `url` was only used by this former page type, it has been
removed.
Impact
======
Custom code that expects the field `url` to exist in the table :sql:`pages`
will fail as the field is not found anymore.
Affected installations
======================
* TYPO3 projects that used the former page type *External URL* to link to
resources other than true external URLs, for example sections such as `#abc`.
* TYPO3 projects with custom code that expects the field `url` to exist
in the table :sql:`pages`.
Migration
=========
The upgrade wizard **"Migrate links of pages of type link"** automatically migrates
pages of the former type *External URL* to the new page type *Link*.
It migrates all links that resolve to external URLs. If your project used the
*External URL* field for other purposes — for example, to link sections such
as `#abc` — you must migrate those links manually.
If your project contains custom code that expects the field :sql:`url` to exist
in the table :sql:`pages`, you can reintroduce this field via a TCA override,
for example:
.. code-block::
:caption: EXT:my_extension/Configuration/TCA/Overrides/pages.php
<?php
defined('TYPO3') || die('Access restricted.');
$GLOBALS['TCA']['pages']['columns']['url'] = [
'label' => 'External URL',
'config' => [
'type' => 'input',
'size' => 50,
'max' => 255,
'required' => true,
'eval' => 'trim',
'softref' => 'url',
'behaviour' => [
'allowLanguageSynchronization' => true,
],
],
];
// Adding column to a existing or new palette and configure showitem,
// for a specific doktype the field is still required, for example:
$GLOBALS['TCA']['pages']['palettes]['custom_url'] = [
'showitem' => 'url',
];
$GLOBALS['TCA']['pages']['types'][$customDokTypeValue] = [
'showitem' => [
--div--;core.form.tabs:general,
doktype,
--palette--;;title,
--palette--;;custom_url,
],
];
Adding it back at least ensures that the database field is not renamed and
dropped by the Database Analyzer. In case TCA is not required while keeping
the database field it could be added to a extension `ext_tables.sql` file.
.. index:: TCA, NotScanned, ext:core
@@ -0,0 +1,51 @@
.. include:: /Includes.rst.txt
.. _breaking-33747-1737642868:
===================================================================
Breaking: #33747 - Remove non-implemented sortable Collection logic
===================================================================
See :issue:`33747`
Description
===========
The :php:`\TYPO3\CMS\Core\Collection\SortableCollectionInterface` has been
removed from the TYPO3 Core.
This interface was never properly implemented and served no purpose in the
codebase. It defined methods for sorting collections via callback functions
and moving items within collections, but no concrete implementations existed.
The interface defined the following methods:
- :php:`usort($callbackFunction)` for sorting a collection via a given callback function
- :php:`moveItemAt($currentPosition, $newPosition = 0)` for moving items within the collection
Impact
======
Any code that implements or references :php-short:`\TYPO3\CMS\Core\Collection\SortableCollectionInterface`
will trigger a PHP fatal error.
Since this interface was never implemented in the TYPO3 Core and had no real-world usage,
the impact should be minimal for most installations.
Affected installations
======================
Installations with custom extensions that implement or reference the
:php-short:`\TYPO3\CMS\Core\Collection\SortableCollectionInterface` are affected.
Migration
=========
Remove any references to :php-short:`\TYPO3\CMS\Core\Collection\SortableCollectionInterface`
from your code.
If you need sortable collection functionality, implement your own sorting logic
directly in your collection classes, or use PHP's built-in array sorting functions
such as :php:`usort()`, :php:`uasort()`, or :php:`uksort()`.
.. index:: PHP-API, FullyScanned
@@ -0,0 +1,38 @@
.. include:: /Includes.rst.txt
.. _breaking-68303-1743324411:
==================================================================
Breaking: #68303 - Make tt_content imagewidth/imageheight nullable
==================================================================
See :issue:`68303`
Description
===========
The default values of the fields `imagewidth` and `imageheight` in the
`tt_content` table are now set to `null`.
This change removes the awkward UI behavior where the fields were previously
set to `0` when no value was entered.
Impact
======
Custom queries might fail if they expect the fields to be `0` instead of `null`.
Affected installations
======================
TYPO3 installations that rely on the `imagewidth` and `imageheight` fields of the
`tt_content` table always being integers are affected.
Migration
=========
Use the "Media fields zero to null" upgrade wizard to update existing field values.
Also, modify your queries to handle `null` values instead of `0`.
.. index:: Backend, Frontend, NotScanned, ext:frontend
@@ -0,0 +1,185 @@
.. include:: /Includes.rst.txt
.. _breaking-92434-1761644184:
==================================================================
Breaking: #92434 - Use Record API in Page Module Preview Rendering
==================================================================
See :issue:`92434`
Description
===========
The Page Module preview rendering has been refactored to use the Record API
internally instead of accessing raw database arrays. This affects both custom
preview renderers that extend :php-short:`\TYPO3\CMS\Backend\Preview\StandardContentPreviewRenderer` and
Fluid-based preview templates.
The method signature has changed for
:php:`\TYPO3\CMS\Backend\Preview\StandardContentPreviewRenderer`:
- :php:`StandardContentPreviewRenderer->linkEditContent()` now expects a
:php-short:`\TYPO3\CMS\Core\Domain\RecordInterface` object as the second :php:`$record` parameter
instead of an array
The :php:`\TYPO3\CMS\Backend\View\Event\PageContentPreviewRenderingEvent` has
also been updated:
- :php:`PageContentPreviewRenderingEvent->getRecord()` now returns a
:php-short:`\TYPO3\CMS\Core\Domain\RecordInterface` object instead of an array
- :php:`PageContentPreviewRenderingEvent->setRecord()` now expects a
:php-short:`\TYPO3\CMS\Core\Domain\RecordInterface` object instead of an array
Additionally, the `@internal` class
:php:`\TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem` has been
updated to work with Record objects:
* The constructor of :php-short:`\TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem`
now requires a :php-short:`\TYPO3\CMS\Core\Domain\RecordInterface` object as
the third :php:`$record` parameter instead of an array
* :php:`GridColumnItem->getRecord()` now returns a :php-short:`\TYPO3\CMS\Core\Domain\RecordInterface` object
instead of an array
* :php:`GridColumnItem->setRecord()` now expects a :php-short:`\TYPO3\CMS\Core\Domain\RecordInterface` object
instead of an array
* A new method :php:`GridColumnItem->getRow()` has been added to access the raw
database array if needed
For Fluid-based content element previews, the template variables have changed.
Previously, all record fields were passed as individual variables to the Fluid
template. Now, only a single :fluid:`{record}` variable is passed, which is a
:php-short:`\TYPO3\CMS\Core\Domain\RecordInterface` object providing access to all record data through
the Record API.
Using the :fluid:`{pi_flexform_transformed}` variable in Fluid-based content
element previews no longer works. The resolved flex form can be directly
accessed on the :php-short:`\TYPO3\CMS\Core\Domain\RecordInterface` object, for example via
:fluid:`{record.pi_flexform}`. The value is a :php:`FlexFormFieldValues`
object, which properly groups the fields by their sheets.
Impact
======
Extensions that extend :php-short:`\TYPO3\CMS\Backend\Preview\StandardContentPreviewRenderer` and override the
:php:`linkEditContent()` method will need to update their method signature.
Extensions that access :php:`GridColumnItem->getRecord()` expecting an array will
need to update their code to work with :php-short:`\TYPO3\CMS\Core\Domain\RecordInterface` objects.
Extensions using event listeners for :php:`PageContentPreviewRenderingEvent` that
access the record via :php:`getRecord()` expecting an array will need to update
their code to work with :php-short:`\TYPO3\CMS\Core\Domain\RecordInterface` objects.
Custom Fluid templates for content element preview rendering must be updated to
use the :php:`{record}` variable instead of accessing individual field variables.
Affected installations
======================
All installations with extensions that:
* Extend :php-short:`\TYPO3\CMS\Backend\Preview\StandardContentPreviewRenderer` and call or override the
:php:`linkEditContent()` method
* Instantiate :php-short:`\TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem` or call :php:`GridColumnItem->getRecord()` /
:php:`GridColumnItem->setRecord()`
* Register event listeners for :php:`PageContentPreviewRenderingEvent`
* Use custom Fluid templates for content element preview rendering via PageTSconfig
:typoscript:`mod.web_layout.tt_content.preview.[recordType]`
Migration
=========
For custom preview renderers extending :php-short:`\TYPO3\CMS\Backend\Preview\StandardContentPreviewRenderer`:
Update the method signature of :php:`linkEditContent()` to accept a
:php-short:`\TYPO3\CMS\Core\Domain\RecordInterface` object:
.. code-block:: php
:caption: Before (TYPO3 v13 and lower)
protected function linkEditContent(string $linkText, array $row, string $table = 'tt_content'): string
{
$uid = (int)$row['uid'];
$pid = (int)$row['pid'];
// ...
}
.. code-block:: php
:caption: After (TYPO3 v14+)
use TYPO3\CMS\Core\Domain\RecordInterface;
protected function linkEditContent(string $linkText, RecordInterface $record): string
{
$uid = $record->getUid();
$pid = $record->getPid();
$table = $record->getMainType();
// ...
}
For code working with :php-short:`\TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem`:
.. code-block:: php
:caption: Before (TYPO3 v13 and lower)
$row = $columnItem->getRecord();
$uid = (int)$row['uid'];
$title = $row['header'];
.. code-block:: php
:caption: After (TYPO3 v14+)
use TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem;
use TYPO3\CMS\Core\Domain\RecordInterface;
$record = $columnItem->getRecord();
$uid = $record->getUid();
$title = $record->has('header') ? $record->get('header') : '';
// Or if raw array access is needed:
$row = $columnItem->getRow();
$uid = (int)$row['uid'];
For custom Fluid templates used for content element preview rendering:
.. code-block:: html
:caption: Before (TYPO3 v13 and lower)
<h2>{header}</h2>
<p>{bodytext}</p>
<f:if condition="{image}">
<p>Image UID: {image}</p>
</f:if>
.. code-block:: html
:caption: After (TYPO3 v14+)
<h2>{record.header}</h2>
<p>{record.bodytext}</p>
<f:if condition="{record.image}">
<p>Image UID: {record.image.uid}</p>
</f:if>
For flex form value rendering, there are two options:
.. code-block:: html
:caption: Before (TYPO3 v13 and lower)
<h2>{header}</h2>
<p>{bodytext}</p>
<small>{pi_flexform_transformed.settings.welcome_header}</small>
<f:if condition="{image}">
<p>Image UID: {image}</p>
</f:if>
.. code-block:: html
:caption: After (TYPO3 v14+)
<f:variable name="path" value="s_messages/settings" />
<small>{record.pi_flexform.{path}.welcome_header}</small>
<!-- or -->
<small>{record.pi_flexform.sheets.s_messages.settings.welcome_header}</small>
.. index:: Backend, PHP-API, Fluid, NotScanned, ext:backend
@@ -0,0 +1,38 @@
.. include:: /Includes.rst.txt
.. _breaking-97151-1744183267:
=============================================================
Breaking: #97151 - Remove "Database Relations" backend module
=============================================================
See :issue:`97151`
Description
===========
The backend submodule **Database Relations** within **DB Check** provided
information about potentially broken database relations. However, the
information it displayed was very limited and barely helpful. In addition, the
entire module and its code have not received any meaningful updates in recent
years.
Due to this, the module has been removed.
Impact
======
The module has been removed. Existing links and stored bookmarks will no longer
work.
Affected installations
======================
All TYPO3 installations are affected.
Migration
=========
There is no migration available.
.. index:: Backend, NotScanned, ext:lowlevel
@@ -0,0 +1,68 @@
.. include:: /Includes.rst.txt
.. _breaking-98070-1743452794:
==========================================
Breaking: #98070 - Remove eval method year
==========================================
See :issue:`98070`
Description
===========
The eval method `year` was used to validate the value of a TCA field. Its
implementation was never completed and simply cast the value to an integer.
As there is no clear definition of what a valid year value should be, the
method has been removed without substitution.
Impact
======
The value `year` has been removed from the list of supported `eval` options.
The TCA migration will trigger a deprecation log entry when building the final
TCA.
Affected installations
======================
TYPO3 installations using old extensions that define custom TCA configurations
with this option set are affected.
Migration
=========
Remove the `year` eval setting from your TCA configuration and use a TCA field
type that better suits your needs.
.. code-block:: php
// Use type "number" with an optional range restriction
'variant_a' => [
'label' => 'My year',
'config' => [
'type' => 'number',
'range' => [
'lower' => 1990,
'upper' => 2038,
],
'default' => 0,
],
],
// Use a date field with an optional range restriction
'variant_b' => [
'label' => 'My year',
'config' => [
'type' => 'datetime',
'range' => [
'lower' => gmmktime(0, 0, 0, 1, 1, 1990),
'upper' => gmmktime(23, 59, 59, 12, 31, 2038),
],
'nullable' => true,
],
],
.. index:: Backend, TCA, NotScanned, ext:backend
@@ -0,0 +1,43 @@
.. include:: /Includes.rst.txt
.. _breaking-98239-1758890437:
=======================================================
Breaking: #98239 - Removed "afterBuildingFinished" hook
=======================================================
See :issue:`98239`
Description
===========
The hook :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['afterBuildingFinished']`
has been removed in favor of the more powerful PSR-14 events
:php:`\TYPO3\CMS\Form\Event\BeforeRenderableIsAddedToFormEvent` and
:php:`\TYPO3\CMS\Form\Event\AfterFormIsBuiltEvent`.
Impact
======
Any hook implementation registered under this identifier will no longer be
executed in TYPO3 v14.0 and later.
Affected installations
======================
TYPO3 installations with custom extensions that implement this hook are
affected. The extension scanner reports such usages as a weak match.
Migration
=========
The hook has been removed without a deprecation phase to allow extensions to
remain compatible with both TYPO3 v13 (using the hook) and v14+ (using the new
events). Implementing the PSR-14 events provides the same or greater control
over form rendering.
Use the :ref:`BeforeRenderableIsAddedToFormEvent <feature-107518-1758539757>` or
:ref:`AfterFormIsBuiltEvent <feature-98239-1758890522>` to achieve the same
functionality with the new event-based system.
.. index:: Backend, ext:form, FullyScanned
@@ -0,0 +1,155 @@
.. include:: /Includes.rst.txt
.. _deprecation-106393-1742454612:
========================================================
Deprecation: #106393 - Various methods in BackendUtility
========================================================
See :issue:`106393`
Description
===========
Due to the introduction of the Schema API, several methods of
:php:`\TYPO3\CMS\Backend\Utility\BackendUtility` that retrieve
information from :php:`$GLOBALS['TCA']` have been deprecated:
* :php:`BackendUtility::getCommonSelectFields()`
* :php:`BackendUtility::getItemLabel()`
* :php:`BackendUtility::isTableLocalizable()`
* :php:`BackendUtility::isTableWorkspaceEnabled()`
* :php:`BackendUtility::isRootLevelRestrictionIgnored()`
* :php:`BackendUtility::isWebMountRestrictionIgnored()`
* :php:`BackendUtility::resolveFileReferences()`
Impact
======
Calling any of the mentioned methods now triggers a deprecation-level log
entry and will stop working in TYPO3 v15.0.
The extension scanner reports usages as a **strong** match.
Affected installations
======================
Instances or extensions that directly call these methods are affected.
Migration
=========
The migration strategy is the same for all cases:
use the corresponding Schema API methods directly in your code.
In most cases, you'll need to inject
:php-short:`\TYPO3\CMS\Core\Schema\TcaSchemaFactory` via dependency injection.
getCommonSelectFields
---------------------
No substitution is available. The method was marked as `@internal` already.
If your code depends on this functionality, copy the method into your own
extension.
getItemLabel
------------
.. code-block:: php
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Schema\TcaSchemaCapability;
use TYPO3\CMS\Core\Schema\TcaSchemaFactory;
// Before
return BackendUtility::getItemLabel('pages', 'title');
// After (retrieve an instance of TcaSchemaFactory via dependency
// injection of TYPO3\CMS\Core\Schema\TcaSchemaFactory)
$schema = $this->schemaFactory->has('pages')
? $this->schemaFactory->get('pages')
: null;
return $schema !== null && $schema->hasField('title')
? $schema->getField('title')->getLabel()
: null;
isTableLocalizable
------------------
.. code-block:: php
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Schema\TcaSchemaCapability;
use TYPO3\CMS\Core\Schema\TcaSchemaFactory;
// Before
return BackendUtility::isTableLocalizable('pages');
// After (retrieve an instance of TcaSchemaFactory via dependency
// injection of TYPO3\CMS\Core\Schema\TcaSchemaFactory)
return $this->schemaFactory->has('pages')
&& $this->schemaFactory->get('pages')
->hasCapability(TcaSchemaCapability::Language);
isTableWorkspaceEnabled
-----------------------
.. code-block:: php
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Schema\TcaSchemaCapability;
use TYPO3\CMS\Core\Schema\TcaSchemaFactory;
// Before
return BackendUtility::isTableWorkspaceEnabled('pages');
// After (retrieve an instance of TcaSchemaFactory via dependency
// injection of TYPO3\CMS\Core\Schema\TcaSchemaFactory)
return $this->schemaFactory->has('pages')
&& $this->schemaFactory->get('pages')
->hasCapability(TcaSchemaCapability::Workspace);
isRootLevelRestrictionIgnored
-----------------------------
.. code-block:: php
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Schema\TcaSchemaCapability;
use TYPO3\CMS\Core\Schema\TcaSchemaFactory;
// Before
return BackendUtility::isRootLevelRestrictionIgnored('pages');
// After (retrieve an instance of TcaSchemaFactory via dependency
// injection of TYPO3\CMS\Core\Schema\TcaSchemaFactory)
return $this->schemaFactory->has('pages')
&& $this->schemaFactory->get('pages')
->getCapability(
TcaSchemaCapability::RestrictionRootLevel
)->shallIgnoreRootLevelRestriction();
isWebMountRestrictionIgnored
----------------------------
.. code-block:: php
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Schema\TcaSchemaCapability;
use TYPO3\CMS\Core\Schema\TcaSchemaFactory;
// Before
return BackendUtility::isWebMountRestrictionIgnored('pages');
// After (retrieve an instance of TcaSchemaFactory via dependency
// injection of TYPO3\CMS\Core\Schema\TcaSchemaFactory)
return $this->schemaFactory->has('pages')
&& $this->schemaFactory->get('pages')
->hasCapability(TcaSchemaCapability::RestrictionWebMount);
resolveFileReferences
---------------------
No substitution is available. Copy the method into your own codebase and adapt
it as needed.
.. index:: TCA, FullyScanned, ext:core

Some files were not shown because too many files have changed in this diff Show More