TYPO3 v15 dev-main snapshot ()
This commit is contained in:
+71
@@ -0,0 +1,71 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-102326-1699703964:
|
||||
|
||||
=================================================================================
|
||||
Deprecation: #102326 - RegularExpressionValidator validator option "errorMessage"
|
||||
=================================================================================
|
||||
|
||||
See :issue:`102326`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The :php:`errorMessage` validator option provides a custom string
|
||||
as error message for validation failures of the :php:`RegularExpressionValidator`.
|
||||
In order to streamline error message translation keys with other validators,
|
||||
the :php:`errorMessage` validator option has been marked as deprecated in
|
||||
TYPO3 v13 and will be removed in TYPO3 v14.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Using the :php:`errorMessage` validator option with the :php:`RegularExpressionValidator`
|
||||
will trigger a PHP deprecation warning.
|
||||
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
TYPO3 installations using the validator option :php:`errorMessage` with the
|
||||
:php:`RegularExpressionValidator`.
|
||||
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
The new :php:`message` validator option should be used to provide a custom
|
||||
translatable error message for failed validation.
|
||||
|
||||
Before:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use TYPO3\CMS\Extbase\Annotation as Extbase;
|
||||
|
||||
#[Extbase\Validate([
|
||||
'validator' => 'RegularExpression',
|
||||
'options' => [
|
||||
'regularExpression' => '/^simple[0-9]expression$/',
|
||||
'errorMessage' => 'Error message or LLL schema string',
|
||||
],
|
||||
])]
|
||||
protected string $myProperty = '';
|
||||
|
||||
After:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use TYPO3\CMS\Extbase\Annotation as Extbase;
|
||||
|
||||
#[Extbase\Validate([
|
||||
'validator' => 'RegularExpression',
|
||||
'options' => [
|
||||
'regularExpression' => '/^simple[0-9]expression$/',
|
||||
'message' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:my.languageKey'
|
||||
],
|
||||
])]
|
||||
protected string $myProperty = '';
|
||||
|
||||
.. index:: Backend, NotScanned, ext:extbase
|
||||
@@ -0,0 +1,50 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-102337-1715591179:
|
||||
|
||||
==========================================================
|
||||
Deprecation: #102337 - Deprecate hooks for record download
|
||||
==========================================================
|
||||
|
||||
See :issue:`102337`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The previously used hooks
|
||||
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList']['customizeCsvHeader']`
|
||||
and
|
||||
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList']['customizeCsvRow']`,
|
||||
used to manipulate the download / export configuration of records, triggered
|
||||
in the :guilabel:`Web > List` backend module, have been deprecated in favor of a
|
||||
new PSR-14 event :php:`TYPO3\CMS\Backend\RecordList\Event\BeforeRecordDownloadIsExecutedEvent`.
|
||||
|
||||
Details for migration and functionality can be found in :ref:`feature-102337-1715591178`
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
When the hook :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList']['customizeCsvHeader']`
|
||||
or
|
||||
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList']['customizeCsvRow']`
|
||||
is executed, this will trigger a PHP deprecation warning.
|
||||
|
||||
The extension scanner will find possible usages with a weak match.
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
All installations using
|
||||
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList']['customizeCsvHeader']`
|
||||
or
|
||||
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList']['customizeCsvRow']`
|
||||
are affected.
|
||||
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
The new PSR-14 event :php:`TYPO3\CMS\Backend\RecordList\Event\BeforeRecordDownloadIsExecutedEvent`
|
||||
can be used as a near drop-in replacement.
|
||||
|
||||
.. index:: PHP-API, FullyScanned, ext:core
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-103752-1714304437:
|
||||
|
||||
========================================================================================
|
||||
Deprecation: #103752 - Obsolete `$GLOBALS['TYPO3_CONF_VARS']['FE']['addRootLineFields']`
|
||||
========================================================================================
|
||||
|
||||
See :issue:`103752`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Configuration option :php:`$GLOBALS['TYPO3_CONF_VARS']['FE']['addRootLineFields']`
|
||||
is obsolete and has been removed in TYPO3 Core v13.2.
|
||||
|
||||
This option is well-known to integrators who add relations to the TCA :sql:`pages`
|
||||
table. It triggers relation resolving of page relations for additional fields when
|
||||
rendering a frontend request in the default language. The most common usage is
|
||||
TypoScript "slide".
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Integrators can simply forget about this option: relations of table :sql:`pages`
|
||||
are now resolved with nearly no performance penalty in comparison to not
|
||||
having them resolved.
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
Many instances add additional relations to the :sql:`pages` table then add
|
||||
this field in :php:`addRootLineFields`. This option is no longer evaluated.
|
||||
Relation fields attached to :sql:`pages` are always resolved in frontend.
|
||||
|
||||
There should be hardly any extensions using this option, since it was
|
||||
an internal option of class :php:`RootlineUtility`. Extensions using
|
||||
:php:`$GLOBALS['TYPO3_CONF_VARS']['FE']['addRootLineFields']` *may* trigger a
|
||||
PHP warning level error because the array key has been removed. The extension scanner
|
||||
is configured to locate such usages.
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
The option is no longer evaluated in TYPO3 Core. It is removed from
|
||||
:php:`settings.php` during upgrade, if given.
|
||||
|
||||
|
||||
.. index:: Frontend, LocalConfiguration, PHP-API, FullyScanned, ext:core
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-103785-1714720280:
|
||||
|
||||
========================================================================
|
||||
Deprecation: #103785 - Deprecate MathUtility::convertToPositiveInteger()
|
||||
========================================================================
|
||||
|
||||
See :issue:`103785`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
TYPO3 has the method :php:`MathUtility::convertToPositiveInteger()` to ensure
|
||||
that an integer is always positive. However, the method is rather
|
||||
"heavy" as it calls :php:`MathUtility::forceIntegerInRange()` internally and
|
||||
therefore misuses a clamp mechanism to convert the integer to a positive number.
|
||||
|
||||
Also, the method name doesn't reflect what the method actually does. Negative
|
||||
numbers are not converted to their positive counterpart, but are swapped with
|
||||
`0`. Due to the naming issue and the fact that the method can be replaced by a
|
||||
simple :php:`max()` call, the method is therefore deprecated.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Calling :php:`MathUtility::convertToPositiveInteger()` will trigger a PHP
|
||||
deprecation warning.
|
||||
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
All installations using :php:`MathUtility::convertToPositiveInteger()`.
|
||||
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
To recover the original behavior of the deprecated method, its call can be
|
||||
replaced with :php:`max(0, $number)`. To actually convert negative numbers to
|
||||
their positive counterpart, call :php:`abs($number)`.
|
||||
|
||||
.. index:: PHP-API, FullyScanned, ext:core
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-103965-1717335369:
|
||||
|
||||
================================================================================
|
||||
Deprecation: #103965 - Deprecate namespaced shorthand validator usage in Extbase
|
||||
================================================================================
|
||||
|
||||
See :issue:`103965`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
It is possible to use undocumented namespaced shorthand notation in Extbase
|
||||
to add validators to properties or arguments. For example,
|
||||
:php:`TYPO3.CMS.Extbase:NotEmpty` will be resolved as
|
||||
:php:`TYPO3\CMS\Extbase\Validation\Validator\NotEmptyValidator` and
|
||||
:php:`Vendor.Extension:Custom` will be resolved as
|
||||
:php:`\Vendor\MyExtension\Validation\Validator\CustomValidator`.
|
||||
|
||||
The namespaced shorthand notation for Extbase validators has been marked as
|
||||
deprecated and will be removed in TYPO3 v14.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Using namespaced shorthand notation in Extbase will trigger a PHP deprecation
|
||||
warning.
|
||||
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
All installations using namespaced shorthand notation in Extbase.
|
||||
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
Extensions using the namespaced shorthand notation must use the FQCN of the
|
||||
validator instead. For Extbase core validators, the well known
|
||||
shorthand validator name can be used.
|
||||
|
||||
Before
|
||||
------
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
/**
|
||||
* @Extbase\Validate("TYPO3.CMS.Extbase:NotEmpty")
|
||||
*/
|
||||
protected $myProperty1;
|
||||
|
||||
/**
|
||||
* @Extbase\Validate("Vendor.Extension:Custom")
|
||||
*/
|
||||
protected $myProperty2;
|
||||
|
||||
|
||||
After
|
||||
-----
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
/**
|
||||
* @Extbase\Validate("NotEmpty")
|
||||
*/
|
||||
protected $myProperty1;
|
||||
|
||||
/**
|
||||
* @Extbase\Validate("Vendor\Extension\Validation\Validator\CustomValidator")
|
||||
*/
|
||||
protected $myProperty2;
|
||||
|
||||
or
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
#[Extbase\Validate(['validator' => \TYPO3\CMS\Extbase\Validation\Validator\NotEmptyValidator::class])]
|
||||
protected $myProperty1;
|
||||
|
||||
#[Extbase\Validate(['validator' => \Vendor\Extension\Validation\Validator\CustomValidator::class])]
|
||||
protected $myProperty2;
|
||||
|
||||
.. index:: Frontend, NotScanned, ext:extbase
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-104108-1718354448:
|
||||
|
||||
================================================================
|
||||
Deprecation: #104108 - Table dependant definition of columnsOnly
|
||||
================================================================
|
||||
|
||||
See :issue:`104108`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
When linking to the edit form it's possible to instruct the
|
||||
:php:`EditDocumentController` to only render a subset of available
|
||||
fields for relevant records using the `columnsOnly` functionality,
|
||||
by adding the fields to be rendered as a comma-separated list.
|
||||
|
||||
However, the edit form can render records from many tables, and not just
|
||||
a single table, in the same request.
|
||||
|
||||
Therefore, the limit fields functionality has been extended to allow
|
||||
setting the fields to be rendered on a per-table basis. This means that
|
||||
passing a comma-separated list of fields as a value for `columnsOnly`
|
||||
has been deprecated.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Passing a comma-separated list of fields as value for `columnsOnly` will
|
||||
trigger a PHP deprecation warning. A compatibility layer will automatically
|
||||
set the field list for the required tables.
|
||||
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
All installations passing a comma-separated list of fields as a value for
|
||||
`columnsOnly`.
|
||||
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
The fields to be rendered have to be passed as an :php:`array` under the
|
||||
corresponding table name.
|
||||
|
||||
An example, building such link using the `UriBuilder`:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$urlParameters = [
|
||||
'edit' => [
|
||||
'pages' => [
|
||||
1 => 'edit',
|
||||
],
|
||||
],
|
||||
'columnsOnly' => 'title,slug'
|
||||
'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri(),
|
||||
];
|
||||
|
||||
GeneralUtility::makeInstance(UriBuilder::class)->buildUriFromRoute('record_edit', $urlParameters);
|
||||
|
||||
Above example has to be migrated to:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$urlParameters = [
|
||||
'edit' => [
|
||||
'pages' => [
|
||||
1 => 'edit',
|
||||
],
|
||||
],
|
||||
'columnsOnly' => [
|
||||
'pages' => [
|
||||
'title',
|
||||
'slug'
|
||||
]
|
||||
],
|
||||
'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri(),
|
||||
];
|
||||
|
||||
GeneralUtility::makeInstance(UriBuilder::class)->buildUriFromRoute('record_edit', $urlParameters);
|
||||
|
||||
Additionally, when rendering records from many tables, a configuration
|
||||
could look like the following:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$urlParameters = [
|
||||
'edit' => [
|
||||
'pages' => [
|
||||
1 => 'edit',
|
||||
],
|
||||
'tt_content' => [
|
||||
2 => 'edit',
|
||||
],
|
||||
],
|
||||
'columnsOnly' => [
|
||||
'pages' => [
|
||||
'title',
|
||||
'slug'
|
||||
],
|
||||
'tt_content' => [
|
||||
'header',
|
||||
'subheader'
|
||||
]
|
||||
],
|
||||
'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri(),
|
||||
];
|
||||
|
||||
// https:://example.com/typo3/record/edit?edit[pages][1]=edit&edit[tt_content][2]=edit&columnsOnly[pages][0]=title&columnsOnly[pages][1]=slug&columnsOnly[tt_content][0]=header&columnsOnly[tt_content][1]=subheader
|
||||
$link = GeneralUtility::makeInstance(UriBuilder::class)->buildUriFromRoute('record_edit', $urlParameters);
|
||||
|
||||
.. index:: Backend, NotScanned, ext:backend
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-104154-1718802119:
|
||||
|
||||
=====================================================================
|
||||
Deprecation: #104154 - Deprecate Utility.updateQueryStringParameter()
|
||||
=====================================================================
|
||||
|
||||
See :issue:`104154`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The :js:`Utility.updateQueryStringParameter()` method in the
|
||||
:js:`@typo3/backend/utility.js` module was introduced in TYPO3 v8 as a bugfix
|
||||
for highlighting in the old ExtJS-based page tree. Since removal of ExtJS in
|
||||
TYPO3 v9 the method has been unused.
|
||||
|
||||
Because safe removal of the method cannot be guaranteed as this point, it is
|
||||
therefore deprecated.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Calling :js:`Utility.updateQueryStringParameter()` will result in a JavaScript
|
||||
warning.
|
||||
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
All 3rd party extensions using the deprecated method.
|
||||
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
Now, JavaScript supports the :js:`URL` and its related :js:`URLSearchParams`
|
||||
object that can be used to achieve the same result:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
const url = new URL('http://localhost?baz=baz');
|
||||
url.searchParams.set('baz', 'bencer');
|
||||
const urlString = url.toString(); // http://localhost?baz=bencer
|
||||
|
||||
.. index:: JavaScript, NotScanned, ext:backend
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-102155-1717653944:
|
||||
|
||||
======================================================================
|
||||
Feature: #102155 - User TSconfig option for default resources ViewMode
|
||||
======================================================================
|
||||
|
||||
See :issue:`102155`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The listing of resources in the TYPO3 backend, e.g. in the
|
||||
:guilabel:`File > Filelist` module or the `FileBrowser` can be switched
|
||||
between `list` and `tiles`. TYPO3 serves `tiles` by default.
|
||||
|
||||
A new User TSconfig option :typoscript:`options.defaultResourcesViewMode` has
|
||||
been introduced, which allows the initial display mode to be defined. Valid
|
||||
values are therefore `list` and `tiles`, e.g.:
|
||||
|
||||
.. code-block:: typoscript
|
||||
|
||||
options.defaultResourcesViewMode = list
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Integrators can now define the default display mode for resources via
|
||||
User TSconfig.
|
||||
|
||||
.. index:: Backend, TSConfig, ext:filelist
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-102326-1699707043:
|
||||
|
||||
===================================================================
|
||||
Feature: #102326 - Allow custom translations for Extbase validators
|
||||
===================================================================
|
||||
|
||||
See :issue:`102326`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
All validation messages from Extbase validators can now be overwritten
|
||||
using validator options. It is possible to provide either a translation key or
|
||||
a custom message as string.
|
||||
|
||||
Extbase validators providing only one validation message can be overwritten by a
|
||||
translation key or message using the validator option :php:`message`. Validators
|
||||
providing multiple validation messages (e.g. :php:`Boolean`, :php:`NotEmpty` or
|
||||
:php:`NumberRange`) use different validator options keys. In general,
|
||||
translation keys or messages for validators are registered in the validator
|
||||
property :php:`translationOptions`.
|
||||
|
||||
Example with translations
|
||||
-------------------------
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use TYPO3\CMS\Extbase\Annotation as Extbase;
|
||||
|
||||
#[Extbase\Validate([
|
||||
'validator' => 'NotEmpty',
|
||||
'options' => [
|
||||
'nullMessage' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:validation.myProperty.notNull',
|
||||
'emptyMessage' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:validation.myProperty.notEmpty',
|
||||
],
|
||||
])]
|
||||
protected string $myProperty = '';
|
||||
|
||||
In this example, translation option keys for the :php:`NotEmptyValidator` are
|
||||
overwritten for the property :php:`$myProperty`. The :php:`locallang.xlf`
|
||||
translation file from the extension :php:`my_extension` will be used to lookup
|
||||
translations for the newly provided translation key options.
|
||||
|
||||
Example with a custom string
|
||||
----------------------------
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use TYPO3\CMS\Extbase\Annotation as Extbase;
|
||||
|
||||
#[Extbase\Validate([
|
||||
'validator' => 'Float',
|
||||
'options' => [
|
||||
'message' => 'A custom, non translatable message',
|
||||
],
|
||||
])]
|
||||
protected float $myProperty = 0.0;
|
||||
|
||||
In this example, translation option keys for the :php:`FloatValidator` are
|
||||
overwritten for the property :php:`$myProperty`. The message string is
|
||||
shown if validation fails.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
The new validator translation option keys allow developers to define unique
|
||||
validation messages for TYPO3 Extbase validators on validator usage basis. This
|
||||
may result in a better user experience, since validation messages now can refer
|
||||
to the current usage scope (e.g. "The field 'Title' is required" instead of
|
||||
"The given subject was empty.").
|
||||
|
||||
.. index:: Backend, ext:extbase
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-102337-1715591178:
|
||||
|
||||
=====================================================================
|
||||
Feature: #102337 - PSR-14 event for modifying record list export data
|
||||
=====================================================================
|
||||
|
||||
See :issue:`102337`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
A new PSR-14 event :php:`TYPO3\CMS\Backend\RecordList\Event\BeforeRecordDownloadIsExecutedEvent`
|
||||
has been introduced to modify the result of a download / export initiated in
|
||||
the :guilabel:`Web > List` module.
|
||||
|
||||
This replaces the
|
||||
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList']['customizeCsvHeader']`
|
||||
and
|
||||
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList']['customizeCsvRow']`,
|
||||
hooks, which have been :ref:`deprecated <deprecation-102337-1715591179>`.
|
||||
|
||||
The event allows body and header sections of the data dump to be modified,
|
||||
so that they can e.g. be used to redact specific data for GDPR compliance,
|
||||
transform / translate specific data, trigger creation of archives or web hooks,
|
||||
log export access and more.
|
||||
|
||||
The event offers the following methods:
|
||||
|
||||
- :php:`getHeaderRow()`: Return the current header row of the dataset.
|
||||
- :php:`setHeaderRow()`: Sets the modified header row of the dataset.
|
||||
- :php:`getRecords()`: Returns the current body rows of the dataset.
|
||||
- :php:`setRecords()`: Sets the modified body rows of the dataset.
|
||||
- :php:`getRequest()`: Returns the PSR request context.
|
||||
- :php:`getTable()`: Returns the name of the database table of the dataset.
|
||||
- :php:`getFormat()`: Returns the format of the download action (CSV/JSON).
|
||||
- :php:`getFilename()`: Returns the name of the download filename (for browser output).
|
||||
- :php:`getId()`: Returns the page UID of the download origin.
|
||||
- :php:`getModTSconfig()`: Returns the active module TSconfig of the download origin.
|
||||
- :php:`getColumnsToRender()`: Returns the list of header columns for the triggered download.
|
||||
- :php:`isHideTranslations()`: Returns whether translations are hidden or not.
|
||||
|
||||
Example
|
||||
=======
|
||||
|
||||
The corresponding event listener class:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Vendor\MyPackage\Core\EventListener;
|
||||
|
||||
use TYPO3\CMS\Backend\RecordList\Event\BeforeRecordDownloadIsExecutedEvent;
|
||||
use TYPO3\CMS\Core\Attribute\AsEventListener;
|
||||
|
||||
#[AsEventListener(identifier: 'my-package/record-list-download-data')]
|
||||
final readonly class DataListener
|
||||
{
|
||||
public function __invoke(BeforeRecordDownloadIsExecutedEvent $event): void
|
||||
{
|
||||
// List of redactable fields.
|
||||
$gdprFields = ['title', 'author'];
|
||||
|
||||
$headerRow = $event->getHeaderRow();
|
||||
$records = $event->getRecords();
|
||||
|
||||
// Iterate header to mark redacted fields...
|
||||
foreach ($headerRow as $headerRowKey => $headerRowValue) {
|
||||
if (in_array($headerRowKey, $gdprFields, true)) {
|
||||
$headerRow[$headerRowKey] .= ' (REDACTED)';
|
||||
}
|
||||
}
|
||||
|
||||
// Redact actual content...
|
||||
foreach ($records as $uid => $record) {
|
||||
foreach ($gdprFields as $gdprField) {
|
||||
if (isset($record[$gdprField])) {
|
||||
$records[$uid][$gdprField] = '(REDACTED)';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$event->setHeaderRow($headerRow);
|
||||
$event->setRecords($records);
|
||||
}
|
||||
}
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
The functionality of both hooks :php:`customizeCsvHeader` and
|
||||
:php:`customizeCsvRow` are now handled by the new PSR-14 event.
|
||||
|
||||
Migrating :php:`customizeCsvHeader`
|
||||
-----------------------------------
|
||||
|
||||
The prior hook parameter/variable :php:`fields` is now available via
|
||||
:php:`$event->getColumnsToRender()`. The actual record data
|
||||
(previously :php:`$this->recordList`, submitted to the hook as its object
|
||||
reference) is accessible via :php:`$event->getHeaderRow()`.
|
||||
|
||||
Migrating :php:`customizeCsvRow`
|
||||
--------------------------------
|
||||
|
||||
The prior hook parameters/variables have the following substitutes:
|
||||
|
||||
- :php:`databaseRow` is now available via :php:`$event->getRecords()` (see note below).
|
||||
- :php:`tableName` is now available via :php:`$event->getTable()`.
|
||||
- :php:`pageId` is now available via :php:`$event->getId()`.
|
||||
|
||||
The actual record data
|
||||
(previously :php:`$this->recordList`, submitted to the hook as its object
|
||||
reference) is accessible via :php:`$event->getRecords()`.
|
||||
|
||||
Please note that the hook was previously executed once per row retrieved
|
||||
from the database. The PSR-14 event however - due to performance reasons -
|
||||
is only executed for the full record list after database retrieval,
|
||||
thus allowing post-processing on the whole dataset.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Using the PSR-14 event :php:`BeforeRecordDownloadIsExecutedEvent` it is
|
||||
now possible to modify all of the data available when downloading / exporting
|
||||
a list of records via the :guilabel:`Web > List` module.
|
||||
|
||||
|
||||
.. index:: Backend, PHP-API, ext:core
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-102337-1715591177:
|
||||
|
||||
==========================================================================
|
||||
Feature: #102337 - PSR-14 event for modifying record list download presets
|
||||
==========================================================================
|
||||
|
||||
See :issue:`102337`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
A new PSR-14 event :php:`TYPO3\CMS\Backend\RecordList\Event\BeforeRecordDownloadPresetsAreDisplayedEvent`
|
||||
has been introduced to manipulate the list of available download presets in
|
||||
the :guilabel:`Web > List` module.
|
||||
|
||||
See :ref:`feature-102337-1712597691` for a detailed description of how to
|
||||
utilize presets when downloading a set of records from the backend in CSV
|
||||
or JSON format.
|
||||
|
||||
The event class offers the following methods:
|
||||
|
||||
- :php:`getPresets()`: Returns a list of presets set via TSconfig
|
||||
- :php:`setPresets()`: Sets a modified list of presets.
|
||||
- :php:`getDatabaseTable()`: Returns the database table name that a preset applies to.
|
||||
- :php:`getRequest()`: Returns the PSR Request object for the context of the request.
|
||||
- :php:`getId()`: Returns the page ID of the originating page.
|
||||
|
||||
Note that the event is dispatched for one specific database table. If
|
||||
an event listener is created to attach presets to different tables, the
|
||||
listener method must check for the table name, as shown in the example below.
|
||||
|
||||
If no download presets exist for a given table, the PSR-14 event can still
|
||||
be used to modify and add presets to it via the :php:`setPresets()` method.
|
||||
|
||||
The array passed from :php:`getPresets()` to :php:`setPresets()` can contain
|
||||
an array collection of :php:`TYPO3\CMS\Backend\RecordList\DownloadPreset`
|
||||
objects with the array key using the preset label.
|
||||
The existing presets can be retrieved with these getters:
|
||||
|
||||
- :php:`$preset->getLabel()`: Name of the preset (can utilize LLL translations), optional.
|
||||
- :php:`$preset->getColumns()`: Array of database table column names.
|
||||
- :php:`$preset->getIdentifier()`: Identifier of the preset (manually set or calculated based on label and columns)
|
||||
|
||||
The event listener can also remove array indexes or columns of existing
|
||||
array entries by passing a newly constructed :php:`DownloadPreset` object with the
|
||||
changed `label` and `columns` constructor properties.
|
||||
|
||||
Example
|
||||
=======
|
||||
|
||||
The corresponding event listener class:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Vendor\MyPackage\RecordList\EventListener;
|
||||
|
||||
use TYPO3\CMS\Backend\RecordList\Event\BeforeRecordDownloadPresetsAreDisplayedEvent;
|
||||
use TYPO3\CMS\Backend\RecordList\DownloadPreset;
|
||||
use TYPO3\CMS\Core\Attribute\AsEventListener;
|
||||
|
||||
#[AsEventListener(identifier: 'my-package/modify-record-list-preset')]
|
||||
final readonly class PresetListener
|
||||
{
|
||||
public function __invoke(BeforeRecordDownloadPresetsAreDisplayedEvent $event): void
|
||||
{
|
||||
$presets = $event->getPresets();
|
||||
|
||||
switch ($event->getDatabaseTable()) {
|
||||
case 'be_users':
|
||||
$presets[] = new DownloadPreset('PSR-14 preset', ['uid','email']);
|
||||
break;
|
||||
|
||||
case 'pages':
|
||||
$presets[] = new DownloadPreset('PSR-14 preset', ['title']);
|
||||
$presets[] = new DownloadPreset('Another PSR-14 preset', ['title', 'doktype']);
|
||||
break;
|
||||
|
||||
case 'tx_myvendor_myextension':
|
||||
$presets[] = new DownloadPreset('PSR-14 preset', ['uid', 'something']);
|
||||
break;
|
||||
}
|
||||
|
||||
$presets[] = new DownloadPreset('Available everywhere, simple UID list', ['uid']);
|
||||
|
||||
$presets['some-identifier'] = new DownloadPreset('Overwrite preset', ['uid, pid'], 'some-identifier');
|
||||
|
||||
$event->setPresets($presets);
|
||||
}
|
||||
}
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Using the PSR-14 event :php:`BeforeRecordDownloadPresetsAreDisplayedEvent`
|
||||
it is now possible to modify the presets of each table for
|
||||
downloading / exporting a list of such records via the :guilabel:`Web > List`
|
||||
module.
|
||||
|
||||
.. index:: Backend, PHP-API, ext:core
|
||||
@@ -0,0 +1,99 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-102337-1712597691:
|
||||
|
||||
=======================================================
|
||||
Feature: #102337 - Presets for download of record lists
|
||||
=======================================================
|
||||
|
||||
See :issue:`102337`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
In the :guilabel:`Web > List` backend module, the data of records for each
|
||||
database table (including pages and content records) can be downloaded.
|
||||
|
||||
This export takes the currently selected list of columns into consideration and
|
||||
alternatively allows all columns to be selected.
|
||||
|
||||
A new feature has been introduced adding the ability to pick the exported
|
||||
data columns from a list of configurable presets.
|
||||
|
||||
Those presets can be configured via page TSconfig, and can also be
|
||||
overridden via user TSconfig (for example, to make certain presets
|
||||
only available to specific users).
|
||||
|
||||
.. code-block:: typoscript
|
||||
:caption: EXT:my_extension/Configuration/page.tsconfig
|
||||
|
||||
mod.web_list.downloadPresets {
|
||||
pages {
|
||||
10 {
|
||||
label = Quick overview
|
||||
columns = uid, title, crdate, slug
|
||||
}
|
||||
|
||||
20 {
|
||||
identifier = LLL:EXT:myext/Resources/Private/Language/locallang.xlf:preset2.label
|
||||
label = UID and titles only
|
||||
columns = uid, title
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Each entry of :typoscript:`mod.web_list.downloadPresets`
|
||||
defines the table name on the first level (in this case `pages`), followed by
|
||||
any number of presets.
|
||||
|
||||
Each preset contains a :typoscript:`label` (the displayed name of the preset,
|
||||
which can be a locallang key), a comma-separated list of each column that
|
||||
should be included in the export as :typoscript:`columns` and optionally
|
||||
an :typoscript:`identifier`. If :typoscript:`identifier` is not provided,
|
||||
the identifier is generated as a hash of the :typoscript:`label` and
|
||||
:typoscript:`columns`.
|
||||
|
||||
This can be manipulated with user TSConfig by adding the :typoscript:`page.`
|
||||
prefix. User TSConfig is loaded after page TSConfig, so you can overwrite
|
||||
existing keys or replace the whole list of keys:
|
||||
|
||||
.. code-block:: typoscript
|
||||
:caption: EXT:my_extension/Configuration/user.tsconfig
|
||||
|
||||
page.mod.web_list.downloadPresets {
|
||||
pages {
|
||||
10 {
|
||||
label = Quick overview (customized)
|
||||
columns = uid, title, crdate, slug
|
||||
}
|
||||
|
||||
30 {
|
||||
label = Short with URL
|
||||
columns = uid, title, slug
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Since any table can be configured for a preset, any extension
|
||||
can deliver a defined set of presets through the
|
||||
:file:`EXT:my_extension/Configuration/page.tsconfig` file and
|
||||
their table name(s).
|
||||
|
||||
Additionally, the list of presets can be manipulated via the new
|
||||
:ref:`BeforeRecordDownloadPresetsAreDisplayedEvent <feature-102337-1715591177>`.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Editors can now export data with specific presets as required
|
||||
as identified by the website maintainer or extension developer(s).
|
||||
|
||||
It is no longer required to pick specific columns to export over and over again,
|
||||
and the list of presets is controlled by the website maintainer.
|
||||
|
||||
Two new PSR-14 Events have been added to allow further manipulation:
|
||||
|
||||
* :ref:`BeforeRecordDownloadIsExecutedEvent <feature-102337-1715591177>`
|
||||
* :ref:`BeforeRecordDownloadPresetsAreDisplayedEvent <feature-102337-1715591178>`
|
||||
|
||||
.. index:: Backend, TSConfig
|
||||
@@ -0,0 +1,26 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-102869-1705661913:
|
||||
|
||||
================================================
|
||||
Feature: #102869 - List workspaces in LiveSearch
|
||||
================================================
|
||||
|
||||
See :issue:`102869`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The backend LiveSearch is now able to list workspaces a backend user has access
|
||||
to, offering the possibility to switch to a workspace quickly outside the
|
||||
Workspaces module.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Backend users now have another, quickly accessible way to access a workspace.
|
||||
With proper permissions, a backend user may also switch to the edit interface of
|
||||
a workspace to configure its settings.
|
||||
|
||||
.. index:: Backend, ext:workspaces
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-102951-1709643048:
|
||||
|
||||
==============================================================
|
||||
Feature: #102951 - Provide PSR-7 request in Extbase validators
|
||||
==============================================================
|
||||
|
||||
See :issue:`102951`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Extbase :php:`abstractValidator` now provides a getter and a setter
|
||||
for the PSR-7 Request object. Validators extending :php:`AbstractValidator`
|
||||
will include the PSR-7 request object, if the validator has been instantiated
|
||||
by Extbase :php:`ValidationResolver`.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Extension developers can now create custom validators which consume data
|
||||
from the PSR-7 request object (e.g. request attribute
|
||||
:php:`frontend.user`).
|
||||
|
||||
.. index:: PHP-API, ext:extbase
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-103019-1706856586:
|
||||
|
||||
======================================================================
|
||||
Feature: #103019 - ModifyRedirectUrlValidationResultEvent PSR-14 event
|
||||
======================================================================
|
||||
|
||||
See :issue:`103019`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
This feature introduces the new PSR-14 event
|
||||
:php:`ModifyRedirectUrlValidationResultEvent` in the felogin extension to
|
||||
provide developers the possibility and flexibility to implement custom
|
||||
validation for the redirect URL. This may be useful if TYPO3 frontend login
|
||||
acts as an SSO system or if users should be redirected to an external URL after
|
||||
login.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
|
||||
namespace Vendor\MyExtension\EventListener;
|
||||
|
||||
use TYPO3\CMS\Core\Attribute\AsEventListener;
|
||||
use TYPO3\CMS\FrontendLogin\Event\ModifyRedirectUrlValidationResultEvent;
|
||||
|
||||
class ValidateRedirectUrl
|
||||
{
|
||||
#[AsEventListener('validate-custom-redirect-url')]
|
||||
public function __invoke(ModifyRedirectUrlValidationResultEvent $event): void
|
||||
{
|
||||
$parsedUrl = parse_url($event->getRedirectUrl());
|
||||
if ($parsedUrl['host'] === 'trusted-host-for-redirect.tld') {
|
||||
$event->setValidationResult(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Developers now have the possibility to modify the validation results for the
|
||||
redirect URL, allowing redirects to URLs not matching existing validation
|
||||
constraints.
|
||||
|
||||
.. index:: Frontend, PHP-API, ext:felogin
|
||||
@@ -0,0 +1,29 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-103493-1711562309:
|
||||
|
||||
===========================================================
|
||||
Feature: #103493 - Edit full record in "Check Links" module
|
||||
===========================================================
|
||||
|
||||
See :issue:`103493`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Previously, the listing in the :guilabel:`Check Links` backend module
|
||||
provided the possibility to edit the field of a record that has been identified
|
||||
as having a broken link. However, in some cases relevant context might be missing,
|
||||
e.g. when editing redirect records.
|
||||
|
||||
Therefore, a new button has been introduced which allows the full record of the
|
||||
broken link to be edited. The new button is placed next to the
|
||||
existing - single field - edit button.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
A new button is now displayed in the :guilabel:`Check Links` backend module,
|
||||
allowing the full record of a broken link to be edited.
|
||||
|
||||
.. index:: Backend, ext:linkvalidator
|
||||
@@ -0,0 +1,44 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-103706-1713883119:
|
||||
|
||||
=========================================================
|
||||
Feature: #103706 - Default search level for record search
|
||||
=========================================================
|
||||
|
||||
See :issue:`103706`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
When searching for records in the :guilabel:`Web > List` module as well as
|
||||
the database browser, it's possible to select the search levels (page tree
|
||||
levels to respect in the search).
|
||||
|
||||
An editor is therefore able to select between the current page, a couple of
|
||||
defined levels (e.g. 1, 2, 3) as well as the special "infinite levels".
|
||||
|
||||
Those options can already be extended using the TSconfig option
|
||||
:typoscript:`mod.web_list.searchLevel.items`.
|
||||
|
||||
Next to this, a new TSconfig option :typoscript:`mod.web_list.searchLevel.default`
|
||||
has been introduced, which allows to define one of the available level options
|
||||
as the default level to use.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code-block:: typoscript
|
||||
:caption: EXT:my_sitepackage/Configuration/page.tsconfig
|
||||
|
||||
# Set the default search level to "infinite levels"
|
||||
mod.web_list.searchLevel.default = -1
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
It's now possible to define a default search level using the new page
|
||||
TSconfig option :typoscript:`mod.web_list.searchLevel.default`.
|
||||
|
||||
.. index:: Backend, TSConfig, ext:backend
|
||||
@@ -0,0 +1,176 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-103783-1715113274:
|
||||
|
||||
======================================================
|
||||
Feature: #103783 - RecordTransformation Data Processor
|
||||
======================================================
|
||||
|
||||
See :issue:`103783`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
A new TypoScript data processor for :typoscript:`FLUIDTEMPLATE` and
|
||||
:typoscript:`PAGEVIEW` has been added.
|
||||
|
||||
The :typoscript:`record-transformation` Data Processor can typically be used in
|
||||
conjunction with the DatabaseQuery Data Processor. The DatabaseQuery Data
|
||||
Processor typically fetches records from the database, and the
|
||||
:typoscript:`record-transformation` will take the result and transform
|
||||
the objects into :php:`Record` objects, which contain relevant data from
|
||||
the TCA table, which has been configured in the TCA columns fields for this
|
||||
record.
|
||||
|
||||
This is especially useful for TCA tables, which contain "types" (such as pages
|
||||
or tt_content database tables), where only relevant fields are added to the
|
||||
record object. In addition, special fields from "enableColumns" or deleted
|
||||
fields, as well as language and version information are extracted so they can be
|
||||
dealt with in a unified way.
|
||||
|
||||
The "type" property contains the database table name and the actual type based
|
||||
on the record, such as "tt_content.textmedia" for Content Elements.
|
||||
|
||||
.. note::
|
||||
|
||||
The Record object is available but details are still to be finalized in
|
||||
the API by TYPO3 v13 LTS. Right now only the usage in Fluid is public
|
||||
API.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Example of the data processor being used in conjunction with DatabaseQuery
|
||||
processor.
|
||||
|
||||
.. code-block:: typoscript
|
||||
|
||||
page = PAGE
|
||||
page {
|
||||
10 = PAGEVIEW
|
||||
10 {
|
||||
paths.10 = EXT:my_extension/Resources/Private/Templates/
|
||||
dataProcessing {
|
||||
10 = database-query
|
||||
10 {
|
||||
as = mainContent
|
||||
table = tt_content
|
||||
select.where = colPos=0
|
||||
dataProcessing.10 = record-transformation
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Transform the current data array of :typoscript:`FLUIDTEMPLATE` to a Record
|
||||
object. This can be used for Content Elements of Fluid Styled Content or
|
||||
custom ones. In this example the FSC element "Text" has its data transformed for
|
||||
easier and enhanced usage.
|
||||
|
||||
.. code-block:: typoscript
|
||||
|
||||
tt_content.text {
|
||||
templateName = Text
|
||||
dataProcessing {
|
||||
10 = record-transformation
|
||||
}
|
||||
}
|
||||
|
||||
Usage in Fluid templates
|
||||
------------------------
|
||||
|
||||
The :html:`f:debug` output of the Record object is misleading for integrators,
|
||||
as most properties are accessed differently than would be expected. The debug view
|
||||
is a better organized overview of all the available information. E.g.
|
||||
the property `properties` lists all relevant fields for the current Content
|
||||
Type.
|
||||
|
||||
We are dealing with an object here. You can, however, access your record
|
||||
properties as you are used to with :html:`{record.title}` or
|
||||
:html:`{record.uid}`. In addition, you gain special, context-aware properties
|
||||
like the language :html:`{record.languageId}` or workspace
|
||||
:html:`{record.versionInfo.workspaceId}`.
|
||||
|
||||
Overview of all possibilities:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<!-- Any property, which is available in the Record (like normal) -->
|
||||
{record.title}
|
||||
{record.uid}
|
||||
{record.pid}
|
||||
|
||||
<!-- Language related properties -->
|
||||
{record.languageId}
|
||||
{record.languageInfo.translationParent}
|
||||
{record.languageInfo.translationSource}
|
||||
|
||||
<!-- The overlaid uid -->
|
||||
{record.overlaidUid}
|
||||
|
||||
<!-- Types are a combination of the table name and the Content Type name. -->
|
||||
<!-- Example for table "tt_content" and CType "textpic": -->
|
||||
|
||||
<!-- "tt_content" (this is basically the table name) -->
|
||||
{record.mainType}
|
||||
|
||||
<!-- "textpic" (this is the CType) -->
|
||||
{record.recordType}
|
||||
|
||||
<!-- "tt_content.textpic" (Combination of mainType and record type, separated by a dot) -->
|
||||
{record.fullType}
|
||||
|
||||
<!-- System related properties -->
|
||||
{record.systemProperties.deleted}
|
||||
{record.systemProperties.disabled}
|
||||
{record.systemProperties.lockedForEditing}
|
||||
{record.systemProperties.createdAt}
|
||||
{record.systemProperties.lastUpdatedAt}
|
||||
{record.systemProperties.publishAt}
|
||||
{record.systemProperties.publishUntil}
|
||||
{record.systemProperties.userGroupRestriction}
|
||||
{record.systemProperties.sorting}
|
||||
{record.systemProperties.description}
|
||||
|
||||
<!-- Computed properties depending on the request context -->
|
||||
{record.computedProperties.versionedUid}
|
||||
{record.computedProperties.localizedUid}
|
||||
{record.computedProperties.requestedOverlayLanguageId}
|
||||
{record.computedProperties.translationSource} <!-- Only for pages, contains the Page model -->
|
||||
|
||||
<!-- Workspace related properties -->
|
||||
{record.versionInfo.workspaceId}
|
||||
{record.versionInfo.liveId}
|
||||
{record.versionInfo.state.name}
|
||||
{record.versionInfo.state.value}
|
||||
{record.versionInfo.stageId}
|
||||
|
||||
.. note::
|
||||
|
||||
The :html:`{record}` object contains only properties relevant for
|
||||
the current record type (e.g. `CType` for :php:`tt_content`). If
|
||||
you need to access properties which are not defined for the record
|
||||
type, which is usually the case for fields of TCA type `passthrough`,
|
||||
the "raw" record can be used by accessing it via :html:`{record.rawRecord}`.
|
||||
Note that those properties are not transformed (:ref:`feature-103581-1723209131`).
|
||||
|
||||
|
||||
Available options
|
||||
------------------
|
||||
|
||||
.. code-block:: typoscript
|
||||
|
||||
The variable that contains the record(s) from a previous data processor,
|
||||
or from a FLUIDTEMPLATE view. Default is :typoscript:`data`.
|
||||
variableName = items
|
||||
|
||||
# the name of the database table of the records. Leave empty to auto-resolve
|
||||
# the table from context.
|
||||
table = tt_content
|
||||
|
||||
# the target variable where the resolved record objects are contained
|
||||
# if empty, "record" or "records" (if multiple records are given) is used.
|
||||
as = myRecords
|
||||
|
||||
.. index:: Fluid, TypoScript, ext:frontend
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-103894-1716544976:
|
||||
|
||||
====================================================================
|
||||
Feature: #103894 - Additional properties for columns in Page Layouts
|
||||
====================================================================
|
||||
|
||||
See :issue:`103894`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Backend Layouts were introduced in TYPO3 v6 in order to customize the view of
|
||||
the :guilabel:`Page` module in TYPO3 backend for pages, but has since grown, also in
|
||||
frontend rendering, to select e.g. Fluid template files via TypoScript for a page,
|
||||
commonly used via :typoscript:`data:pagelayout`.
|
||||
|
||||
In order to use a single source for backend and frontend representation, the
|
||||
definition of a "Backend Layout" or "Page Layout" is expanded to also include
|
||||
more information for a specific content area. The Content Area was previously
|
||||
defined via "name" (for the label in the :guilabel:`Page` module) and "colPos",
|
||||
the numeric database field in which content is grouped in.
|
||||
|
||||
A definition can now optionally also contain a "slideMode" property and an
|
||||
"identifier" property next to each colPos, in order to simplify frontend
|
||||
rendering.
|
||||
|
||||
Whereas "identifier" is a speaking representation for the colPos, such as
|
||||
"main", "sidebar" or "footerArea", the "slideMode" can be set to one of the
|
||||
three options:
|
||||
|
||||
* :typoscript:`slideMode = slide` - if no content is found, check the parent
|
||||
pages for more content
|
||||
* :typoscript:`slideMode = collect` - use all content from this page, and the
|
||||
parent pages as one collection
|
||||
* :typoscript:`slideMode = collectReverse`- same as "collect" but in the
|
||||
opposite order
|
||||
|
||||
With this information added, a new DataProcessor :typoscript:`page-content`
|
||||
(:php:`\TYPO3\CMS\Frontend\DataProcessing\PageContentFetchingProcessor`)
|
||||
is introduced for the frontend rendering,
|
||||
which fetches all content for a page and respecting the settings from the
|
||||
page layout.
|
||||
|
||||
The new data processor allows to manipulate the fetched page content via
|
||||
the PSR-14 :ref:`AfterContentHasBeenFetchedEvent <feature-105638-1732034075>`.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Enriching the backend layout information for each colPos enables a TYPO3
|
||||
integrator to write less TypoScript in order to render content on a page.
|
||||
|
||||
The DataProcessor fetches all content elements from all defined columns with an
|
||||
included "identifier" in the selected backend layout and makes the resolved
|
||||
record objects available in the Fluid template via
|
||||
:html:`{content."myIdentifier".records}`.
|
||||
|
||||
Example of an enriched backend layout definition:
|
||||
|
||||
.. code-block:: typoscript
|
||||
|
||||
mod.web_layout.BackendLayouts {
|
||||
default {
|
||||
title = Default
|
||||
config {
|
||||
backend_layout {
|
||||
colCount = 1
|
||||
rowCount = 1
|
||||
rows {
|
||||
1 {
|
||||
columns {
|
||||
1 {
|
||||
name = Main Content Area
|
||||
colPos = 0
|
||||
identifier = main
|
||||
slideMode = slide
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Example of the frontend output:
|
||||
|
||||
.. code-block:: typoscript
|
||||
|
||||
page = PAGE
|
||||
page.10 = PAGEVIEW
|
||||
page.10.paths.10 = EXT:my_site_package/Tests/Resources/Private/Templates/
|
||||
page.10.dataProcessing.10 = page-content
|
||||
page.10.dataProcessing.10.as = myContent
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<main>
|
||||
<f:for each="{myContent.main.records}" as="record">
|
||||
<f:cObject typoscriptObjectPath="{record.mainType}" table="{record.mainType}" data="{record}"/>
|
||||
</f:for>
|
||||
</main>
|
||||
|
||||
The :html:`f:cObject` ViewHelper above uses the rendering definition of the
|
||||
tt_content table :html:`{record.mainType}` to render the Content Element from
|
||||
the list. The attribute :html:`data` expects the raw database record, which is
|
||||
retrieved from :html:`{record}`.
|
||||
|
||||
.. index:: Backend, Frontend, ext:frontend
|
||||
@@ -0,0 +1,183 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104002-1718273913:
|
||||
|
||||
=============================
|
||||
Feature: #104002 - Schema API
|
||||
=============================
|
||||
|
||||
See :issue:`104002`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
A new Schema API is introduced to access information about TCA structures
|
||||
in a unified way.
|
||||
|
||||
The main goal of this architecture is to reduce direct access to
|
||||
:php:`$GLOBALS['TCA']` after the Bootstrap process is completed.
|
||||
|
||||
The Schema API implements the following design goals:
|
||||
|
||||
#. An object-oriented approach to access common TCA information such as if a
|
||||
database table is localizable or workspace-aware, if it has a "deleted" field
|
||||
("soft-delete"), or other common functionality such as "enableFields" / "enablecolumns",
|
||||
which can be accessed via "Capabilities" within a Schema.
|
||||
|
||||
#. A unified way to access information which "types" a TCA table has available,
|
||||
such as "tt_content", where the "CType" field is the divisor for types, thus,
|
||||
allowing a Schema to have sub-schemata for a TCA Table.
|
||||
|
||||
The API in turn then handles which fields are available for a specific "CType".
|
||||
An example is "tt_content" with type "textpic": The sub-schema "tt_content.textpic"
|
||||
only contains the fields that are registered of that "CType", such as "bodytext",
|
||||
which then knows it is a Rich Text Field (the default column does not have this information),
|
||||
or "image" (a file relation field), but the sub-schema does not contain fields
|
||||
that are irrelevant for this type, such as "assets" (also a file relation field).
|
||||
|
||||
#. An abstracted approach to available TCA field types such as "input" or "select",
|
||||
which also takes information into account, if a select field is a selection of a
|
||||
static list (such as "pages.layout") or if it contains a relation to another
|
||||
schema or field (based on "foreign_table"). Previously, this was evaluated in
|
||||
many places in TYPO3 Core, and can now be reduced.
|
||||
|
||||
Thus, Schema API can now be utilized to determine the :php:`RelationshipType`
|
||||
of a relational field type in a unified way without having to deal with deeply
|
||||
nested arrays.
|
||||
|
||||
#. Information about relations to other database tables or fields. This is
|
||||
especially useful when dealing with Inline elements or category selection fields.
|
||||
|
||||
Schema API can find out, which fields of other schemata are pointing to one-self.
|
||||
Schema API differentiates between an "Active Relation" and a "Passive Relation".
|
||||
An Active Relation is the information that a field such as "pages.media"
|
||||
(a field of type "file") contains a reference to the "sys_file_reference.uid_foreign"
|
||||
field. Active Relations in consequence are connected to a specific field
|
||||
(of type :php:`RelationalFieldTypeInterface`).
|
||||
|
||||
In turn, a "Passive Relation" is the information what other schemata/fields are
|
||||
pointing to a specific table or field.
|
||||
|
||||
A common example of a "Passive Relation" is "sys_workspace_stage":
|
||||
The information stored in :php:`$GLOBALS[TCA][sys_workspace_stage]` does not contain
|
||||
the information that this table is actually used as a reference from the database
|
||||
field `sys_workspace.custom_stages`, the `sys_workspace_stage` Schema now
|
||||
contains this information directly via :php:`TcaSchema->getPassiveRelations()`.
|
||||
This is possible as TcaSchemaFactory is evaluating all TCA information and
|
||||
holistically as a graph. Passive Relations
|
||||
are currently only connected to a Schema, and Active Relations to a Field or
|
||||
a Schema.
|
||||
|
||||
As the Schema API fetches information solely based on the TCA, an Active Relation
|
||||
only points to **possible** references, however, the actual reference
|
||||
(does a record really have a connection to another database table) would
|
||||
require an actual Record instance (a database row) to evaluate this information.
|
||||
|
||||
Relations do not know about the "Type" or "Quantity" (many-to-many etc) as
|
||||
this information is already stored in the Field information. For this reason,
|
||||
the "Relations" currently only contain a flat information structure of the table
|
||||
(and possibly a field) pointing TO another schema name (Active Relation) or
|
||||
FROM another schema name / field (Passive Relation).
|
||||
|
||||
Schema API also parses all available FlexForm data structures in order to
|
||||
resolve relations. As a result, a field of type FlexFormField contains
|
||||
a list of possible "FlexFormSchema" instances, which resolve all fields, sheets
|
||||
and section containers within each data structure.
|
||||
|
||||
#. Once built, the Schema can never be changed. Whereas the TCA could be
|
||||
overridden at runtime, all TCA is now evaluated once and
|
||||
then cached. This is a consequence of working with an object-oriented approach.
|
||||
|
||||
If the TCA is changed after the Bootstrap process is completed,
|
||||
the Schema needs to be rebuilt manually, which TYPO3 Core currently does, for
|
||||
example, in some Functional Testing Scenarios.
|
||||
|
||||
All key objects (Schema, FieldType, Capabilities) are treated as immutable DTOs
|
||||
and never contain cross-references to their parent objects (Sub schemata do not
|
||||
know information about their parent schema, a field does not know which schema
|
||||
it belongs to), so the only entry point is always the :php:`TcaSchemaFactory`
|
||||
object.
|
||||
|
||||
This design allows the API to be fully cacheable at PHP level as a nested tree.
|
||||
|
||||
#. Low-level, not full-fledged but serves as a basis.
|
||||
|
||||
Several API decisions were made in order to let Schema API keep only its
|
||||
original purpose, but can be encapsulated further in other APIs:
|
||||
|
||||
- Schema API is not available during Bootstrap as it needs TCA to be available
|
||||
and fully finished.
|
||||
|
||||
- Schema API does not contain all available TCA properties for each field type.
|
||||
An example is "renderType" for select fields. This information is not relevant
|
||||
when querying records in the frontend, and mainly relevant for FormEngine -
|
||||
it is not generic enough to justify a getter method.
|
||||
|
||||
- Extensibility: custom field types are currently not available
|
||||
until TYPO3 Core as fully migrated to Schema API.
|
||||
|
||||
- User Permissions: Evaluating if a user has access to "tt_content.bodytext"
|
||||
requires information about the currently logged in user, thus it is not part of the
|
||||
Schema API. A "Permission API" should evaluate this information in the
|
||||
future.
|
||||
|
||||
- Available options for a field. As an example, a common scenario is to find out
|
||||
which possible options are available for "pages.backend_layout". In TYPO3 Core
|
||||
an :php:`itemsProcFunc` is connected to that field in TCA. Whether there is an
|
||||
:php:`itemsProcFunc` is stored, but Schema API is not designed to actually
|
||||
execute the itemsProcFunc as it is dependent on various factors evaluated during
|
||||
runtime, such as the page it resides on, user permissions or PageTsConfig
|
||||
overrides.
|
||||
|
||||
Schema API is currently marked as internal, as it might be changed during
|
||||
TYPO3 v13 development, because more parts of TYPO3 will be migrated towards
|
||||
Schema API.
|
||||
|
||||
DataHandler and the Record Factory already utilize Schema API in order to reduce
|
||||
direct access to :php:`$GLOBALS[TCA]`.
|
||||
|
||||
In the future Schema API might be used to evaluate information
|
||||
for Site Configurations, like TCA and FlexForms.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Reading and writing :php:`$GLOBALS[TCA]` within :file:`Configuration/TCA/*`
|
||||
and via TCA Overrides is untouched, as the API is meant for reading the
|
||||
information there in a unified way.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The API can now be used to find out information about TCA fields.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
public function __construct(
|
||||
protected readonly PageRepository $pageRepository,
|
||||
protected readonly TcaSchemaFactory $tcaSchemaFactory
|
||||
) {}
|
||||
|
||||
public function myMethod(string $tableName): void
|
||||
{
|
||||
if (!$this->tcaSchemaFactory->has($tableName)) {
|
||||
// this table is not managed via TYPO3's TCA API
|
||||
return;
|
||||
}
|
||||
$schema = $this->tcaSchemaFactory->get($tableName);
|
||||
|
||||
// Find out if a table is localizable
|
||||
if ($schema->isLocalizable()) {
|
||||
// do something
|
||||
}
|
||||
|
||||
// Find all registered types
|
||||
$types = $schema->getSubSchemata();
|
||||
|
||||
}
|
||||
|
||||
Using the API improves handling for parts such as evaluating :php:`columnsOverrides`,
|
||||
foreign field structures, FlexForm Schema parsing, and evaluating type fields
|
||||
for database fields.
|
||||
|
||||
.. index:: PHP-API, TCA, ext:core
|
||||
@@ -0,0 +1,50 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104020-1718381897:
|
||||
|
||||
====================================================
|
||||
Feature: #104020 - ViewHelper to check feature flags
|
||||
====================================================
|
||||
|
||||
See :issue:`104020`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The `<f:feature>` ViewHelper allows integrators to check for feature flags from within Fluid
|
||||
templates. The ViewHelper follows the same rules as the underlying TYPO3 api, which means
|
||||
that undefined flags will be treated as `false`.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
Basic usage
|
||||
-----------
|
||||
|
||||
::
|
||||
|
||||
<f:feature name="myFeatureFlag">
|
||||
This is being shown if the flag is enabled
|
||||
</f:feature>
|
||||
|
||||
feature / then / else
|
||||
---------------------
|
||||
|
||||
::
|
||||
|
||||
<f:feature name="myFeatureFlag">
|
||||
<f:then>
|
||||
Flag is enabled
|
||||
</f:then>
|
||||
<f:else>
|
||||
Flag is undefined or not enabled
|
||||
</f:else>
|
||||
</f:feature>
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Feature flags can now be checked from within Fluid templates.
|
||||
|
||||
.. index:: Fluid, ext:fluid
|
||||
@@ -0,0 +1,23 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104067-1718188232:
|
||||
|
||||
======================================================
|
||||
Feature: #104067 - Sorting of forms in the form module
|
||||
======================================================
|
||||
|
||||
See :issue:`104067`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The listing of existing forms in the :guilabel:`Form` backend module has
|
||||
been extended to provide sorting functionality.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
It's now possible to sort the existing forms in the :guilabel:`Form`
|
||||
backend module.
|
||||
|
||||
.. index:: Backend, ext:form
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104069-1718551315:
|
||||
|
||||
======================================================================
|
||||
Feature: #104069 - Improved backend notifications display and handling
|
||||
======================================================================
|
||||
|
||||
See :issue:`104069`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The notifications shown on the lower right now have a "Clear all" button to allow the
|
||||
user to clear all notifications with a single click. This button is only displayed when
|
||||
two or more notifications are on screen.
|
||||
|
||||
In case the height of the notification container exceeds the viewport, a scroll bar will
|
||||
allow the user to navigate through the notifications.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Handling of multiple notifications has been improved by allowing to
|
||||
scroll and clear all notifications at once.
|
||||
|
||||
.. index:: Backend, ext:backend
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104085-1718271935:
|
||||
|
||||
===========================================================================
|
||||
Feature: #104085 - Edit specific columns of multiple records in List module
|
||||
===========================================================================
|
||||
|
||||
See :issue:`104085`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Using the "Show columns" button on a record table in the :guilabel:`Web > List`
|
||||
backend module allows to select the columns to be displayed for the
|
||||
corresponding table listing.
|
||||
|
||||
When selecting multiple records, it has already been possible to edit all
|
||||
those records at once, using the "Edit" button in the table header.
|
||||
|
||||
Now, a new button "Edit columns" has been introduced, which additionally
|
||||
allows to access the editing form for the selected records with just the
|
||||
columns of the current selection (based on "Show columns"). This improves
|
||||
the usability when doing mass editing of specific columns.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
It's now possible to edit the columns of multiple records in the
|
||||
:guilabel:`Web > List` backend module, using the new "Edit columns" button.
|
||||
|
||||
.. index:: Backend, ext:backend
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104095-1718283782:
|
||||
|
||||
=============================================================================
|
||||
Feature: #104095 - Edit specific columns of multiple files in Filelist module
|
||||
=============================================================================
|
||||
|
||||
See :issue:`104095`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Using the "Show columns" action in the :guilabel:`File > Filelist`
|
||||
backend module allows to select the columns to be displayed file and
|
||||
folder listing.
|
||||
|
||||
When selecting multiple files, it has already been possible to edit the
|
||||
metadata of all those records at once, using the "Edit Metadata" button
|
||||
above the listing.
|
||||
|
||||
Now, a new button "Edit selected columns" has been introduced, which
|
||||
additionally allows to access the editing form for the selected files
|
||||
with just the columns of the current selection (based on "Show columns").
|
||||
This improves the usability when doing mass editing of specific columns.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
It's now possible to edit selected columns of multiple file metadata in the
|
||||
:guilabel:`File > Filelist` backend module, using the new
|
||||
"Edit selected columns" button.
|
||||
|
||||
.. index:: Backend, ext:filelist
|
||||
@@ -0,0 +1,48 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104114-1719419341:
|
||||
|
||||
=========================================================
|
||||
Feature: #104114 - Command to generate Fluid schema files
|
||||
=========================================================
|
||||
|
||||
See :issue:`104114`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
With Fluid Standalone 2.12, a new implementation of the XSD schema generator has
|
||||
been introduced, which was previously a separate composer package. These XSD files
|
||||
allow IDEs to provide autocompletion for ViewHelper arguments in Fluid templates,
|
||||
provided that they are included in the template by using the xmlns syntax:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<html
|
||||
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
||||
xmlns:my="http://typo3.org/ns/Vendor/MyPackage/ViewHelpers"
|
||||
data-namespace-typo3-fluid="true"
|
||||
>
|
||||
|
||||
A new CLI command has been defined to apply Fluid's new schema generator to TYPO3's
|
||||
Fluid integration. New Fluid APIs are used to find all ViewHelpers that exist in
|
||||
the current project (based on the composer autoloader). Then, TYPO3's configuration
|
||||
is checked for any merged Fluid namespaces (like `f:`, which consists of both
|
||||
Fluid Standalone and EXT:fluid ViewHelpers which in some cases override each other).
|
||||
|
||||
After that consolidation, `*.xsd` files are created in `var/transient/` using another
|
||||
API from Fluid Standalone. These files which will automatically get picked up by
|
||||
supporting IDEs (like PhpStorm) to provide autocompletion in template files.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
To get autocompletion for all available ViewHelpers in supporting IDEs, the following
|
||||
CLI command can be executed in local development environments:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
vendor/bin/typo3 fluid:schema:generate
|
||||
|
||||
.. index:: CLI, Fluid, ext:fluid
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104220-1719409311:
|
||||
|
||||
=================================================================
|
||||
Feature: #104220 - Make parseFunc allowTags and denyTags optional
|
||||
=================================================================
|
||||
|
||||
See :issue:`104220`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Defining the TypoScript properties :typoscript:`allowTags` or
|
||||
:typoscript:`denyTags` for the HTML processing via
|
||||
:typoscript:`stdWrap.parseFunc` is now optional.
|
||||
|
||||
Besides that, it is now possible to use :typoscript:`allowTags = *`.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
By omitting :typoscript:`allowTags` or :typoscript:`denyTags`, the
|
||||
corresponding rendering instructions can be simplified.
|
||||
Security aspects are considered automatically by the HTML sanitizer,
|
||||
unless :typoscript:`htmlSanitize` is disabled explicitly.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
.. code-block:: typoscript
|
||||
|
||||
10 = TEXT
|
||||
10.value = <p><em>Example</em> <u>underlined</u> text</p>
|
||||
10.parseFunc = 1
|
||||
10.parseFunc {
|
||||
allowTags = *
|
||||
denyTags = u
|
||||
}
|
||||
|
||||
The example above allows any tag, except :html:`<u>` which will be encoded.
|
||||
|
||||
.. code-block:: typoscript
|
||||
|
||||
10 = TEXT
|
||||
10.value = <p><em>Example</em> <u>underlined</u> text</p>
|
||||
10.parseFunc = 1
|
||||
10.parseFunc {
|
||||
allowTags = u
|
||||
}
|
||||
|
||||
The example above only allows :html:`<u>` and encodes any other tag.
|
||||
|
||||
.. code-block:: typoscript
|
||||
|
||||
10 = TEXT
|
||||
10.value = <p><em>Example</em> <u>underlined</u> text</p>
|
||||
10.parseFunc = 1
|
||||
10.parseFunc {
|
||||
allowTags = *
|
||||
denyTags = *
|
||||
}
|
||||
|
||||
The example above allows all tags, the new :typoscript:`allowTags = *`
|
||||
takes precedence over :typoscript:`denyTags = *`.
|
||||
|
||||
.. index:: Frontend, TypoScript, ext:core
|
||||
@@ -0,0 +1,49 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104223-1719417803:
|
||||
|
||||
==================================================
|
||||
Feature: #104223 - Update Fluid Standalone to 2.12
|
||||
==================================================
|
||||
|
||||
See :issue:`104223`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Fluid Standalone has been updated to version 2.12. This version adds new capabilities for
|
||||
tab based ViewHelpers and adds the new ViewHelper :html:`f:constant`.
|
||||
|
||||
Also see this :ref:`deprecation document<deprecation-104223-1721383576>` for
|
||||
information on deprecated functionality.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Arbitrary tags with tag based view helpers
|
||||
------------------------------------------
|
||||
|
||||
Tag based view helpers (such as :html:`<f:image />` or :html:`<f:form.*>`) can now
|
||||
receive arbitrary tag attributes which will be appended to the resulting HTML tag,
|
||||
without dedicated registration.
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<f:form.textfield inputmode="tel" />
|
||||
<f:image image="{image}" hidden="hidden" />
|
||||
|
||||
|
||||
New f:constant ViewHelper
|
||||
-------------------------
|
||||
|
||||
A :html:`<f:constant>` ViewHelper has been added to be able to access PHP constants from
|
||||
Fluid templates:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
{f:constant(name: 'PHP_INT_MAX')}
|
||||
{f:constant(name: '\Vendor\Package\Class::CONSTANT')}
|
||||
{f:constant(name: '\Vendor\Package\Enum::CASE')}
|
||||
|
||||
.. index:: Fluid, Frontend, ext:fluid
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-91783-1712426102:
|
||||
|
||||
=========================================================================
|
||||
Feature: #91783 - Allow system maintainer to mute disable_functions error
|
||||
=========================================================================
|
||||
|
||||
See :issue:`91783`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Adds a configuration option to adapt the environment check in the Install Tool
|
||||
for a list of sanctioned :php:`disable_functions`.
|
||||
|
||||
With the new configuration option
|
||||
:php:`$GLOBALS['TYPO3_CONF_VARS']['SYS']['allowedPhpDisableFunctions']`,
|
||||
a system maintainer can add native PHP function names to this list,
|
||||
which are then reported as environment warnings instead of errors.
|
||||
|
||||
Configuration example in :file:`additional.php`:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$GLOBALS['TYPO3_CONF_VARS']['SYS']['allowedPhpDisableFunctions']
|
||||
= ['set_time_limit', 'set_file_buffer'];
|
||||
|
||||
You can also define this in your :file:`settings.php` file manually
|
||||
or via :guilabel:`Admin Tools > Settings > Configure options`.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Native php function names can be added as an array of function names, which will
|
||||
not trigger an error but only a warning, if they can also be found in the php.ini
|
||||
setting :php:`disable_functions`.
|
||||
|
||||
.. index:: Backend, ext:core
|
||||
@@ -0,0 +1,23 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-92009-1718182575:
|
||||
|
||||
=======================================================
|
||||
Feature: #92009 - Provide backend modules in LiveSearch
|
||||
=======================================================
|
||||
|
||||
See :issue:`92009`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The backend LiveSearch is now capable of listing backend modules, a user has
|
||||
access to, offering the possibility of alternative navigation to different
|
||||
parts of the backend.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Backend users now have another possibility to quickly access a backend module.
|
||||
|
||||
.. index:: Backend, ext:backend
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-99203-1704401590:
|
||||
|
||||
===========================================================================
|
||||
Feature: #99203 - Streamline FE/versionNumberInFilename to 'EXT:' resources
|
||||
===========================================================================
|
||||
|
||||
See :issue:`99203`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Local resources are currently not "cache-busted", for example, have no version
|
||||
in URL. TypoScript has no possibility to add the cache buster. When replacing
|
||||
them a new filename must be used (which feels little hacky).
|
||||
|
||||
getText "asset" to cache-bust assets in TypoScript
|
||||
--------------------------------------------------
|
||||
|
||||
.. code-block:: typoscript
|
||||
:caption: EXT:my_extension/Configuration/TypoScript/setup.typoscript
|
||||
:emphasize-lines: 3
|
||||
|
||||
page.20 = TEXT
|
||||
page.20 {
|
||||
value = { asset : EXT:core/Resources/Public/Icons/Extension.svg }
|
||||
insertData = 1
|
||||
}
|
||||
|
||||
.. code-block:: text
|
||||
:caption: Result
|
||||
|
||||
typo3/sysext/core/Resources/Public/Icons/Extension.svg?1709051481
|
||||
|
||||
Cache-busted assets with the :html:`<f:uri.resource>` ViewHelper
|
||||
----------------------------------------------------------------
|
||||
|
||||
.. code-block:: html
|
||||
:caption: EXT:my_extension/Resources/Private/Template/MyTemplate.html
|
||||
:emphasize-lines: 3
|
||||
|
||||
<f:uri.resource
|
||||
path="EXT:core/Resources/Public/Icons/Extension.svg"
|
||||
useCacheBusting="true"
|
||||
/>
|
||||
|
||||
.. code-block:: text
|
||||
:caption: Comparison
|
||||
|
||||
Before: typo3/sysext/core/Resources/Public/Icons/Extension.svg
|
||||
Now: typo3/sysext/core/Resources/Public/Icons/Extension.svg?1709051481
|
||||
|
||||
The ViewHelper argument :html:`useCacheBusting` is enabled by default.
|
||||
|
||||
Depending on :php:`$GLOBALS['TYPO3_CONF_VARS']['FE']['versionNumberInFilename']`
|
||||
the cache buster is applied as query string or embedded in the filename.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Local resources now can have a cache buster to easily replace them without
|
||||
changing the filename.
|
||||
|
||||
.. index:: Fluid, Frontend, ext:frontend
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _important-101621-1718125029:
|
||||
|
||||
=================================================================
|
||||
Important: #101621 - Changed default value for twitter_card field
|
||||
=================================================================
|
||||
|
||||
See :issue:`101621`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The default value of the `twitter_card` field of a page is now an empty string
|
||||
instead of `summary`.
|
||||
|
||||
Meta tag :html:`<meta name="twitter:card">` is only rendered if one of the
|
||||
following fields is filled in,
|
||||
|
||||
- `twitter_title`
|
||||
- `twitter_description`
|
||||
- `twitter_image`
|
||||
- `twitter_card`
|
||||
- `og_title`
|
||||
- `og_description`
|
||||
- `og_image`
|
||||
|
||||
If no twitter card is selected, the fallback value is `summary`.
|
||||
|
||||
.. index:: Frontend, ext:seo
|
||||
@@ -0,0 +1,32 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _important-103485-1718964758:
|
||||
|
||||
===========================================================
|
||||
Important: #103485 - Provide lib.parseFunc via ext:frontend
|
||||
===========================================================
|
||||
|
||||
See :issue:`103485`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The :typoscript:`lib.parseFunc` and :typoscript:`lib.parseFunc_RTE` functions
|
||||
render HTML from Rich Text Fields in TYPO3. Direct interaction with these
|
||||
libraries is now uncommon, but they control the output of the
|
||||
:html:`<f:format.html>` ViewHelper.
|
||||
|
||||
Previously, the libraries were available only through content rendering definitions
|
||||
like fluid_styled_content, the bootstrap_package or your own packages.
|
||||
|
||||
The :html:`<f:format.html>` ViewHelper requires a parseFunc to function and
|
||||
will throw an exception if none is provided. With the shift towards
|
||||
self-contained content elements, also known as content blocks, there is no need
|
||||
to include a separate rendering definition. The frontend provides a base version
|
||||
of the libraries, which are now available in the frontend context.
|
||||
|
||||
The libraries are loaded early in the TypoScript chain, ensuring that all
|
||||
existing overrides continue to work as before, without the need for a basic
|
||||
parseFunc definition.
|
||||
|
||||
.. index:: Frontend, TypoScript, ext:frontend
|
||||
@@ -0,0 +1,48 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _important-103748-1714290385:
|
||||
|
||||
=====================================================
|
||||
Important: #103748 - Reference index rebuild required
|
||||
=====================================================
|
||||
|
||||
See :issue:`103748`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
A series of new columns has been added to the reference index table
|
||||
:sql:`sys_refindex`. This requires a rebuild of the table. All instances
|
||||
must update the reference index when upgrading.
|
||||
|
||||
In TYPO3 v13 the reference index has become more important. Most notably,
|
||||
it is used in the frontend for performance improvements. This requires
|
||||
a valid index and keeping it up-to-date after deployments is mandatory
|
||||
to avoid incorrect data during frontend and backend processing.
|
||||
|
||||
After deployment and initial rebuild, the index is kept up-to-date automatically
|
||||
by the :php:`DataHandler` when changing records in the backend .
|
||||
|
||||
In general, updating the reference index is required when database
|
||||
relations that are defined in TCA change - typically when adding, removing
|
||||
or changing extensions, and after TYPO3 Core updates (also patch level).
|
||||
|
||||
It is strongly recommended to update the reference index after deployments.
|
||||
Note TYPO3 v13 has optimized this operation - a full update is usually much
|
||||
quicker than with previous versions.
|
||||
|
||||
The recommended way to rebuild and fully update the reference index is the CLI
|
||||
command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
bin/typo3 referenceindex:update
|
||||
|
||||
If CLI can not be used, the reference index can be updated in the backend
|
||||
using the "DB check" module in the "typo3/cms-lowlevel" extension. Since
|
||||
the update process may take a while, PHP web processes may time out during
|
||||
this operation, which makes this backend interface suitable for small sized
|
||||
instances only.
|
||||
|
||||
|
||||
.. index:: Database, ext:core
|
||||
@@ -0,0 +1,88 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _important-103915-1716666919:
|
||||
|
||||
=========================================================================
|
||||
Important: #103915 - Adjust database field defaults for "check" TCA types
|
||||
=========================================================================
|
||||
|
||||
See :issue:`103915`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
TYPO3 v13.0 has introduced automatic database field creation for TCA
|
||||
fields configured as type "check" (if not explicitly defined in
|
||||
:file:`ext_tables.sql`), via
|
||||
`https://review.typo3.org/c/Packages/TYPO3.CMS/+/80513`__.
|
||||
|
||||
This conversion applied a :sql:`default 0` to all fields, and did not
|
||||
evaluate the actual TCA definition for the
|
||||
:php:`['config']['default']` setting.
|
||||
|
||||
This bug has been fixed, and the DB schema analyzer will now convert
|
||||
all the following fields to their proper default settings:
|
||||
|
||||
* :sql:`be_users.options` (0->3)
|
||||
* :sql:`sys_file_storage.is_browsable` (0->1)
|
||||
* :sql:`sys_file_storage.is_writable` (0->1)
|
||||
* :sql:`sys_file_storage.is_online` (0->1)
|
||||
* :sql:`sys_file_storage.auto_extract_metadata` (0->1)
|
||||
* :sql:`sys_file_metadata.visible` (0->1)
|
||||
* :sql:`tt_content.sectionIndex` (0->1)
|
||||
* :sql:`tx_styleguide_palette.palette_1_1` (0->1)
|
||||
* :sql:`tx_styleguide_palette.palette_1_3` (0->1)
|
||||
* :sql:`tx_styleguide_valuesdefault.checkbox_1` (0->1)
|
||||
* :sql:`tx_styleguide_valuesdefault.checkbox_2` (0->1)
|
||||
* :sql:`tx_styleguide_valuesdefault.checkbox_3` (0->5)
|
||||
* :sql:`tx_styleguide_valuesdefault.checkbox_4` (0->5)
|
||||
* :sql:`sys_workspace.edit_allow_notificaton_settings` (0->3)
|
||||
* :sql:`sys_workspace.edit_notification_preselection` (0->2)
|
||||
* :sql:`sys_workspace.publish_allow_notificaton_settings` (0->3)
|
||||
* :sql:`sys_workspace.publish_notification_preselection` (0->1)
|
||||
* :sql:`sys_workspace.execute_allow_notificaton_settings` (0->3)
|
||||
* :sql:`sys_workspace.execute_notification_preselection` (0->3)
|
||||
* :sql:`sys_workspace_stage.allow_notificaton_settings` (0->3)
|
||||
* :sql:`sys_workspace_stage.notification_preselection` (0->8)
|
||||
|
||||
All these records, created via :php:`DataHandler` calls, actually
|
||||
evaluate the TCA default for record insertion and do not rely
|
||||
on SQL database field defaults.
|
||||
|
||||
Only records created using the :php:`QueryBuilder` or
|
||||
other "raw" database calls would apply the wrong
|
||||
values.
|
||||
|
||||
An example of this is
|
||||
:php:`TYPO3\CMS\Core\Resource\StorageRepository->createLocalStorage()`
|
||||
which creates a default :file:`fileadmin` record via the :php:`QueryBuilder`
|
||||
and then sets the field :sql:`auto_extract_metadata` to :sql:`0`, instead of `1`
|
||||
as would be expected in the TCA. This would mean YouTube files would not
|
||||
automatically fetch metadata on creation.
|
||||
|
||||
This means, for all custom extension code that
|
||||
|
||||
* removed the column definition in :file:`ext_tables.sql`
|
||||
to enforce automatic database field creation,
|
||||
* *and* did not use the recommended :php:`DataHandler` for
|
||||
record insertion (so, any code that is not executed in the
|
||||
backend context, using :php:`QueryBuilder` or Extbase
|
||||
repository methods),
|
||||
* *and* expects a different default than :sql:`0` for newly
|
||||
created records,
|
||||
* *and* relied on the database field definition default
|
||||
|
||||
this code may have created incorrect database records for versions between
|
||||
TYPO3 v13.0 and 13.2.
|
||||
|
||||
For TYPO3 Core code, this has only affected:
|
||||
|
||||
* Default file storage creation, field :sql:`sys_file_metadata.auto_extract_metadata`
|
||||
* Default backend user creation (admin) property :sql:`be_users.options`
|
||||
|
||||
In these rare case, the database record integrity needs to be
|
||||
checked manually, because there are no automated tools
|
||||
to see if a record has used SQL default values or specifically
|
||||
defined values.
|
||||
|
||||
.. index:: Database, ext:core
|
||||
@@ -0,0 +1,19 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _important-104037-1718098487:
|
||||
|
||||
=====================================================================
|
||||
Important: #104037 - Backend module "Access" renamed to "Permissions"
|
||||
=====================================================================
|
||||
|
||||
See :issue:`104037`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The TYPO3 backend module "Access" has been renamed to "Permissions".
|
||||
|
||||
This accurately reflects the purpose of this module and improves consistency in the
|
||||
TYPO3 backend.
|
||||
|
||||
.. index:: Backend, ext:core
|
||||
@@ -0,0 +1,397 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _important-104153-1718790066:
|
||||
|
||||
==============================================================
|
||||
Important: #104153 - About database error "Row size too large"
|
||||
==============================================================
|
||||
|
||||
See :issue:`104153`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
MySQL and MariaDB database engines sometimes generate a "Row size too large" error
|
||||
when modifying the schema of tables with many columns. This document aims to
|
||||
provide a detailed explanation of this error and presents solutions for TYPO3
|
||||
instance maintainers to fix it.
|
||||
|
||||
Note that TYPO3 Core v13 has implemented measures to mitigate this error in
|
||||
most scenarios. Therefore, instance maintainers typically do not need to
|
||||
be aware of the specific details outlined below.
|
||||
|
||||
|
||||
Preface
|
||||
-------
|
||||
|
||||
Firstly, it is important to recognize that there are two different error messages
|
||||
that appear similar but have distinct root causes and potentially opposite solution
|
||||
strategies. This will be elaborated on later in this document.
|
||||
|
||||
Secondly, we will not cover all possible variations of these errors, but will
|
||||
focus on a subset most relevant to TYPO3. Therefore, later sections of the
|
||||
document are very specific. Correctly following the instructions may already
|
||||
resolve the issue for instances running a different setup.
|
||||
|
||||
The issue is most likely to occur with the database table :sql:`tt_content`, as
|
||||
this table is often extended with many additional columns, increasing the
|
||||
likelihood of encountering the error. This document uses table :sql:`tt_content`
|
||||
in code examples. However, the solution strategies are applicable to other
|
||||
tables as well by adjusting the code examples below.
|
||||
|
||||
Ensure storage engine is 'InnoDB'
|
||||
.................................
|
||||
|
||||
TYPO3 typically utilizes the :sql:`InnoDB` storage engine for tables in
|
||||
MySQL / MariaDB databases. However, instances upgraded from older TYPO3 Core
|
||||
versions might still employ different storage engines for some tables.
|
||||
|
||||
TYPO3 Core provides an automatic migration within
|
||||
:guilabel:`Admin Tools > Maintenance > Analyze Database Structure` and will
|
||||
suggest to migrate all tables to :sql:`InnoDB`.
|
||||
|
||||
You can manually verify the engine currently in use:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
SELECT `TABLE_NAME`,`ENGINE`
|
||||
FROM `information_schema`.`TABLES`
|
||||
WHERE `TABLE_SCHEMA`='my_database'
|
||||
AND `TABLE_NAME`='tt_content';
|
||||
|
||||
Tables *not* using :sql:`InnoDB` should be converted via
|
||||
:guilabel:`Admin Tools > Maintenance > Analyze Database Structure` or manually
|
||||
via SQL:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
USE `my_database`;
|
||||
ALTER TABLE `tt_content` ENGINE=InnoDB;
|
||||
|
||||
Ensure InnoDB row format is 'Dynamic'
|
||||
.....................................
|
||||
|
||||
The :sql:`InnoDB` row format dictates how data is physically stored. The
|
||||
:sql:`Dynamic` row format provides better support for tables with many
|
||||
variable-length columns and has been the default format for some time. However,
|
||||
instances upgraded from older TYPO3 Core versions and older MySQL / MariaDB
|
||||
engines might still use the previous default format :sql:`Compact`.
|
||||
|
||||
TYPO3 Core provides an automatic migration within
|
||||
:guilabel:`Admin Tools > Maintenance > Analyze Database Structure` and will
|
||||
suggest to migrate all tables to :sql:`ROW_FORMAT=DYNAMIC`.
|
||||
|
||||
You can manually verify the row format currently in use:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
SELECT `TABLE_NAME`,`Row_format`
|
||||
FROM `information_schema`.`TABLES`
|
||||
WHERE `TABLE_SCHEMA`='my_database'
|
||||
AND `TABLE_NAME`='tt_content';
|
||||
|
||||
Tables *not* using :sql:`Dynamic` should be converted via
|
||||
:guilabel:`Admin Tools > Maintenance > Analyze Database Structure` or manually
|
||||
via SQL:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
USE 'my_database`;
|
||||
ALTER TABLE `tt_content` ROW_FORMAT=DYNAMIC;
|
||||
|
||||
Database, table and column charset
|
||||
..................................
|
||||
|
||||
The column charset impacts length calculations. This document assumes
|
||||
:sql:`utf8mb4` for columns, aligning with the default TYPO3 setup. Converting
|
||||
an existing instance to :sql:`utf8mb4` can be a complex task depending on the
|
||||
currently used charset and is beyond the scope of this document.
|
||||
|
||||
A key point about :sql:`utf8mb4` is that when dealing with the :sql:`utf8mb4`
|
||||
charset for :sql:`VARCHAR()` columns, storage and index calculations need to be
|
||||
multiplied by four (4). For example, a :sql:`VARCHAR(20)` can take up to eighty
|
||||
(80) *bytes* since each of the twenty (20) *characters* can use up to four (4)
|
||||
*bytes*. In contrast, a :sql:`VARCHAR(20)` in a :sql:`latin1` column will consume
|
||||
only twenty (20) *bytes*, as each *character* is only one byte long.
|
||||
|
||||
The TYPO3 Core may set individual columns to a charset like :sql:`latin1` in the
|
||||
future, which will optimize storage for ASCII-character only columns, but most
|
||||
content-related columns should be :sql:`utf8mb4` to avoid issues with
|
||||
multi-byte characters.
|
||||
|
||||
Note that column types that do not store characters (like :sql:`INT`) do not have
|
||||
a charset. An overview of current charsets can be retrieved:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
# Default charset of the database, new tables use this charset when no
|
||||
# explicit charset is given with a "CREATE TABLE" statement:
|
||||
SELECT `SCHEMA_NAME`, `DEFAULT_CHARACTER_SET_NAME` FROM `INFORMATION_SCHEMA`.`SCHEMATA`
|
||||
WHERE `SCHEMA_NAME`='my_database';
|
||||
|
||||
# Default charset of a table, new columns use this charset when no
|
||||
# explicit charset is given with a "ALTER TABLE" statement:
|
||||
SELECT `table`.`table_name`,`charset`.`character_set_name`
|
||||
FROM `information_schema`.`TABLES` AS `table`,`information_schema`.`COLLATION_CHARACTER_SET_APPLICABILITY` AS `charset`
|
||||
WHERE `charset`.`collation_name`=`table`.`table_collation`
|
||||
AND `table`.`table_schema`='my_database'
|
||||
AND `table`.`table_name`='tt_content';
|
||||
|
||||
# List table columns, their column types with length and selected charsets:
|
||||
SELECT `column_name`,`column_type`,`character_set_name`
|
||||
FROM `information_schema`.`COLUMNS`
|
||||
WHERE `table_schema`='my_database'
|
||||
AND `table_name`='tt_content';
|
||||
|
||||
Ensure innodb_page_size is 16384
|
||||
................................
|
||||
|
||||
Few instances modify the MySQL / MariaDB :sql:`innodb_page_size` system variable,
|
||||
and it is advisable to keep the default value of :sql:`16384`. Verify the
|
||||
current value:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
SHOW variables WHERE `Variable_name`='innodb_page_size';
|
||||
|
||||
|
||||
Row size too large
|
||||
------------------
|
||||
|
||||
This document now assumes that MySQL / MariaDB is used, the table in question
|
||||
uses the :sql:`InnoDB` storage engine with :sql:`Dynamic` row format (please
|
||||
check :guilabel:`Admin Tools > Maintenance > Analyze Database Structure` which
|
||||
provides automatic migrations), :sql:`innodb_page_size` default :sql:`16384` is
|
||||
set, and that a system maintainer is aware of specific column charsets.
|
||||
|
||||
|
||||
Error "Row size too large 65535"
|
||||
--------------------------------
|
||||
|
||||
.. code-block:: plaintext
|
||||
|
||||
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type,
|
||||
not counting BLOBs, is 65535. This includes storage overhead, check the manual. You
|
||||
have to change some columns to TEXT or BLOBs
|
||||
|
||||
Explanation
|
||||
...........
|
||||
|
||||
When altering the database schema of a table, such as adding or increasing the
|
||||
size of a :sql:`VARCHAR` column, the above error might occur.
|
||||
|
||||
Note the statement: "The maximum row size [...] is 65535".
|
||||
|
||||
MySQL / MariaDB impose a global maximum size per table row of 65kB. The combined
|
||||
length of all column types contribute to this limit, except for :sql:`TEXT` and
|
||||
:sql:`BLOB` types, which are stored "off row" where only a "pointer" to the actual
|
||||
storage location counts.
|
||||
|
||||
However, standard :sql:`VARCHAR` fields contribute their full maximum byte length
|
||||
towards this 65kB limit. For instance, a :sql:`VARCHAR(2048)` column with the
|
||||
:sql:`utf8mb4` character set (4 bytes per character) requires 4 * 2048 = 8192 bytes.
|
||||
Therefore, only 65535 - 8192 = 57343 bytes remain available for the storage
|
||||
of all other table columns.
|
||||
|
||||
As another example, consider the query below which creates a table with
|
||||
a :sql:`VARCHAR(16383)` column alongside an :sql:`INT` column:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
# ERROR 1118 (42000): Row size too large. The maximum row size [...] is 65535
|
||||
CREATE TABLE test (c1 varchar(16383), c2 int) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
Let's break down the calculation:
|
||||
|
||||
.. code-block:: plaintext
|
||||
|
||||
varchar 16383 characters = 16383 * 4 bytes = 65532 bytes
|
||||
int = 4 bytes
|
||||
Total: 65532 + 4 = 65536 bytes
|
||||
|
||||
This exceeds the maximum limit by one byte, causing the query to fail.
|
||||
|
||||
Mitigation
|
||||
..........
|
||||
|
||||
The primary strategy to mitigate the 65kB limit is to minimize the use of
|
||||
lengthy :sql:`VARCHAR` columns.
|
||||
|
||||
For instance, in the :sql:`tt_content` table of a default Core instance, there
|
||||
are approximately a dozen :sql:`VARCHAR(255)` columns, totaling about 12kB,
|
||||
alongside smaller :sql:`INT` and similar fields. This leaves ample
|
||||
room for additional custom :sql:`VARCHAR()` columns.
|
||||
|
||||
TYPO3 v13 has introduced improvements in two key areas:
|
||||
|
||||
Firstly, TCA fields with :php:`type='link'` and :php:`type='slug'` have been
|
||||
converted from :sql:`VARCHAR(2048)` (requiring 8kB of row space) to :sql:`TEXT`.
|
||||
The :sql:`tt_content` table was affected by this change in at least one
|
||||
column (:sql:`header_link`). This adjustment provides more space by default for
|
||||
custom columns.
|
||||
|
||||
Additionally, the TYPO3 Core now defaults to using :sql:`TEXT` instead of
|
||||
:sql:`VARCHAR()` for TCA fields with :php:`type='input'` when the TCA property
|
||||
:php:`max` is set to a value greater than :php:`255` and extension authors utilize
|
||||
the :ref:`column auto creation feature <feature-101553-1691166389>`.
|
||||
|
||||
Instances encountering the 65kB limit can consider adjusting fields with these
|
||||
considerations in mind:
|
||||
|
||||
* Priority should be given to reconsidering long :sql:`VARCHAR()` columns first.
|
||||
Changing a single :sql:`utf8mb4` :sql:`VARCHAR(2048)` column to :sql:`TEXT`
|
||||
can free enough space for up to eight (8) :sql:`utf8mb4` :sql:`VARCHAR(255)`
|
||||
columns.
|
||||
|
||||
* Consider reducing the length of :sql:`VARCHAR()` columns. For instance, columns
|
||||
containing database table or column names can be limited to :sql:`VARCHAR(64)`,
|
||||
as MySQL / MariaDB restricts table and column names to a maximum of 64 characters.
|
||||
Similar considerations apply to "short" content fields, such as a column storing
|
||||
an author's name or similar potentially limited length information.
|
||||
|
||||
However, be cautious, as setting :sql:`VARCHAR()` columns to "too short" lengths
|
||||
may impose a different limit, as discussed below.
|
||||
|
||||
* Consider removing entries from :file:`ext_tables.sql` with TYPO3 Core v13: the
|
||||
:ref:`column auto creation feature <feature-101553-1691166389>` generally provides
|
||||
better-defined column definitions and ensures columns stay synchronized with TCA
|
||||
definitions automatically. The TYPO3 Core aims to provide sensible default
|
||||
definitions, often superior to a potentially imprecise definition by extension
|
||||
authors.
|
||||
|
||||
* Note that individual column definitions in :file:`ext_tables.sql` always override
|
||||
TYPO3 Core v13's column auto creation feature. In rare cases where TYPO3
|
||||
Core's definition is inappropriate, extension authors can always override these
|
||||
details.
|
||||
|
||||
* Note :sql:`utf8mb4` :sql:`VARCHAR(255)` and :sql:`TINYTEXT` are *not* the same:
|
||||
a :sql:`VARCHAR(255)` size limit is 255 *characters*, while a :sql:`TINYTEXT`
|
||||
is 255 *bytes*. The proper substitution for a (4 bytes per character) :sql:`utf8mb4`
|
||||
:sql:`VARCHAR(255)` field is :sql:`TEXT`, which allows for 65535 bytes.
|
||||
|
||||
* :sql:`TEXT` *may* negatively impact performance as it forces additional
|
||||
Input/Output operations in the database. This is typically not a significant issue
|
||||
with standard TYPO3 queries, as various other operations in TYPO3 have a greater
|
||||
impact on overall performance. However, indiscriminately changing all fields from
|
||||
:sql:`VARCHAR()` to :sql:`TEXT` or similar is *not* advisable.
|
||||
|
||||
* Be mindful of indices. When :sql:`VARCHAR()` columns that are part of an index
|
||||
are changed to :sql:`TEXT` or similar, these indexes may require adjustment.
|
||||
Ensure they are properly restricted in length to avoid a "Specified key was too long"
|
||||
error. The :sql:`InnoDB` key length limit with row format :sql:`Dynamic` is 3072
|
||||
*bytes* (not *characters*). In general, indexes on :sql:`VARCHAR()` and all other
|
||||
"longish" columns should be set with care and only if really needed since long
|
||||
indexes can negatively impact database performance as well, especially when a
|
||||
table has many write operations in production.
|
||||
|
||||
|
||||
Error "Row size too large (> 8126)"
|
||||
-----------------------------------
|
||||
|
||||
.. code-block:: plaintext
|
||||
|
||||
ERROR 1118 (42000): Row size too large (> 8126). Changing some columns to TEXT
|
||||
or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.
|
||||
|
||||
Sometimes there is also an error similar to this in MySQL / MariaDB logs:
|
||||
|
||||
.. code-block:: plaintext
|
||||
|
||||
[Warning] InnoDB: Cannot add field col1 in table db1.tab because after adding it,
|
||||
the row size is 8478 which is greater than maximum allowed size (8126) for a record
|
||||
on index leaf page.
|
||||
|
||||
Explanation
|
||||
...........
|
||||
|
||||
This error may occur when adding or updating table rows, not only when altering table
|
||||
schema.
|
||||
|
||||
Note the statement: "Row size too large (> 8126)". This differs from the
|
||||
previous error message. This error is *not* about a general row size limit of
|
||||
65535 bytes, but a limit imposed by InnoDB tables.
|
||||
|
||||
The root cause is that InnoDB has a maximum row size equivalent to half of the
|
||||
:sql:`innodb_page_size` system variable value of 16384 bytes, which is 8192 bytes.
|
||||
|
||||
InnoDB mitigates this by storing certain variable-length columns on "overflow pages".
|
||||
The decision regarding which columns are *actually* stored on overflow pages is made
|
||||
dynamically when adding or changing rows. This is why the error can be raised at
|
||||
runtime and not only when altering the schema. Additionally, it makes accurately
|
||||
predicting whether the error will occur challenging. Furthermore, not all variable-length
|
||||
columns *can* be stored on overflow pages. This is why the error can be raised when
|
||||
altering table schema.
|
||||
|
||||
Variable-length columns of type :sql:`TEXT` and :sql:`BLOB` can always be stored on
|
||||
overflow pages, thus minimally impacting the main data page limit of 8192 bytes.
|
||||
However, :sql:`VARCHAR` columns can only be stored on overflow pages if their maximum
|
||||
length exceeds 255 *bytes*. Therefore, an unexpected solution to the "Row size too
|
||||
large 8192" error in many cases is to increase the length of some variable-length
|
||||
columns, enabling InnoDB to store them on overflow pages.
|
||||
|
||||
Mitigation
|
||||
..........
|
||||
|
||||
TYPO3 Core v13 has modified several default columns to mitigate the issue for instances
|
||||
with many custom columns. The TYPO3 Core maintainers expect this issue to occur
|
||||
infrequently in practice.
|
||||
|
||||
Instances encountering the 8192 bytes limit can consider adjusting fields with these
|
||||
considerations in mind:
|
||||
|
||||
* The calculation determining if a column can be stored on overflow pages is based
|
||||
on a minimum of 256 *bytes*, not *characters*. A typical :sql:`utf8mb4`
|
||||
:sql:`VARCHAR(255)` equates to 1020 bytes, which *can* be stored on overflow pages.
|
||||
Changing such fields makes no difference.
|
||||
|
||||
* Changing a :sql:`utf8mb4` :sql:`VARCHAR(63)` (or smaller) to :sql:`VARCHAR(64)`
|
||||
(64 characters utf8mb4 = 256 bytes) allows this column to be stored on overflow
|
||||
pages and *does* make a difference.
|
||||
|
||||
* Changing a :sql:`utf8mb4` :sql:`VARCHAR(63)` (or smaller) to :sql:`TINYTEXT`
|
||||
should allow this column to be stored on overflow pages as well. However, this
|
||||
may not be the optimal solution due to potential performance penalties, as
|
||||
discussed earlier. Similarly, indiscriminately increasing the length of
|
||||
multiple variable-length columns is not advisable. Columns should ideally be
|
||||
kept as small as possible, only exceeding the 255-byte limit or converting to
|
||||
:sql:`TEXT` types if absolutely necessary. Also, refer to the note on indexes
|
||||
above when single columns are part of indexes.
|
||||
|
||||
* Columns using :sql:`utf8mb4` that are smaller or equal to :sql:`VARCHAR(63)`
|
||||
and only store ASCII characters can be downsized by changing the charset to
|
||||
:sql:`latin1`. For instance, a :sql:`VARCHAR(60)` column occupies 4 * 60 = 240
|
||||
bytes in row size, but only 60 bytes when using the :sql:`latin1` charset.
|
||||
Currently, TYPO3 Core does not interpret charset definitions for individual
|
||||
columns from :sql:`ext_tables.sql`. The Core Team anticipates implementing
|
||||
this feature in the future.
|
||||
|
||||
* Note that increasing the length of :sql:`VARCHAR` columns can potentially
|
||||
conflict with the 65kB limit mentioned earlier. This is another reason to
|
||||
avoid indiscriminately increasing the length of variable-length columns.
|
||||
|
||||
|
||||
Further reading
|
||||
---------------
|
||||
|
||||
This document is based on information from database vendors and other sites
|
||||
found online. The following links may provide further insights:
|
||||
|
||||
* `(MariaDB) InnoDB Row Formats Overview <https://mariadb.com/kb/en/innodb-row-formats-overview/>`_
|
||||
* `(MariaDB) Troubleshooting Row Size Too Large Errors with InnoDB <https://mariadb.com/kb/en/troubleshooting-row-size-too-large-errors-with-innodb/>`_
|
||||
* `(Contao) MySQL Row size too large <https://github.com/contao/contao/issues/4159>`_
|
||||
|
||||
|
||||
Final words
|
||||
-----------
|
||||
|
||||
Navigating the two limits in MySQL / MariaDB requires a deep understanding of
|
||||
database engine internals to manage them effectively. The TYPO3 Core Team is
|
||||
confident that version 13 has effectively mitigated the issue, ensuring that
|
||||
typical instances will rarely encounter it. We trust this document remains
|
||||
helpful and welcome any feedback in case something crucial has been overlooked.
|
||||
|
||||
|
||||
.. index:: Database, ext:core
|
||||
@@ -0,0 +1,52 @@
|
||||
:template: changelogOverview.html
|
||||
.. include:: /Includes.rst.txt
|
||||
.. _changelog-13-2:
|
||||
|
||||
============
|
||||
13.2 Changes
|
||||
============
|
||||
|
||||
.. contents:: Table of contents
|
||||
:local:
|
||||
:depth: 1
|
||||
|
||||
Breaking Changes
|
||||
================
|
||||
|
||||
None since TYPO3 v13.0 release.
|
||||
|
||||
.. attention::
|
||||
|
||||
After TYPO3 v13.0, only new functionality with a solid migration path
|
||||
can be added on top, aiming for as few as possible breaking changes
|
||||
after the initial v13.0 release on the way to LTS.
|
||||
|
||||
Features
|
||||
========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:titlesonly:
|
||||
:glob:
|
||||
|
||||
Feature-*
|
||||
|
||||
Deprecation
|
||||
===========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:titlesonly:
|
||||
:glob:
|
||||
|
||||
Deprecation-*
|
||||
|
||||
Important
|
||||
=========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:titlesonly:
|
||||
:glob:
|
||||
|
||||
Important-*
|
||||
Reference in New Issue
Block a user