TYPO3 v15 dev-main snapshot ()
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-101559-1721761906:
|
||||
|
||||
==========================================================
|
||||
Deprecation: #101559 - Extbase uses ext:core ViewInterface
|
||||
==========================================================
|
||||
|
||||
See :issue:`101559`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The default view of ext:extbase now returns a view that implements
|
||||
:php:`\TYPO3\CMS\Core\View\ViewInterface` and not only
|
||||
:php:`\TYPO3Fluid\Fluid\View\ViewInterface` anymore. This allows
|
||||
implementing any view that implements :php-short:`\TYPO3\CMS\Core\View\ViewInterface`,
|
||||
and frees the direct dependency to Fluid.
|
||||
|
||||
The default return object is an instance of
|
||||
:php:`\TYPO3\CMS\Fluid\View\FluidViewAdapter` which implements all
|
||||
special methods tailored for Fluid. Extbase controllers should
|
||||
check for instance of this object before calling these methods,
|
||||
especially:
|
||||
|
||||
* :php:`getRenderingContext()`
|
||||
* :php:`setRenderingContext()`
|
||||
* :php:`renderSection()`
|
||||
* :php:`renderPartial()`
|
||||
|
||||
Method calls not being part of :php-short:`\TYPO3\CMS\Core\View\ViewInterface` or the above
|
||||
listed method names have been marked as deprecated and will be removed in TYPO3 v14.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Extbase controllers that extend :php-short:`\TYPO3\CMS\Extbase\Mvc\Controller\ActionController`
|
||||
and call methods not part of :php-short:`\TYPO3\CMS\Core\View\ViewInterface`, should
|
||||
test for :php:`$view instanceof FluidViewAdapter` before calling
|
||||
:php:`getRenderingContext()`, :php:`setRenderingContext()`, php:`renderSection()`
|
||||
and :php:`renderPartial()`.
|
||||
|
||||
All other Fluid related methods called on :php:`$view` have been marked as
|
||||
deprecated and will log a deprecation level error message.
|
||||
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
Instances with Extbase based extensions that call :php:`$view` methods without
|
||||
testing for :php-short:`\TYPO3\CMS\Fluid\View\FluidViewAdapter`.
|
||||
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
Methods on "old" Fluid instances were wrapper methods for
|
||||
:php-short:`\TYPO3\CMS\Fluid\Core\Rendering\RenderingContext`. Controllers
|
||||
should call :php:`$view->getRenderingContext()`
|
||||
to perform operations instead.
|
||||
|
||||
|
||||
.. index:: Fluid, PHP-API, NotScanned, ext:extbase
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-102422-1700563266:
|
||||
|
||||
============================================================================================
|
||||
Deprecation: #102422 - TypoScriptFrontendController->addCacheTags() and ->getPageCacheTags()
|
||||
============================================================================================
|
||||
|
||||
See :issue:`102422`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The methods :php:`\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->addCacheTags()` and
|
||||
:php:`\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->getPageCacheTags()`
|
||||
have been marked as deprecated.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Calling the methods
|
||||
:php-short:`\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->addCacheTags()`
|
||||
and
|
||||
:php-short:`\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->getPageCacheTags()`
|
||||
will trigger a PHP deprecation warning.
|
||||
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
TYPO3 installations calling
|
||||
:php-short:`\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->addCacheTags()`
|
||||
or
|
||||
:php-short:`\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->getPageCacheTags()`.
|
||||
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// Before
|
||||
$GLOBALS['TSFE']->addCacheTags([
|
||||
'tx_myextension_mytable_123',
|
||||
'tx_myextension_mytable_456'
|
||||
]);
|
||||
|
||||
// After
|
||||
use TYPO3\CMS\Core\Cache\CacheTag;
|
||||
|
||||
$request->getAttribute('frontend.cache.collector')->addCacheTags(
|
||||
new CacheTag('tx_myextension_mytable_123', 3600),
|
||||
new CacheTag('tx_myextension_mytable_456', 3600)
|
||||
);
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// Before
|
||||
$GLOBALS['TSFE']->getPageCacheTags();
|
||||
|
||||
// After
|
||||
$request->getAttribute('frontend.cache.collector')->getCacheTags();
|
||||
|
||||
.. index:: PHP-API, FullyScanned, ext:core
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-102821-1709843835:
|
||||
|
||||
================================================================
|
||||
Deprecation: #102821 - ExtensionManagementUtility::addPItoST43()
|
||||
================================================================
|
||||
|
||||
See :issue:`102821`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The method :php:`\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPItoST43()`
|
||||
has been marked as deprecated in TYPO3 v13 and will be removed with TYPO3 v14.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Using the :php:`ExtensionManagementUtility::addPItoST43()` will raise a deprecation
|
||||
level log entry and a fatal error in TYPO3 v14.
|
||||
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
Extensions using :php:`ExtensionManagementUtility::addPItoST43()` are affected:
|
||||
Using :php:`ExtensionManagementUtility::addPItoST43()` triggers a deprecation level log message.
|
||||
The extension scanner will find usages of :php:`ExtensionManagementUtility::addPItoST43()` as strong match.
|
||||
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// Before:
|
||||
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPItoST43('my_extkey', '', '_pi1');
|
||||
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScript(
|
||||
'tx_myextkey',
|
||||
'setup',
|
||||
'plugin.tx_myextkey_pi1.userFunc = MY\MyExtkey\Plugins\Plugin->main'
|
||||
);
|
||||
|
||||
// After:
|
||||
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScript(
|
||||
'my_extkey',
|
||||
'setup',
|
||||
'plugin.tx_myextkey_pi1 = USER_INT
|
||||
plugin.tx_myextkey_pi1.userFunc = MY\MyExtkey\Plugins\Plugin->main'
|
||||
);
|
||||
|
||||
.. index:: LocalConfiguration, PHP-API, FullyScanned, ext:core
|
||||
@@ -0,0 +1,70 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-104223-1721383576:
|
||||
|
||||
===============================================
|
||||
Deprecation: #104223 - Fluid standalone methods
|
||||
===============================================
|
||||
|
||||
See :issue:`104223`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Some methods in Fluid standalone v2 have been marked as deprecated:
|
||||
|
||||
* :php:`\TYPO3Fluid\Fluid\Core\ViewHelper\AbstractTagBasedViewHelper->registerUniversalTagAttributes()`
|
||||
* :php:`\TYPO3Fluid\Fluid\Core\ViewHelper\AbstractTagBasedViewHelper->registerTagAttribute()`
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Calling these methods is discouraged. They will log a deprecation level
|
||||
error when used with Fluid standalone v4.
|
||||
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
Instances with extensions calling above methods.
|
||||
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
registerUniversalTagAttributes()
|
||||
--------------------------------
|
||||
|
||||
Within tag based ViewHelpers, calls to :php:`registerUniversalTagAttributes()` should be removed.
|
||||
This method has been marked as :php:`@deprecated` with Fluid standalone 2.12, will
|
||||
log a deprecation level error with Fluid standalone v4, and will be removed with v5.
|
||||
|
||||
When removing the call, attributes registered by the call are now available in
|
||||
:php:`$this->additionalArguments`, and no longer in :php:`$this->arguments`. This *may* need
|
||||
adaption within single ViewHelpers, *if* they handle such attributes on their own. For example,
|
||||
the common ViewHelper :html:`f:image` was affected within the TYPO3 Core. The following attributes
|
||||
may need attention when removing :php:`registerUniversalTagAttributes()`: :html:`class`, :html:`dir`,
|
||||
:html:`id`, :html:`lang`, :html:`style`, :html:`title`, :html:`accesskey`, :html:`tabindex`,
|
||||
:html:`onclick`.
|
||||
|
||||
registerTagAttribute()
|
||||
----------------------
|
||||
|
||||
Within tag based ViewHelpers, calls to :php:`registerTagAttribute()` should be removed.
|
||||
This method has been marked as :php:`@deprecated` with Fluid standalone 2.12, will
|
||||
log a deprecation level error with Fluid standalone v4, and will be removed with v5.
|
||||
|
||||
The call be often simply removed since arbitrary attributes not specifically registered
|
||||
are just added as-is by :php:`\TYPO3Fluid\Fluid\Core\ViewHelper\AbstractTagBasedViewHelper`.
|
||||
This only needs attention
|
||||
if single view helpers deal with such attributes within the :php:`render()` method:
|
||||
When removing the call, those arguments are no longer available in :php:`$this->arguments`,
|
||||
but in :php:`$this->additionalArguments`. Additional attention is needed with
|
||||
attributes registered with type :php:`boolean`: Those usually have some handling
|
||||
within :php:`render()`. To stay compatible, it can be helpful to not simply
|
||||
remove the :php:`registerTagAttribute()` call, but to turn it into a call to
|
||||
:php:`registerArgument()`.
|
||||
|
||||
|
||||
.. index:: Fluid, PHP-API, FullyScanned, ext:fluid
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-104304-1720084447:
|
||||
|
||||
===============================================================
|
||||
Deprecation: #104304 - BackendUtility::getTcaFieldConfiguration
|
||||
===============================================================
|
||||
|
||||
See :issue:`104304`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The method :php:`\TYPO3\CMS\Backend\Utility\BackendUtility::getTcaFieldConfiguration` was introduced back
|
||||
in 2010 to add a simple abstraction to access "TCA" definitions of a field.
|
||||
|
||||
However, apart from the set up that it is not part of a flexible API without
|
||||
knowing the context, it was used seldom in TYPO3 Core.
|
||||
|
||||
The method has now been deprecated, as one could and can easily write the same
|
||||
PHP code with :php:`$GLOBALS['TCA']` in mind already (which the TYPO3 Core already did
|
||||
in several other places).
|
||||
|
||||
Now that Schema API was introduced, the last parts have been migrated to use
|
||||
the new API.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Calling the PHP method :php:`BackendUtility::getTcaFieldConfiguration` will
|
||||
trigger a PHP deprecation warning.
|
||||
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
TYPO3 installations with custom extensions using this method.
|
||||
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
Either access :php:`$GLOBALS['TCA']` directly (in order to support TYPO3 v12 and TYPO3 v13),
|
||||
or migrate to the new Schema API:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
public function __construct(
|
||||
private readonly TcaSchemaFactory $tcaSchemaFactory
|
||||
) {}
|
||||
|
||||
private function getFieldConfiguration(string $table, string $fieldName): array
|
||||
{
|
||||
return $this->tcaSchemaFactory
|
||||
->get($table)
|
||||
->getField($fieldName)
|
||||
->getConfiguration();
|
||||
}
|
||||
|
||||
.. index:: PHP-API, TCA, FullyScanned, ext:backend
|
||||
@@ -0,0 +1,53 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-104325-1720298173:
|
||||
|
||||
=====================================================
|
||||
Deprecation: #104325 - DiffUtility->makeDiffDisplay()
|
||||
=====================================================
|
||||
|
||||
See :issue:`104325`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Method :php:`\TYPO3\CMS\Core\Utility\DiffUtility->makeDiffDisplay()`
|
||||
and class property :php:`DiffUtility->stripTags` have been
|
||||
deprecated in favor of new method :php:`DiffUtility->diff()`.
|
||||
The new method no longer applies :php:`strip_tags()` to the input strings.
|
||||
|
||||
This change makes class :php-short:`\TYPO3\CMS\Core\Utility\DiffUtility` stateless: Property
|
||||
:php:`$stripTags` will vanish in v14.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Using method :php:`DiffUtility->makeDiffDisplay()` will trigger a
|
||||
deprecation level error message.
|
||||
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
Instances with extensions calling :php:`DiffUtility->makeDiffDisplay()`.
|
||||
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
If :php:`DiffUtility->stripTags` *is not* explicitly set to false, a typical
|
||||
migration looks like this:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// before
|
||||
$diffUtility->DiffUtility->makeDiffDisplay($from, $to);
|
||||
|
||||
// after
|
||||
$diffUtility->DiffUtility->diff(strip_tags($from), stripTags($to));
|
||||
|
||||
If :php:`DiffUtility->stripTags = false` is set before calling
|
||||
:php:`DiffUtility->makeDiffDisplay()`, method :php:`diff()` can be called
|
||||
as before, and :php:`DiffUtility->stripTags = false` can be removed.
|
||||
|
||||
.. index:: PHP-API, FullyScanned, ext:core
|
||||
@@ -0,0 +1,42 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-104463-1721754926:
|
||||
|
||||
========================================================
|
||||
Deprecation: #104463 - Fluid standalone overrideArgument
|
||||
========================================================
|
||||
|
||||
See :issue:`104463`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Fluid standalone method :php:`\TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper->overrideArgument()`
|
||||
has been marked as deprecated.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Using :php:`overrideArgument()` in ViewHelpers logs a deprecation level error message in Fluid standalone v4,
|
||||
and will be removed with Fluid standalone v5. The method continues to work without deprecation level
|
||||
error message in Fluid standalone v2.
|
||||
|
||||
With Fluid standalone v2.14, :php:`registerArgument()` no longer throws an exception if an
|
||||
argument is already registered. This allows to override existing arguments transparently
|
||||
without using :php:`overrideArgument()`.
|
||||
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
Instances with custom ViewHelpers using :php:`overrideArgument()` are affected.
|
||||
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
Update `typo3fluid/fluid` to at least 2.14 and use :php:`registerArgument()`.
|
||||
|
||||
|
||||
.. index:: PHP-API, FullyScanned, ext:fluid
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-104607-1723556132:
|
||||
|
||||
==================================================================
|
||||
Deprecation: #104607 - BackendUserAuthentication:returnWebmounts()
|
||||
==================================================================
|
||||
|
||||
See :issue:`104607`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Method :php:`\TYPO3\CMS\Core\Authentication\BackendUserAuthentication::returnWebmounts()` has
|
||||
been marked as deprecated and will be removed with TYPO3 v14.
|
||||
|
||||
Method :php:`BackendUserAuthentication::getWebmounts()` was
|
||||
introduced as substitution. It returns a unique list of integer uids
|
||||
instead of a list of strings, which is more type safe.
|
||||
Superfluous calls to array_unique() can be removed since the uniqueness
|
||||
is now guaranteed by BackendUserAuthentication::getWebmounts().
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Calling :php:`BackendUserAuthentication::returnWebmounts()` will trigger a PHP
|
||||
deprecation warning.
|
||||
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
All installations using :php:`BackendUserAuthentication::returnWebmounts()`
|
||||
are affected.
|
||||
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
Existing calls to :php:`BackendUserAuthentication::returnWebmounts()` should
|
||||
be replaced by :php:`BackendUserAuthentication::getWebmounts()`.
|
||||
|
||||
If third party extensions convert the previous result array from an array of
|
||||
strings to an array of integers, this can be skipped. In addition
|
||||
superfluous calls to array_unique() can be removed since the uniqueness
|
||||
is now guaranteed by BackendUserAuthentication::getWebmounts().
|
||||
|
||||
.. index:: PHP-API, TCA, FullyScanned, ext:core
|
||||
@@ -0,0 +1,93 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-104662-1724058079:
|
||||
|
||||
===============================================
|
||||
Deprecation: #104662 - BackendUtility thumbCode
|
||||
===============================================
|
||||
|
||||
See :issue:`104662`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The method :php:`\TYPO3\CMS\Backend\Utility\BackendUtility::thumbCode()` has been deprecated since the
|
||||
method is no longer used in TYPO3 anymore. Additionally, due to multiple changes
|
||||
to file processing over the years, e.g. introducing of FAL, the method's
|
||||
signature changed a couple of times leading to a couple of method arguments
|
||||
are being unused, which is quite a bad API.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Calling the PHP method :php:`BackendUtility::thumbCode()` will
|
||||
trigger a PHP deprecation warning.
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
TYPO3 installations with custom extensions using this method. The extension
|
||||
scanner will report any usage as strong match.
|
||||
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
Remove any usage of this method. In case you currently rely on the
|
||||
functionality, you can copy it to your custom extension. However, you might
|
||||
want to consider refactoring the corresponding code places.
|
||||
|
||||
The method basically resolved given :php-short:`\TYPO3\CMS\Core\Resource\FileReference` objects. In case
|
||||
a file could not be resolved, a special icon has been rendered. Otherwise,
|
||||
the cropping configuration has been applied and the file's :php:`process()`
|
||||
has been called to get the thumbnail, which has been wrapped in corresponding
|
||||
thumbnail markup. This might has been extended to also open the information
|
||||
modal on click.
|
||||
|
||||
This means the relevant parts are:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// Get file references
|
||||
$fileReferences = BackendUtility:resolveFileReferences($table, $field, $row);
|
||||
|
||||
// Check for existence of the file
|
||||
$fileReference->getOriginalFile()->isMissing()
|
||||
|
||||
// Render special icon if missing
|
||||
$iconFactory
|
||||
->getIcon('mimetypes-other-other', IconSize::MEDIUM, 'overlay-missing')
|
||||
->setTitle(static::getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:warning.file_missing') . ' ' . $fileObject->getName())
|
||||
->render()
|
||||
|
||||
// Process file with cropping configuration if not missing
|
||||
$fileReference->getOriginalFile()->process(
|
||||
ProcessedFile::CONTEXT_IMAGEPREVIEW,// ProcessedFile::CONTEXT_IMAGECROPSCALEMASK if cropArea is defined
|
||||
[
|
||||
'width' => '...',
|
||||
'height' => '...',
|
||||
'crop' // If cropArea is defined
|
||||
]
|
||||
)
|
||||
|
||||
// Use cropped file and create <img> tag
|
||||
<img src="' . $fileReference->getOriginalFile()->process()->getPublicUrl() . '"/>
|
||||
|
||||
// Wrap the info popup via <a> around the thumbnail
|
||||
<a href="#" data-dispatch-action="TYPO3.InfoWindow.showItem" data-dispatch-args-list="_FILE,' . (int)$fileReference->getOriginalFile()->getUid() . '">
|
||||
|
||||
|
||||
Example of the HTML markup for a thumbnail:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<div class="preview-thumbnails" style="--preview-thumbnails-size: 64px">
|
||||
<div class="preview-thumbnails-element">
|
||||
<div class="preview-thumbnails-element-image">
|
||||
<img src="' . $fileReference->getOriginalFile()->process()->getPublicUrl() . '" width="64px" height="64px" alt="' . $fileReference->getAlternative() ?: $fileReference->getName() . '" loading="lazy"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
.. index:: PHP-API, FullyScanned, ext:backend
|
||||
@@ -0,0 +1,94 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-104684-1724258020:
|
||||
|
||||
===========================================================
|
||||
Deprecation: #104684 - Fluid RenderingContext->getRequest()
|
||||
===========================================================
|
||||
|
||||
See :issue:`104684`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The following methods have been marked as deprecated in TYPO3 v13 and will
|
||||
be removed with TYPO3 v14:
|
||||
|
||||
* :php:`\TYPO3\CMS\Fluid\Core\Rendering\RenderingContext->setRequest()`
|
||||
* :php:`\TYPO3\CMS\Fluid\Core\Rendering\RenderingContext->getRequest()`
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Calling above methods triggers a deprecation level log entry in TYPO3 v13 and
|
||||
will trigger a fatal PHP error with TYPO3 v14.
|
||||
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
:php:`RenderingContext->getRequest()` is a relatively common call in custom
|
||||
view helpers. Instances with extensions that deliver custom view helpers may
|
||||
be affected. The extension scanner is *not* configured to find potential
|
||||
places since the method names are common and would lead to too many false
|
||||
positives.
|
||||
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
Class :php:`\TYPO3\CMS\Fluid\Core\Rendering\RenderingContext` of the Core
|
||||
extension Fluid extends class :php:`\TYPO3Fluid\Fluid\Core\Rendering\RenderingContext`
|
||||
of Fluid standalone and adds the methods :php:`setRequest()` and :php:`getRequest()`.
|
||||
These methods are however not part of :php:`\TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface`.
|
||||
|
||||
Fluid standalone will not add these methods, since the view of this library should
|
||||
stay free from direct PSR-7 :php-short:`\Psr\Http\Message\ServerRequestInterface`
|
||||
dependencies. Having those
|
||||
methods in ext:fluid :php-short:`\TYPO3\CMS\Fluid\Core\Rendering\RenderingContext`
|
||||
however collides with :php-short:`\TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface`,
|
||||
which is type hinted in Fluid view helper method signatures.
|
||||
|
||||
Fluid standalone instead added three methods to handle arbitrary additional data
|
||||
in :php-short:`\TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface`:
|
||||
:php:`setAttribute()`, :php:`hasAttribute()`
|
||||
and :php:`getAttribute()`. Those should be used instead.
|
||||
|
||||
A typical usage in a view helper before:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
/** @var \TYPO3Fluid\Fluid\Core\Rendering\RenderingContext $renderingContext */
|
||||
$renderingContext = $this->renderingContext;
|
||||
$request = $renderingContext->getRequest();
|
||||
|
||||
After:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// use Psr\Http\Message\ServerRequestInterface
|
||||
|
||||
$request = null;
|
||||
if ($renderingContext->hasAttribute(ServerRequestInterface::class)) {
|
||||
$request = $renderingContext->getAttribute(ServerRequestInterface::class);
|
||||
}
|
||||
|
||||
To stay compatible to previous TYPO3 versions while avoiding deprecation notices,
|
||||
the following code can be used:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// use Psr\Http\Message\ServerRequestInterface
|
||||
|
||||
if (
|
||||
method_exists($renderingContext, 'getAttribute') &&
|
||||
method_exists($renderingContext, 'hasAttribute') &&
|
||||
$renderingContext->hasAttribute(ServerRequestInterface::class)
|
||||
) {
|
||||
$request = $renderingContext->getAttribute(ServerRequestInterface::class);
|
||||
} else {
|
||||
$request = $renderingContext->getRequest();
|
||||
}
|
||||
|
||||
.. index:: Fluid, PHP-API, NotScanned, ext:fluid
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-104764-1724851918:
|
||||
|
||||
=====================================================================
|
||||
Deprecation: #104764 - Fluid TemplatePaths->fillDefaultsByPackageName
|
||||
=====================================================================
|
||||
|
||||
See :issue:`104764`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Method :php:`\TYPO3\CMS\Fluid\View\TemplatePaths->fillDefaultsByPackageName()`
|
||||
has been marked as deprecated in TYPO3 v13 and will be removed in TYPO3 v14.
|
||||
|
||||
Fluid template paths should be set directly using the methods
|
||||
:php:`setTemplateRootPaths()`, :php:`setLayoutRootPaths()` and
|
||||
:php:`setPartialRootPaths()`, or - even better - be handled by
|
||||
:php:`ViewFactoryInterface`, which comes as new feature in TYPO3 v13.
|
||||
|
||||
See :ref:`feature-104773-1724939348` for more details of the generic
|
||||
view interface.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Calling :php:`fillDefaultsByPackageName()` triggers a deprecation level
|
||||
log level entry in TYPO3 v13 and will be removed in TYPO3 v14.
|
||||
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
The method is relatively rarely used by extensions directly, a usage in
|
||||
Extbase :php:`ActionController` has been refactored away. The extension
|
||||
scanner will find candidates.
|
||||
|
||||
Note class :php:`TemplatePaths` is marked `@internal` and should not be
|
||||
used by extensions at all.
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
Use :php:`\TYPO3\CMS\Core\View\ViewFactoryInterface` to create views with
|
||||
proper template paths instead. The TYPO3 system extensions come with plenty
|
||||
of examples on how to do this.
|
||||
|
||||
.. index:: PHP-API, FullyScanned, ext:fluid
|
||||
@@ -0,0 +1,53 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-104773-1724942036:
|
||||
|
||||
=====================================================
|
||||
Deprecation: #104773 - Custom Fluid views and Extbase
|
||||
=====================================================
|
||||
|
||||
See :issue:`104773`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
These classes have been marked as deprecated in TYPO3 v13 and will be removed in v14:
|
||||
|
||||
* :php:`\TYPO3\CMS\Fluid\View\StandaloneView`
|
||||
* :php:`\TYPO3\CMS\Fluid\View\TemplateView`
|
||||
* :php:`\TYPO3\CMS\Fluid\View\AbstractTemplateView`
|
||||
* :php:`\TYPO3\CMS\Extbase\Mvc\View\ViewResolverInterface`
|
||||
* :php:`\TYPO3\CMS\Extbase\Mvc\View\GenericViewResolver`
|
||||
|
||||
This change is related to the general :ref:`View refactoring <feature-104773-1724939348>`.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Using one of the above classes triggers a deprecation level log entry.
|
||||
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
Instances with extensions that create view instances of
|
||||
:php-short:`\TYPO3\CMS\Fluid\View\StandaloneView` or
|
||||
:php-short:`\TYPO3\CMS\Fluid\View\TemplateView` are affected. The extension
|
||||
scanner will find possible candidates.
|
||||
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
Extensions should no longer directly instantiate own views, but should get
|
||||
:php:`\TYPO3\CMS\Core\View\ViewFactoryInterface` injected and use :php:`create()`
|
||||
to retrieve a view.
|
||||
|
||||
Within Extbase, :php:`ActionController->defaultViewObjectName` should only be
|
||||
set to Extbase :php:`JsonView` if needed, or not set at all. Custom view implementations
|
||||
should implement an own :php-short:`\TYPO3\CMS\Core\View\ViewFactoryInterface` and configure
|
||||
controllers to inject an instance, or can set :php:`$this->defaultViewObjectName = JsonView::class`
|
||||
in a custom :php:`__construct()`.
|
||||
|
||||
.. index:: PHP-API, PartiallyScanned, ext:core
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-104773-1724940753:
|
||||
|
||||
=================================================================
|
||||
Deprecation: #104773 - ext:backend LoginProviderInterface changes
|
||||
=================================================================
|
||||
|
||||
See :issue:`104773`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Method :php:`\TYPO3\CMS\Backend\LoginProvider\LoginProviderInterface->render()` has been marked as deprecated
|
||||
and is substituted by :php:`LoginProviderInterface->modifyView()` that will
|
||||
be added to the interface in TYPO3 v14, removing :php:`render()` from the
|
||||
interface in v14.
|
||||
|
||||
Related to this, event :php:`\TYPO3\CMS\Backend\LoginProvider\Event\ModifyPageLayoutOnLoginProviderSelectionEvent`
|
||||
has been changed to deprecate :php:`getController()` and :php:`getPageRenderer()`,
|
||||
while :php:`getRequest()` has been added. :php:`getView()` now typically returns
|
||||
an instance of :php:`ViewInterface`.
|
||||
|
||||
This change is related to the general :ref:`View refactoring <feature-104773-1724939348>`.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
The default :php-short:`\TYPO3\CMS\Backend\LoginProvider\LoginProviderInterface`
|
||||
implementation is
|
||||
:php-short:`\TYPO3\CMS\Backend\LoginProvider\UsernamePasswordLoginProvider`
|
||||
provided by ext:core. This consumer has been adapted.
|
||||
|
||||
Using :php:`LoginProviderInterface->render()` in TYPO3 v13 will trigger a
|
||||
deprecation level log entry and will fail in v14.
|
||||
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
Instances with custom login providers that change the TYPO3 backend login
|
||||
field rendering may be affected. The extension scanner is not configured to
|
||||
find usages, since method name :php:`render()` is too common. A deprecation
|
||||
level log message is triggered upon use of the old method.
|
||||
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
Consumers of :php-short:`\TYPO3\CMS\Backend\LoginProvider\LoginProviderInterface`
|
||||
should implement :php:`modifyView()` instead, the transition should be smooth.
|
||||
Consumers that need the :php-short:`\TYPO3\CMS\Core\Page\PageRenderer`
|
||||
for JavaScript magic, should use :ref:`dependency injection <t3coreapi:Dependency-Injection>`
|
||||
to receive an instance.
|
||||
|
||||
The default implementation in :php-short:`\TYPO3\CMS\Backend\LoginProvider\UsernamePasswordLoginProvider`
|
||||
is a good example. Extensions that need to configure additional template, layout or
|
||||
partial lookup paths can extend them:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
if ($view instanceof FluidViewAdapter) {
|
||||
$templatePaths = $view->getRenderingContext()->getTemplatePaths();
|
||||
$templateRootPaths = $templatePaths->getTemplateRootPaths();
|
||||
$templateRootPaths[] = 'EXT:my_extension/Resources/Private/Templates';
|
||||
$templatePaths->setTemplateRootPaths($templateRootPaths);
|
||||
}
|
||||
|
||||
Consumers of :php-short:`\TYPO3\CMS\Backend\LoginProvider\Event\ModifyPageLayoutOnLoginProviderSelectionEvent`
|
||||
should use the request instead, and/or should get an instance of
|
||||
:php-short:`\TYPO3\CMS\Core\Page\PageRenderer` injected as well.
|
||||
|
||||
.. index:: PHP-API, NotScanned, ext:backend
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-104778-1724953249:
|
||||
|
||||
=========================================================================
|
||||
Deprecation: #104778 - Instantiation of IconRegistry in ext_localconf.php
|
||||
=========================================================================
|
||||
|
||||
See :issue:`104778`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Since TYPO3 v11 it is possible to automatically register own icons via
|
||||
:file:`Configuration/Icons.php`. Prior to this, extension authors used to register
|
||||
icons manually via instantiating the php:`\TYPO3\CMS\Core\Imaging\IconRegistry`
|
||||
in their :file:`ext_localconf.php`
|
||||
files. This method has now been deprecated. It is recommended to switch to
|
||||
the newer method introduced with :issue:`94692`.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Instantiating :php-short:`\TYPO3\CMS\Core\Imaging\IconRegistry` inside
|
||||
:file:`ext_localconf.php` files will trigger a deprecation-level log entry.
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
All installations, which instantiate :php-short:`\TYPO3\CMS\Core\Imaging\IconRegistry`
|
||||
before the :php:`\TYPO3\CMS\Core\Core\Event\BootCompletedEvent`. This includes
|
||||
:file:`ext_localconf.php` files as well as :path:`TCA/Overrides`.
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
The most common use-cases can be accomplished via the :file:`Configuration/Icons.php`
|
||||
file.
|
||||
|
||||
Before:
|
||||
|
||||
.. code-block:: php
|
||||
:caption: EXT:example/ext_localconf.php
|
||||
|
||||
<?php
|
||||
|
||||
$iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
|
||||
\TYPO3\CMS\Core\Imaging\IconRegistry::class,
|
||||
);
|
||||
$iconRegistry->registerIcon(
|
||||
'example',
|
||||
\TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
|
||||
[
|
||||
'source' => 'EXT:example/Resources/Public/Icons/example.svg'
|
||||
],
|
||||
);
|
||||
|
||||
After:
|
||||
|
||||
.. code-block:: php
|
||||
:caption: EXT:example/Configuration/Icons.php
|
||||
|
||||
<?php
|
||||
|
||||
return [
|
||||
'example' => [
|
||||
'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
|
||||
'source' => 'EXT:example/Resources/Public/Icons/example.svg',
|
||||
],
|
||||
];
|
||||
|
||||
For more complex tasks, it is recommended to register an event listener for the
|
||||
:php-short:`\TYPO3\CMS\Core\Core\Event\BootCompletedEvent`. At this stage the system
|
||||
is fully booted and you have a completely configured IconRegistry at hand.
|
||||
|
||||
In case the registry was used in :path:`TCA/Overrides` files to retrieve icon
|
||||
identifiers, then this should be replaced completely with static identifiers.
|
||||
The reason behind this is, that the registry isn't even fully usable at this
|
||||
stage. TCA isn't fully built yet and icons can still be registered at a later
|
||||
point.
|
||||
|
||||
.. index:: PHP-API, NotScanned, ext:core
|
||||
@@ -0,0 +1,40 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-104789-1725196704:
|
||||
|
||||
========================================================
|
||||
Deprecation: #104789 - Fluid variables true, false, null
|
||||
========================================================
|
||||
|
||||
See :issue:`104789`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Fluid standalone will add proper language syntax for booleans and `null`
|
||||
with Fluid v4, which will be used in TYPO3 v13. Thus, user-defined variables
|
||||
named `true`, `false` and `null` are no longer allowed.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Assigning variables with name `true`, `false` or `null` will throw
|
||||
an exception in Fluid v4. In preparation of this change, Fluid v2.15 logs a
|
||||
deprecation level error message if any of these variable names are used.
|
||||
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
Instances with Fluid templates using `true`, `false` or `null` as user-defined variable names.
|
||||
This should rarely happen, as it would involve using :php:`$view->assign('true', $someVar)`.
|
||||
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
Template code using these variables should be adjusted to use different variable names.
|
||||
In Fluid v4, the variables will contain their matching PHP counterparts.
|
||||
|
||||
.. index:: Fluid, NotScanned, ext:fluid
|
||||
@@ -0,0 +1,155 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _deprecation-104789-1725195584:
|
||||
|
||||
===========================================================
|
||||
Deprecation: #104789 - renderStatic() for Fluid ViewHelpers
|
||||
===========================================================
|
||||
|
||||
See :issue:`104789`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The usage of :php:`renderStatic()` for Fluid ViewHelpers has been deprecated.
|
||||
Also, Fluid standalone traits
|
||||
:php:`\TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithContentArgumentAndRenderStatic`
|
||||
and :php:`\TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic`
|
||||
have been marked as deprecated.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Using one of the mentioned traits or :php:`renderStatic()` in ViewHelpers
|
||||
logs a deprecation level error message in Fluid standalone v4. :php:`renderStatic()`
|
||||
will no longer be called in Fluid standalone v5. :php:`renderStatic()` and both
|
||||
traits continue to work without deprecation level error message in
|
||||
Fluid standalone v2.
|
||||
|
||||
|
||||
Affected installations
|
||||
======================
|
||||
|
||||
Instances with custom ViewHelpers using any variant of :php:`renderStatic()` are affected.
|
||||
|
||||
|
||||
Migration
|
||||
=========
|
||||
|
||||
ViewHelpers should always use :php:`render()` as their primary rendering method.
|
||||
|
||||
ViewHelpers using just :php:`renderStatic()` without any trait or with the trait
|
||||
:php-short:`\TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic`
|
||||
can be migrated by converting the static rendering method to a non-static method:
|
||||
|
||||
Before:
|
||||
|
||||
.. code-block:: php
|
||||
class MyViewHelper extends AbstractViewHelper
|
||||
{
|
||||
use CompileWithRenderStatic;
|
||||
|
||||
public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext): string
|
||||
{
|
||||
return $renderChildrenClosure();
|
||||
}
|
||||
}
|
||||
|
||||
After:
|
||||
|
||||
.. code-block:: php
|
||||
class MyViewHelper extends AbstractViewHelper
|
||||
{
|
||||
public function render(): string
|
||||
{
|
||||
return $this->renderChildren();
|
||||
}
|
||||
}
|
||||
|
||||
ViewHelpers using :php:`\TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithContentArgumentAndRenderStatic`
|
||||
can use the new contentArgumentName feature added with Fluid v2.15:
|
||||
|
||||
Before:
|
||||
|
||||
.. code-block:: php
|
||||
class MyViewHelper extends AbstractViewHelper
|
||||
{
|
||||
use CompileWithContentArgumentAndRenderStatic;
|
||||
|
||||
public function initializeArguments(): void
|
||||
{
|
||||
$this->registerArgument('value', 'string', 'a value');
|
||||
}
|
||||
|
||||
public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext): string
|
||||
{
|
||||
return $renderChildrenClosure();
|
||||
}
|
||||
|
||||
public function resolveContentArgumentName(): string
|
||||
{
|
||||
return 'value';
|
||||
}
|
||||
}
|
||||
|
||||
After:
|
||||
|
||||
.. code-block:: php
|
||||
class MyViewHelper extends AbstractViewHelper
|
||||
{
|
||||
public function initializeArguments(): void
|
||||
{
|
||||
$this->registerArgument('value', 'string', 'a value');
|
||||
}
|
||||
|
||||
public function render(): string
|
||||
{
|
||||
return $this->renderChildren();
|
||||
}
|
||||
|
||||
public function getContentArgumentName(): string
|
||||
{
|
||||
return 'value';
|
||||
}
|
||||
}
|
||||
|
||||
Here is a basic recipe to perform this migration, preferably utilizing
|
||||
statical code analysis/replacement tools on your :file:`*ViewHelper.php`
|
||||
files:
|
||||
|
||||
* Find definitions of :php:`renderStatic`
|
||||
|
||||
* Rename method to :php:`render()`, remove the arguments, remove :php:`static` declaration
|
||||
|
||||
* Within that method:
|
||||
|
||||
* Replace :php:`$arguments` with :php:`$this->arguments`
|
||||
* Replace :php:`$renderingContext` with :php:`$this->renderingContext`
|
||||
* Replace :php:`$renderChildrenClosure()` with :php:`$this->renderChildren()`
|
||||
* Replace remaining :php:`$renderChildrenClosure` usages with proper closure handling, like :php:`$this->renderChildren(...)`.
|
||||
|
||||
* Replace :php:`resolveContentArgumentName(` with :php:`getContentArgumentName(`
|
||||
|
||||
* Remove the mentioned definitions:
|
||||
|
||||
* :php:`use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;`
|
||||
* :php:`use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;`
|
||||
* :php:`use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithContentArgumentAndRenderStatic;`
|
||||
* :php:`use CompileWithRenderStatic;` (class trait)
|
||||
* :php:`use CompileWithContentArgumentAndRenderStatic;` (class trait)
|
||||
|
||||
* (Optionally remove custom phpdoc annotations to the `renderStatic` parameters)
|
||||
|
||||
* If you previously called ViewHelper's :php:`renderStatic` methods in other places,
|
||||
you may utilize something like:
|
||||
|
||||
.. code-block:: php
|
||||
$this->renderingContext->getViewHelperInvoker()->invoke(
|
||||
MyViewHelper::class,
|
||||
$arguments,
|
||||
$this->renderingContext,
|
||||
$this->renderChildren(...),
|
||||
);
|
||||
|
||||
.. index:: Fluid, PartiallyScanned, ext:fluid
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-101252-1715447531:
|
||||
|
||||
=============================================================================
|
||||
Feature: #101252 - Introduce ErrorHandler for 403 errors with redirect option
|
||||
=============================================================================
|
||||
|
||||
See :issue:`101252`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The new error handler :php:`\TYPO3\CMS\Core\Error\PageErrorHandler\RedirectLoginErrorHandler`
|
||||
has been added, which makes it possible to redirect the user to a configurable page.
|
||||
|
||||
Requesting a login-protected URL would usually return a generic HTTP 403 error
|
||||
in case of a missing fulfilled access permissions and the configuration
|
||||
:php:`typolinkLinkAccessRestrictedPages = NONE` (default)
|
||||
is set.
|
||||
|
||||
By enabling this new handler via the site settings, the 403 response
|
||||
can be handled and a custom redirect can be performed.
|
||||
|
||||
The :php-short:`\TYPO3\CMS\Core\Error\PageErrorHandler\RedirectLoginErrorHandler`
|
||||
allows to define a
|
||||
:php:`loginRedirectTarget`, which must be configured to the page, where the
|
||||
login process is handled. Additionally, the :php:`loginRedirectParameter`
|
||||
must be set to the URL parameter that will be used to hand over the original
|
||||
URL to the target page.
|
||||
|
||||
The redirect ensures that the original URL is added to the configured GET
|
||||
parameter :php:`loginRedirectParameter`, so that the user can be redirected
|
||||
back to the original page after a successful login.
|
||||
|
||||
The error handler allows :php:`return_url` or :php:`redirect_url` as values
|
||||
for :php:`loginRedirectParameter`. Those values are used in extensions like
|
||||
`EXT:felogin` or `EXT:oidc`.
|
||||
|
||||
.. important::
|
||||
|
||||
Redirection to the originating URL via URI arguments requires that
|
||||
extensions like `EXT:felogin` are configured to allow these redirect modes
|
||||
(for example via
|
||||
:typoscript:`plugin.tx_felogin_login.settings.redirectMode=getpost,loginError`)
|
||||
|
||||
The new error handler works (with some minor exceptions) similar to the
|
||||
"Forbidden (HTTP Status 403)" handler in TYPO3 extension :composer:`plan2net/sierrha`.
|
||||
It will still emit generic 403 HTTP error messages in certain scenarios,
|
||||
like when a user is already logged in, but the permissions are not
|
||||
satisfied.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
It is now possible to configure a login redirection process when a user has no
|
||||
access to a page and a 403 error is thrown, so that after login the
|
||||
originating URL is requested again. Previously, this required custom
|
||||
Middlewares or implementations of
|
||||
:php-short:`\TYPO3\CMS\Core\Error\PageErrorHandler\PageErrorHandlerInterface`.
|
||||
|
||||
.. index:: Frontend, ext:core
|
||||
@@ -0,0 +1,35 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-101391-1689772689:
|
||||
|
||||
==========================================================
|
||||
Feature: #101391 - Add base64 attribute to ImageViewHelper
|
||||
==========================================================
|
||||
|
||||
See :issue:`101391`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The ViewHelpers :ref:`<f:image> <t3viewhelper:typo3-fluid-image>` and
|
||||
:ref:`<f:uri.image> <t3viewhelper:typo3-fluid-uri-image>` now
|
||||
support the attribute :fluid:`base64="true"` that will provide
|
||||
a possibility to return the value of the image's :fluid:`src` attribute
|
||||
encoded in base64.
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<f:image base64="true" src="EXT:backend/Resources/Public/Images/typo3_logo_orange.svg" height="20" class="pr-2" />
|
||||
<img src="{f:uri.image(base64: 'true', src:'EXT:backend/Resources/Public/Images/typo3_logo_orange.svg')}">
|
||||
|
||||
Will result in the according HTML tag providing the image encoded in base64.
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<img class="pr-2" src="data:image/svg+xml;base64,PHN2...cuODQ4LTYuNzU3Ii8+Cjwvc3ZnPgo=" alt="" width="20" height="20">
|
||||
<img src="data:image/svg+xml;base64,PHN2...cuODQ4LTYuNzU3Ii8+Cjwvc3ZnPgo=">
|
||||
|
||||
This can be particularly useful inside `\TYPO3\CMS\Core\Mail\FluidEmail` or
|
||||
to prevent unneeded HTTP calls.
|
||||
|
||||
.. index:: Fluid, ext:fluid
|
||||
@@ -0,0 +1,36 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-101472-1721137289:
|
||||
|
||||
================================================
|
||||
Feature: #101472 - Allow static routes to assets
|
||||
================================================
|
||||
|
||||
See :issue:`101472`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
It is now possible to configure static routes with the type `asset` to link to
|
||||
resources which are typically located in the directory
|
||||
:file:`EXT:my_extension/Resources/Public/`.
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: config/sites/my-site/config.yaml
|
||||
|
||||
routes:
|
||||
-
|
||||
route: example.svg
|
||||
type: asset
|
||||
asset: 'EXT:backend/Resources/Public/Icons/Extension.svg'
|
||||
|
||||
Note that the asset URL can be configured on a per-site basis.
|
||||
This allows to deliver site-dependent custom favicon or manifest
|
||||
assets, for example.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Static routes to files shipped with extensions can now be configured in the site configuration.
|
||||
|
||||
.. index:: Frontend, YAML, ext:frontend
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-102255-1726090749:
|
||||
|
||||
=================================================================
|
||||
Feature: #102255 - Option to skip URL processing in AssetRenderer
|
||||
=================================================================
|
||||
|
||||
See :issue:`102255`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The :php:`\TYPO3\CMS\Core\Page\AssetCollector` options have been extended to
|
||||
include an `external`
|
||||
flag. When set for asset files using :php:`$assetCollector->addStyleSheet()`
|
||||
or :php:`$assetCollector->addJavaScript()`, all processing of the asset
|
||||
URI (like the addition of the cache busting parameter) is skipped and the input
|
||||
path will be used as-is in the resulting HTML tag.
|
||||
|
||||
Example
|
||||
=======
|
||||
|
||||
The following code skips the cache busting parameter `?1726090820` for the
|
||||
supplied CSS file:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$assetCollector->addStyleSheet(
|
||||
'myCssFile',
|
||||
PathUtility::getAbsoluteWebPath(GeneralUtility::getFileAbsFileName('EXT:my_extension/Resources/Public/MyFile.css')),
|
||||
[],
|
||||
['external' => true]
|
||||
);
|
||||
|
||||
|
||||
Resulting in the following HTML output:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<link rel="stylesheet" href="/_assets/<hash>/myFile.css" />
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Developers can now use the :php-short:`\TYPO3\CMS\Core\Page\AssetCollector`
|
||||
API to embed JavaScript or CSS files without any processing of the
|
||||
supplied asset URI.
|
||||
|
||||
.. index:: PHP-API, ext:core
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-102353-1699523309:
|
||||
|
||||
==================================================================
|
||||
Feature: #102353 - AVIF support for images generated by GIFBUILDER
|
||||
==================================================================
|
||||
|
||||
See :issue:`102353`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
GIFBUILDER, the image manipulation library for TypoScript based on GDlib, a PHP
|
||||
extension bundled into PHP, now also supports generating resulting files of
|
||||
type "avif".
|
||||
|
||||
AVIF is an image format, that is supported by most modern browsers, and usually
|
||||
has a better compression (= smaller file size) than jpg files.
|
||||
|
||||
.. important::
|
||||
|
||||
Before using this feature, please check whether the used operating system
|
||||
actually supports de/encoding AVIF files. Especially Debian 11 (Bullseye)
|
||||
and older or systems forked from that may lack AVIF support.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
If defined via format=avif within a GifBuilder setup, the generated files are
|
||||
now AVIF files instead of png (the default).
|
||||
|
||||
It is possible to define the quality of a AVIF image similar to jpg images
|
||||
globally via :php:`$TYPO3_CONF_VARS['GFX']['avif_quality']` or via TypoScript's
|
||||
"quality" property on a per-image basis. Via TypoScript it is also possible
|
||||
to use the new property "speed" - see https://www.php.net/manual/en/function.imageavif.php
|
||||
for more details.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code-block:: typoscript
|
||||
|
||||
page.10 = IMAGE
|
||||
page.10 {
|
||||
file = GIFBUILDER
|
||||
file {
|
||||
backColor = yellow
|
||||
XY = 1024,199
|
||||
format = avif
|
||||
quality = 44
|
||||
speed = 1
|
||||
|
||||
10 = IMAGE
|
||||
10.offset = 10,10
|
||||
10.file = 1:/my-image.jpg
|
||||
}
|
||||
}
|
||||
|
||||
A new test in the Environment module / Install Tool can be used to check if the
|
||||
bundled GDlib extension of your PHP version supports the AVIF image format.
|
||||
|
||||
.. index:: Frontend, TypoScript, ext:frontend
|
||||
@@ -0,0 +1,102 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-109999-1700506000:
|
||||
|
||||
===================================================
|
||||
Feature: #102422 - Introduce CacheDataCollector Api
|
||||
===================================================
|
||||
|
||||
See :issue:`102422`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
A new API has been introduced to collect cache tags and their corresponding
|
||||
lifetime. This API is used in TYPO3 to accumulate cache tags from page cache and
|
||||
content object cache.
|
||||
|
||||
The API is implemented as a new PSR-7 request attribute
|
||||
:php:`'frontend.cache.collector'`, which makes this API independent from TSFE.
|
||||
|
||||
Every cache tag has a lifetime. The minimum lifetime is calculated
|
||||
from all given cache tags. By default, the lifetime of a cache tag is set to
|
||||
:php:`PHP_INT_MAX`, so it expires many years in the future. API users must
|
||||
therefore define the lifetime of a cache tag individually.
|
||||
|
||||
The current TSFE API is deprecated in favor of the new API, as the
|
||||
current cache tag API implementation does not allow to set lifetime and
|
||||
extension authors had to work around it.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code-block:: php
|
||||
:caption: Add a single cache tag with 24 hours lifetime
|
||||
|
||||
use TYPO3\CMS\Core\Cache\CacheTag;
|
||||
|
||||
$cacheDataCollector = $request->getAttribute('frontend.cache.collector');
|
||||
$cacheDataCollector->addCacheTags(
|
||||
new CacheTag('tx_myextension_mytable', 86400)
|
||||
);
|
||||
|
||||
.. code-block:: php
|
||||
:caption: Add multiple cache tags with different lifetimes
|
||||
|
||||
use TYPO3\CMS\Core\Cache\CacheTag;
|
||||
|
||||
$cacheDataCollector = $request->getAttribute('frontend.cache.collector');
|
||||
$cacheDataCollector->addCacheTags(
|
||||
new CacheTag('tx_myextension_mytable_123', 3600),
|
||||
new CacheTag('tx_myextension_mytable_456', 2592000)
|
||||
);
|
||||
|
||||
.. code-block:: php
|
||||
:caption: Remove a cache tag
|
||||
|
||||
use TYPO3\CMS\Core\Cache\CacheTag;
|
||||
|
||||
$cacheDataCollector = $request->getAttribute('frontend.cache.collector');
|
||||
$cacheDataCollector->removeCacheTags(
|
||||
new CacheTag('tx_myextension_mytable_123')
|
||||
);
|
||||
|
||||
.. code-block:: php
|
||||
:caption: Remove multiple cache tags
|
||||
|
||||
use TYPO3\CMS\Core\Cache\CacheTag;
|
||||
|
||||
$cacheDataCollector = $request->getAttribute('frontend.cache.collector');
|
||||
$cacheDataCollector->removeCacheTags(
|
||||
new CacheTag('tx_myextension_mytable_123'),
|
||||
new CacheTag('tx_myextension_mytable_456')
|
||||
);
|
||||
|
||||
.. code-block:: php
|
||||
:caption: Get minimum lifetime, calculated from all cache tags
|
||||
|
||||
$cacheDataCollector = $request->getAttribute('frontend.cache.collector');
|
||||
$cacheDataCollector->resolveLifetime();
|
||||
|
||||
.. code-block:: php
|
||||
:caption: Get all cache tags
|
||||
|
||||
$cacheDataCollector = $request->getAttribute('frontend.cache.collector');
|
||||
$cacheDataCollector->getCacheTags();
|
||||
|
||||
The following event should only be used in code that has no access to the
|
||||
request attribute :php:`'frontend.cache.collector'`, it is marked :php:`@internal`
|
||||
and may vanish: It designed to allow passive cache-data signaling, without
|
||||
exactly knowing the current context and not having the current request at hand.
|
||||
It is not meant to allow for cache tag interception or extension.
|
||||
|
||||
.. code-block:: php
|
||||
:caption: Add cache tag without access to the request object
|
||||
|
||||
$this->eventDispatcher->dispatch(
|
||||
new AddCacheTagEvent(
|
||||
new CacheTag('tx_myextension_mytable_123', 3600)
|
||||
)
|
||||
);
|
||||
|
||||
.. index:: PHP-API, ext:core
|
||||
@@ -0,0 +1,87 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-103090-1707479280:
|
||||
|
||||
====================================================
|
||||
Feature: #103090 - Make link type label configurable
|
||||
====================================================
|
||||
|
||||
See :issue:`103090`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
It is now possible to provide a translated label for custom link types.
|
||||
|
||||
For this, a new interface
|
||||
:php:`\TYPO3\CMS\Linkvalidator\Linktype\LabelledLinktypeInterface` has been
|
||||
created, which offers the method :php:`getReadableName` for implementation.
|
||||
That method can return the translated label.
|
||||
|
||||
The default abstract implementation
|
||||
:php:`\TYPO3\CMS\Linkvalidator\Linktype\AbstractLinktype` has been enhanced
|
||||
to implement that interface. Any custom class extending this abstract is
|
||||
able to override the method :php:`getReadableName` to provide the
|
||||
custom translation.
|
||||
|
||||
Example extending the abstract:
|
||||
-------------------------------
|
||||
|
||||
.. code-block:: php
|
||||
:caption: EXT:extension/Classes/Linktype/CustomLinktype.php
|
||||
|
||||
use TYPO3\CMS\Linkvalidator\Linktype\AbstractLinktype;
|
||||
|
||||
#[Autoconfigure(public: true)]
|
||||
class CustomLinktype extends AbstractLinktype
|
||||
{
|
||||
public function getReadableName(): string
|
||||
{
|
||||
$type = $this->getIdentifier();
|
||||
return $this->getLanguageService()->sL(
|
||||
'LLL:EXT:linkvalidator_example/Resources/Private/Language/Module/locallang.xlf:linktype_'
|
||||
. $type
|
||||
) ?: $type;
|
||||
}
|
||||
}
|
||||
|
||||
Example implementing the interface:
|
||||
-----------------------------------
|
||||
|
||||
.. code-block:: php
|
||||
:caption: EXT:extension/Classes/Linktype/CustomLinktype.php
|
||||
|
||||
use TYPO3\CMS\Linkvalidator\Linktype\LinktypeInterface;
|
||||
use TYPO3\CMS\Linkvalidator\Linktype\LabelledLinktypeInterface;
|
||||
|
||||
#[Autoconfigure(public: true)]
|
||||
class CustomLinktype implements LinktypeInterface, LabelledLinktypeInterface
|
||||
{
|
||||
// implement all LinktypeInterface methods:
|
||||
// getIdentifier, checkLink, setAdditionalConfig, ...
|
||||
|
||||
// Implement the LabelledLinktypeInterface method getReadableName()
|
||||
public function getReadableName(): string
|
||||
{
|
||||
$type = $this->getIdentifier();
|
||||
return $this->getLanguageService()->sL(
|
||||
'LLL:EXT:linkvalidator_example/Resources/Private/Language/Module/locallang.xlf:linktype_'
|
||||
. $type
|
||||
) ?: $type;
|
||||
}
|
||||
}
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Custom linktype classes should now configure a label by implementing the method
|
||||
:php:`LabelledLinktypeInterface::getReadableName()`.
|
||||
|
||||
All existing custom implementations of the
|
||||
:php-short:`\TYPO3\CMS\Linkvalidator\Linktype\AbstractLinktype` class or the
|
||||
:php-short:`\TYPO3\CMS\Linkvalidator\Linktype\LabelledLinktypeInterface`
|
||||
will continue to work as before, and will just continue to use the internal name of
|
||||
the link type, instead of a translated label.
|
||||
|
||||
|
||||
.. index:: Backend, ext:linkvalidator
|
||||
@@ -0,0 +1,429 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-103511-1711894330:
|
||||
|
||||
======================================================================
|
||||
Feature: #103511 - Introduce Extbase file upload and deletion handling
|
||||
======================================================================
|
||||
|
||||
See :issue:`103511`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
TYPO3 now provides an API for file upload- and deletion-handling in Extbase
|
||||
extensions, which allows extension developers to implement file uploads
|
||||
more easily into Extbase Domain Models.
|
||||
|
||||
The scope of this API is to cover some of the most common use cases and to
|
||||
keep the internal file upload and deletion process in Extbase as simple as
|
||||
possible.
|
||||
|
||||
The API supports mapping and handling of file uploads and deletions for the
|
||||
following scenarios:
|
||||
|
||||
* Property of type :php-short:`\TYPO3\CMS\Extbase\Domain\Model\FileReference`
|
||||
in a domain model
|
||||
* Property of type
|
||||
:php:`\TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference>`
|
||||
in a domain model
|
||||
|
||||
File uploads can be validated by the following rules:
|
||||
|
||||
* minimum and maximum file count
|
||||
* minimum and maximum file size
|
||||
* allowed MIME types
|
||||
* image dimensions (for image uploads)
|
||||
|
||||
Additionally, it is ensured, that the filename given by the client is valid,
|
||||
meaning that no invalid characters (null-bytes) are added and that the file
|
||||
does not contain an invalid file extension. The API has support for custom
|
||||
validators, which can be created on demand.
|
||||
|
||||
To avoid complexity and maintain data integrity, a file upload is only
|
||||
processed if the validation of all properties of a domain model is successful.
|
||||
In this first implementation, file uploads are not persisted/cached temporarily,
|
||||
so this means in any case of a validation failure ("normal" validators and file upload
|
||||
validation) a file upload must be performed again by users.
|
||||
|
||||
Possible future enhancements of this functionality could enhance the existing
|
||||
`#[FileUpload]` attribute/annotation with configuration like a temporary storage
|
||||
location, or specifying additional custom validators (which can be done via the PHP-API as
|
||||
described below)
|
||||
|
||||
Nesting of domain models
|
||||
------------------------
|
||||
|
||||
File upload handling for nested domain models (e.g. modelA.modelB.fileReference)
|
||||
is not supported.
|
||||
|
||||
|
||||
File upload configuration with the `FileUpload` attribute
|
||||
---------------------------------------------------------
|
||||
|
||||
File upload for a property of a domain model can be configured using the
|
||||
newly introduced :php:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
#[FileUpload([
|
||||
'validation' => [
|
||||
'required' => true,
|
||||
'maxFiles' => 1,
|
||||
'fileSize' => ['minimum' => '0K', 'maximum' => '2M'],
|
||||
'mimeType' => ['allowedMimeTypes' => ['image/jpeg', 'image/png']],
|
||||
'fileExtension' => ['allowedFileExtensions' => ['jpg', 'jpeg', 'png']],
|
||||
],
|
||||
'uploadFolder' => '1:/user_upload/files/',
|
||||
])]
|
||||
protected ?FileReference $file = null;
|
||||
|
||||
All configuration settings of the
|
||||
:php:`\TYPO3\CMS\Extbase\Mvc\Controller\FileUploadConfiguration` object can
|
||||
be defined using the :php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload`
|
||||
attribute. It is however not possible
|
||||
to add custom validators using the
|
||||
:php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute, which you
|
||||
can achieve with a manual configuration as shown below.
|
||||
|
||||
The currently available configuration array keys are:
|
||||
|
||||
* `validation` (:php:`array` with keys `required`, `maxFiles`, `minFiles`,
|
||||
`fileSize`, `fileExtension`, `allowedMimeTypes`, `mimeType`, `imageDimensions`,
|
||||
see :ref:`83749-validationkeys`)
|
||||
* `uploadFolder` (:php:`string`, destination folder)
|
||||
* `duplicationBehavior` (:php:`object`, behaviour when file exists)
|
||||
* `addRandomSuffix` (:php:`bool`, suffixing files)
|
||||
* `createUploadFolderIfNotExist` (:php:`bool`, whether to create missing
|
||||
directories)
|
||||
|
||||
It is also possible to use the :php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` annotation to configure
|
||||
file upload properties, but it is recommended to use the
|
||||
:php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute due to better readability.
|
||||
|
||||
|
||||
Manual file upload configuration
|
||||
--------------------------------
|
||||
|
||||
A file upload configuration can also be created manually and should be
|
||||
done in the :php:`initialize*Action`.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
public function initializeCreateAction(): void
|
||||
{
|
||||
$mimeTypeValidator = GeneralUtility::makeInstance(MimeTypeValidator::class);
|
||||
$mimeTypeValidator->setOptions(['allowedMimeTypes' => ['image/jpeg']]);
|
||||
$fileExtensionValidator = GeneralUtility::makeInstance(FileExtensionValidator::class);
|
||||
$fileExtensionValidator->setOptions(['allowedFileExtensions' => ['jpg', 'jpeg']]);
|
||||
|
||||
$fileHandlingServiceConfiguration = $this->arguments->getArgument('myArgument')->getFileHandlingServiceConfiguration();
|
||||
$fileHandlingServiceConfiguration->addFileUploadConfiguration(
|
||||
(new FileUploadConfiguration('myPropertyName'))
|
||||
->setRequired()
|
||||
->addValidator($mimeTypeValidator)
|
||||
->addValidator($fileExtensionValidator)
|
||||
->setMaxFiles(1)
|
||||
->setUploadFolder('1:/user_upload/files/')
|
||||
);
|
||||
|
||||
$this->arguments->getArgument('myArgument')->getPropertyMappingConfiguration()->skipProperties('myPropertyName');
|
||||
}
|
||||
|
||||
|
||||
Configuration options for file uploads
|
||||
--------------------------------------
|
||||
|
||||
The configuration for a file upload is defined in a
|
||||
:php:`FileUploadConfiguration` object.
|
||||
|
||||
This object contains the following configuration options.
|
||||
|
||||
.. hint::
|
||||
|
||||
The appropriate setter methods or configuration
|
||||
keys can best be inspected inside that class definition.
|
||||
|
||||
Property name:
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Defines the name of the property of a domain model to which the file upload
|
||||
configuration applies. The value is automatically retrieved when using
|
||||
the :php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute. If the
|
||||
:php-short:`\TYPO3\CMS\Extbase\Mvc\Controller\FileUploadConfiguration` object
|
||||
is created manually, it must be set using the :php:`$propertyName`
|
||||
constructor argument.
|
||||
|
||||
Validation:
|
||||
~~~~~~~~~~~
|
||||
|
||||
File upload validation is defined in an array of validators in the
|
||||
:php-short:`\TYPO3\CMS\Extbase\Mvc\Controller\FileUploadConfiguration` object.
|
||||
|
||||
The validators
|
||||
:php:`\TYPO3\CMS\Extbase\Validation\Validator\FileNameValidator`,
|
||||
(ensures that no executable PHP files can
|
||||
be uploaded) and :php:`\TYPO3\CMS\Extbase\Validation\Validator\FileExtensionMimeTypeConsistencyValidator`
|
||||
(ensuring that the file extension matches the expected mime-type assumptions),
|
||||
are enforced and executed by default.
|
||||
|
||||
In addition, Extbase includes the following validators to validate an
|
||||
:php-short:`\TYPO3\CMS\Core\Http\UploadedFile` object:
|
||||
|
||||
* :php:`\TYPO3\CMS\Extbase\Validation\Validator\FileExtensionValidator`
|
||||
* :php:`\TYPO3\CMS\Extbase\Validation\Validator\FileSizeValidator`
|
||||
* :php:`\TYPO3\CMS\Extbase\Validation\Validator\MimeTypeValidator`
|
||||
* :php:`\TYPO3\CMS\Extbase\Validation\Validator\ImageDimensionsValidator`
|
||||
|
||||
Those validators can either be configured with the
|
||||
:php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute or added
|
||||
manually to the configuration object
|
||||
with the :php:`addValidator` method.
|
||||
|
||||
Required:
|
||||
~~~~~~~~~
|
||||
|
||||
Defines whether a file must be uploaded. If it is set to `true`, the
|
||||
:php:`minFiles` configuration is set to `1`.
|
||||
|
||||
Minimum files:
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Defines the minimum amount of files to be uploaded.
|
||||
|
||||
Maximum files:
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Defines the maximum amount of files to be uploaded.
|
||||
|
||||
Upload folder:
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Defines the upload path for the file upload. This configuration expects a
|
||||
storage identifier (e.g. :php:`1:/user_upload/folder/`). If the given target
|
||||
folder in the storage does not exist, it is created automatically.
|
||||
|
||||
Upload folder creation, when missing:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The default creation of a missing storage folder can be disabled via the
|
||||
configuration attribute :php:`createUploadFolderIfNotExist`
|
||||
(:php:`bool`, default :php:`true`).
|
||||
|
||||
Add random suffix:
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
When enabled, the filename of an uploaded and persisted file will contain a
|
||||
random 16 char suffix. As an example, an uploaded file named
|
||||
:php:`job-application.pdf` will be persisted as
|
||||
:php:`job-application-<random-hash>.pdf` in the upload folder.
|
||||
|
||||
The default value for this configuration is :php:`true` and it is recommended
|
||||
to keep this configuration active.
|
||||
|
||||
This configuration only has an effect when uploaded files are persisted.
|
||||
|
||||
Duplication behavior:
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Defines the FAL behavior, when a file with the same name exists in the target
|
||||
folder. Possible values are :php:`DuplicationBehavior::RENAME` (default),
|
||||
:php:`DuplicationBehavior::REPLACE` and :php:`DuplicationBehavior::CANCEL`.
|
||||
|
||||
|
||||
Modifying existing configuration
|
||||
--------------------------------
|
||||
|
||||
File upload configuration defined by the
|
||||
:php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute can be
|
||||
changed in the :php:`initialize*Action`.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
public function initializeCreateAction(): void
|
||||
{
|
||||
$validator = GeneralUtility::makeInstance(MyCustomValidator::class);
|
||||
|
||||
$argument = $this->arguments->getArgument('myArgument');
|
||||
$configuration = $argument->getFileHandlingServiceConfiguration()->getFileUploadConfigurationForProperty('file');
|
||||
$configuration?->setMinFiles(2);
|
||||
$configuration?->addValidator($validator);
|
||||
$configuration?->setUploadFolder('1:/user_upload/custom_folder');
|
||||
}
|
||||
|
||||
The example shows how to modify the file upload configuration for the argument
|
||||
:php:`item` and the property :php:`file`. The minimum amount of files to be
|
||||
uploaded is set to :php:`2` and a custom validator is added.
|
||||
|
||||
To remove all defined validators except the :php:`FileNameValidator`, use
|
||||
the :php:`resetValidators()` method.
|
||||
|
||||
|
||||
Using TypoScript configuration for file uploads configuration
|
||||
-------------------------------------------------------------
|
||||
|
||||
When a file upload configuration for a property has been added using the
|
||||
:php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute, it may be
|
||||
required make the upload folder or
|
||||
other configuration options configurable with TypoScript.
|
||||
|
||||
Extension authors should use the :php:`initialize*Action` to apply settings
|
||||
from TypoScript to a file upload configuration.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
public function initializeCreateAction(): void
|
||||
{
|
||||
$argument = $this->arguments->getArgument('myArgument');
|
||||
$configuration = $argument->getFileHandlingServiceConfiguration()->getFileUploadConfigurationForProperty('file');
|
||||
$configuration?->setUploadFolder($this->settings['uploadFolder'] ?? '1:/fallback_folder');
|
||||
}
|
||||
|
||||
|
||||
.. _83749-validationkeys:
|
||||
|
||||
File upload validation
|
||||
----------------------
|
||||
|
||||
Each uploaded file can be validated against a configurable set of validators.
|
||||
The :php:`validation` section of the :php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute allows to
|
||||
configure commonly used validators using a configuration shorthand.
|
||||
|
||||
The following validation rules can be configured in the :php:`validation`
|
||||
section of the :php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute:
|
||||
|
||||
* :php:`required`
|
||||
* :php:`minFiles`
|
||||
* :php:`maxFiles`
|
||||
* :php:`fileExtension` (for :php:`TYPO3\CMS\Extbase\Validation\Validator\FileExtensionValidator`)
|
||||
* :php:`fileSize` (for :php:`TYPO3\CMS\Extbase\Validation\Validator\FilesizeValidator`)
|
||||
* :php:`imageDimensions` (for :php:`TYPO3\CMS\Extbase\Validation\Validator\ImageDimensionsValidator`)
|
||||
* :php:`mimeType` (for :php:`TYPO3\CMS\Extbase\Validation\Validator\MimeTypeValidator`)
|
||||
* :php:`allowedMimeTypes` (shorthand notation for configuration option :php:`allowedMimeTypes` of the :php:`MimeTypeValidator`)
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
#[FileUpload([
|
||||
'validation' => [
|
||||
'required' => true,
|
||||
'maxFiles' => 1,
|
||||
'fileSize' => ['minimum' => '0K', 'maximum' => '2M'],
|
||||
'mimeType' => ['allowedMimeTypes' => ['image/jpeg']],
|
||||
'fileExtension' => ['allowedFileExtensions' => ['jpg', 'jpeg']],
|
||||
'imageDimensions' => ['maxWidth' => 4096, 'maxHeight' => 4096]
|
||||
],
|
||||
'uploadFolder' => '1:/user_upload/extbase_single_file/',
|
||||
])]
|
||||
|
||||
Extbase will internally use the Extbase file upload validators for
|
||||
:php:`fileExtensionMimeTypeConsistency`, :php:`fileExtension`, :php:`fileSize`,
|
||||
:php:`mimeType` and :php:`imageDimensions` validation.
|
||||
|
||||
Custom validators can be created according to project requirements and must
|
||||
extend the Extbase :php-short:`\TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator`.
|
||||
The value to be validated is
|
||||
always a PSR-7 :php-short:`\TYPO3\CMS\Core\Http\UploadedFile` object.
|
||||
Custom validators can however not
|
||||
be used in the :php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute
|
||||
and must be configured manually.
|
||||
|
||||
Shorthand notation for `allowedMimeTypes`
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Using the :php:`mimeType` configuration array, all options of the `MimeTypeValidator`
|
||||
can be set as sub-keys (since TYPO3 13.4.1):
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
#[FileUpload([
|
||||
'validation' => [
|
||||
'required' => true,
|
||||
'mimeType' => [
|
||||
'allowedMimeTypes' => ['image/jpeg'],
|
||||
'ignoreFileExtensionCheck' => false,
|
||||
'notAllowedMessage' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:validation.mimetype.notAllowedMessage',
|
||||
'invalidExtensionMessage' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:validation.mimetype.invalidExtensionMessage',
|
||||
],
|
||||
],
|
||||
'uploadFolder' => '1:/user_upload/files/',
|
||||
])]
|
||||
|
||||
The shorthand notation via :php:`'allowedMimeTypes'` continues to
|
||||
exist, in case only the mime type validation is needed. However, it is recommended
|
||||
to utilize the full :php:`'mimeType'` configuration array.
|
||||
|
||||
|
||||
Deletion of uploaded files and file references
|
||||
----------------------------------------------
|
||||
|
||||
The new Fluid ViewHelper
|
||||
:ref:`Form.uploadDeleteCheckbox ViewHelper <f:form.uploadDeleteCheckbox> <t3viewhelper:typo3-fluid-form-uploaddeletecheckbox>`
|
||||
can be used to show a "delete file" checkbox in a form.
|
||||
|
||||
Example for object with :php-short:`\TYPO3\CMS\Extbase\Domain\Model\FileReference` property:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<f:form.uploadDeleteCheckbox property="file" fileReference="{object.file}" />
|
||||
|
||||
Example for an object with an
|
||||
:php:`TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference>`
|
||||
property, containing multiple files and allowing to delete the first one
|
||||
(iteration is possible within Fluid, to do that for every object of the collection):
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<f:form.uploadDeleteCheckbox property="file.0" fileReference="{object.file}" />
|
||||
|
||||
Extbase will then handle file deletion(s) before persisting a validated
|
||||
object. It will:
|
||||
|
||||
* validate that minimum and maximum file upload configuration for the affected
|
||||
property is fulfilled (only if the property has a :php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload`)
|
||||
* delete the affected :php:`sys_file_reference` record
|
||||
* delete the affected file
|
||||
|
||||
Internally, Extbase uses :php:`FileUploadDeletionConfiguration` objects to track
|
||||
file deletions for properties of arguments. Files are deleted directly without
|
||||
checking whether the current file is referenced by other objects.
|
||||
|
||||
Apart from using this ViewHelper, it is of course still possible to manipulate
|
||||
:php-short:`\TYPO3\CMS\Extbase\Domain\Model\FileReference` properties with custom logic before persistence.
|
||||
|
||||
New PSR-14 events
|
||||
-----------------
|
||||
|
||||
The following new PSR-14 event has been added to allow customization
|
||||
of file upload related tasks:
|
||||
|
||||
ModifyUploadedFileTargetFilenameEvent
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The :php-short:`\TYPO3\CMS\Extbase\Event\Service\ModifyUploadedFileTargetFilenameEvent`
|
||||
allows event listeners to
|
||||
alter a filename of an uploaded file before it is persisted.
|
||||
|
||||
Event listeners can use the method `getTargetFilename()` to retrieve the filename
|
||||
used for persistence of a configured uploaded file. The filename can then be
|
||||
adjusted via `setTargetFilename()`. The relevant configuration can be retrieved
|
||||
via `getConfiguration()`.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Extension developers can use the new feature to implement file uploads and
|
||||
file deletions in Extbase extensions easily with commonly known Extbase
|
||||
property attributes/annotations.
|
||||
|
||||
.. index:: PHP-API, ext:extbase
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-103521-1718028096:
|
||||
|
||||
=====================================================================================
|
||||
Feature: #103521 - Change table restrictions UI to combine read and write permissions
|
||||
=====================================================================================
|
||||
|
||||
See :issue:`103521`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The `tables_select` and `tables_modify` fields of the `be_groups` table store
|
||||
information about permissions to read and write into selected database tables.
|
||||
|
||||
Due to TYPO3's internal behavior, when write permissions are granted for some
|
||||
tables, those tables are also automatically available for reading.
|
||||
|
||||
To make managing table permissions much easier and more efficient for
|
||||
integrators, the separate form fields for `Tables (listing) [tables_select]` and
|
||||
`Tables (modify) [tables_modify]` have been combined into a single UI element.
|
||||
This field now offers separate radio buttons to define which tables the backend
|
||||
user group should have permission to read and / or write. This is done by
|
||||
selecting one of the "No Access", "Read" or "Read & Write" options.
|
||||
|
||||
To further improve the user experience, it is also possible to use the
|
||||
"Check All", "Uncheck All" and "Toggle Selection" options for each permission.
|
||||
|
||||
Under the hood, when these permissions are processed, they are still saved
|
||||
separately in the `tables_select` and `tables_modify` columns in the
|
||||
`be_groups` table, as they were before.
|
||||
|
||||
To render this new table view and handle its behavior, a dedicated form
|
||||
renderType `tablePermission` has been introduced, which is now set for
|
||||
the `tables_modify` column. The `tables_select` column has been changed
|
||||
to TCA type `passthrough`.
|
||||
|
||||
The new form element is defined through:
|
||||
:php:`\TYPO3\CMS\Backend\Form\Element\TablePermissionElement`.
|
||||
It uses a dedicated data provider defined in:
|
||||
:php:`\TYPO3\CMS\Backend\Form\FormDataProvider\TcaTablePermission`.
|
||||
The JavaScript code is handled by a new web component:
|
||||
:js:`@typo3/backend/form-engine/element/table-permission-element.js`.
|
||||
|
||||
When the :php-short:`\TYPO3\CMS\Backend\Form\FormDataProvider\TcaTablePermission`
|
||||
data provider handles the configuration, it
|
||||
reads table lists from both the `tables_select` and `tables_modify`
|
||||
columns and combines them into a single array with unique table names.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Managing table permissions for backend user groups has been improved by
|
||||
visually combining the `Tables (listing) [tables_select]` and
|
||||
`Tables (modify) [tables_modify]` options, as well as by adding the
|
||||
multi record selection functionality.
|
||||
|
||||
.. note::
|
||||
|
||||
These changes might affect custom integrations and modifications made to
|
||||
the `tables_select` or `tables_modify` columns in the `be_groups` TCA.
|
||||
Integrators who have modified the configuration for these fields should
|
||||
verify if their code works and adapt it if needed.
|
||||
|
||||
.. index:: Backend, JavaScript, PHP-API, TCA, ext:core
|
||||
@@ -0,0 +1,35 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-103576-1720813198:
|
||||
|
||||
===================================================================
|
||||
Feature: #103576 - Allow defining opacity in TCA type=color element
|
||||
===================================================================
|
||||
|
||||
See :issue:`103576`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
A new boolean property `opacity` has been added to the TCA configuration of
|
||||
a TCA type `color` element to allow defining colors with an opacity using
|
||||
the `RRGGBBAA` color notation.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'my_color' => [
|
||||
'label' => 'My Color',
|
||||
'config' => [
|
||||
'type' => 'color',
|
||||
'opacity' => true,
|
||||
],
|
||||
],
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
If `opacity` is enabled, editors can select not only a color but also its
|
||||
opacity in a corresponding color element.
|
||||
|
||||
.. index:: TCA, ext:backend
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-103581-1723209131:
|
||||
|
||||
==============================================================================
|
||||
Feature: #103581 - Automatically transform TCA field values for record objects
|
||||
==============================================================================
|
||||
|
||||
See :issue:`103581`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
With :issue:`103783` the new :php:`\TYPO3\CMS\Core\Domain\Record` object has been
|
||||
introduced. It is an
|
||||
object representing a raw database record, based on TCA and is usually used in
|
||||
the frontend (via Fluid Templates), when fetching records with the
|
||||
:ref:`RecordTransformationProcessor <t3tsref:RecordTransformationProcessor>`
|
||||
(:typoscript:`record-transformation`) or by collecting content elements with the
|
||||
:ref:`PageContentFetchingProcessor <t3tsref:PageContentFetchingProcessor>`
|
||||
(:typoscript:`page-content`).
|
||||
|
||||
The Records API - introduced together with the Schema API in :issue:`104002` -
|
||||
now expands the record's values for most common field types (known
|
||||
from the TCA Schema) from their raw database value into "rich-flavored" values,
|
||||
which might be :php-short:`\TYPO3\CMS\Core\Domain\Record`,
|
||||
:php-short:`\TYPO3\CMS\Core\Resource\FileReference`,
|
||||
:php:`\TYPO3\CMS\Core\Resource\Folder` or :php:`\DateTimeImmutable` objects.
|
||||
|
||||
This works for the following "relation" TCA types:
|
||||
|
||||
* :php:`category`
|
||||
* :php:`file`
|
||||
* :php:`folder`
|
||||
* :php:`group`
|
||||
* :php:`inline`
|
||||
* :php:`select` with :php:`MM` and :php:`foreign_table`
|
||||
|
||||
In addition, the values of following TCA types are also resolved and
|
||||
expanded automatically:
|
||||
|
||||
* :php:`datetime`
|
||||
* :php:`flex`
|
||||
* :php:`json`
|
||||
* :php:`link`
|
||||
* :php:`select` with a static list of entries
|
||||
|
||||
Each of the fields receives a full-fledged resolved value, based on the field
|
||||
configuration from TCA.
|
||||
|
||||
In case of relations (:php:`category`, :php:`group`, :php:`inline`,
|
||||
:php:`select` with :php:`MM` and :php:`foreign_table`), a collection
|
||||
(:php:`LazyRecordCollection`) of new :php-short:`\TYPO3\CMS\Core\Domain\Record` objects is attached as
|
||||
value. In case of :php:`file`, a collection (:php:`LazyFileReferenceCollection`)
|
||||
of :php:`FileReference` objects and in case of type :php:`folder`, a collection
|
||||
(:php:`LazyFolderCollection`) of :php:`Folder` objects are attached.
|
||||
|
||||
.. note::
|
||||
|
||||
The relations are only resolved once they are accessed - also known as
|
||||
"lazy loading". This allows for recursion and circular dependencies to be
|
||||
managed automatically. It is therefore also possible that the collection
|
||||
is actually empty.
|
||||
|
||||
|
||||
Example
|
||||
=======
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<f:for each="{myContent.main.records}" as="record">
|
||||
<f:for each="{record.image}" as="image">
|
||||
<f:image image="{image}" />
|
||||
</f:for>
|
||||
</f:for>
|
||||
|
||||
New TCA option `relationship`
|
||||
=============================
|
||||
|
||||
In order to define cardinality on TCA level, the option :php:`relationship` is
|
||||
introduced for all "relation" TCA types listed above. If this option is set to
|
||||
:php:`oneToOne` or :php:`manyToOne`, then relations are resolved directly
|
||||
without being wrapped into collection objects. In case the relation can
|
||||
not be resolved, :php:`NULL` is returned.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'image' => [
|
||||
'config' => [
|
||||
'type' => 'file',
|
||||
'relationship' => 'manyToOne',
|
||||
]
|
||||
]
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<f:for each="{myContent.main.records}" as="record">
|
||||
<f:image image="{record.image}" />
|
||||
</f:for>
|
||||
|
||||
.. note::
|
||||
|
||||
The TCA option :php:`maxitems` does not influence this behavior. This means
|
||||
it is possible to have a :php:`oneToMany` relation with maximum one value
|
||||
allowed. This way, overrides of this value will not break functionality.
|
||||
|
||||
Field expansion
|
||||
===============
|
||||
|
||||
For TCA type :php:`flex`, the corresponding FlexForm is resolved and therefore
|
||||
all values within this FlexForm are processed and expanded as well.
|
||||
|
||||
Fields of TCA type :php:`datetime` will be transformed into a full
|
||||
:php:`\DateTimeInterface` object.
|
||||
|
||||
Fields of TCA type :php:`json` will provide the decoded JSON value.
|
||||
|
||||
Fields of TCA type :php:`link` will provide the
|
||||
:php:`\TYPO3\CMS\Core\LinkHandling\TypolinkParameter` object,
|
||||
which is an object oriented representation of the corresponding TypoLink
|
||||
:typoscript:`parameter` configuration.
|
||||
|
||||
Fields of TCA type :php:`select` without a :php:`relationship` will always provide
|
||||
an array of static values.
|
||||
|
||||
.. note::
|
||||
|
||||
TYPO3 tries to automatically resolve the :php:`relationship` for type
|
||||
:php:`select` fields, which use :php:`renderType=selectSingle` and
|
||||
having a :php:`foreign_table` set. This means, in case no
|
||||
:php:`relationship` has been defined yet, it is set to either :php:`manyToOne`
|
||||
as the default or :php:`manyToMany` for fields with option :php:`MM`.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
When using :php-short:`\TYPO3\CMS\Core\Domain\Record` objects through the
|
||||
:php:`\TYPO3\CMS\Core\Domain\RecordFactory` API, e.g. via
|
||||
:ref:`RecordTransformationProcessor <t3tsref:RecordTransformationProcessor>`
|
||||
(:typoscript:`record-transformation`) or
|
||||
:ref:`PageContentFetchingProcessor <t3tsref:PageContentFetchingProcessor>`
|
||||
(`page-content`), the corresponding :php-short:`\TYPO3\CMS\Core\Domain\Record`
|
||||
objects are now automatically processed and enriched.
|
||||
|
||||
Those can not only be used in the frontend but also for Backend Previews in
|
||||
the page module. This is possible by configuring a Fluid Template via Page
|
||||
TSconfig to be used for the page preview rendering:
|
||||
|
||||
|
||||
.. code-block:: typoscript
|
||||
|
||||
mod.web_layout.tt_content.preview {
|
||||
textmedia = EXT:site/Resources/Private/Templates/Preview/Textmedia.html
|
||||
}
|
||||
|
||||
In such template the newly available variable :html:`{record}` can be used to
|
||||
access the resolved field values. It is advised to migrate existing preview
|
||||
templates to this new object, as the former values will probably vanish in the
|
||||
next major version.
|
||||
|
||||
By utilizing the new API for fetching records and content elements, the need
|
||||
for further data processors, e.g.
|
||||
:php-short:`\TYPO3\CMS\Frontend\DataProcessing\FilesProcessor` (:typoscript:`files`),
|
||||
becomes superfluous since all relations are resolved automatically when
|
||||
requested.
|
||||
|
||||
.. index:: Backend, FlexForm, Frontend, TCA, ext:core
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-103789-1714805317:
|
||||
|
||||
=========================================================================
|
||||
Feature: #103789 - Add "close"-button to page layout, if returnUrl is set
|
||||
=========================================================================
|
||||
|
||||
See :issue:`103789`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
A "close"-button is now displayed in the page module, if the `returnUrl`
|
||||
argument is set. When this button is clicked, the previous module
|
||||
leading to the page module (or a custom link defined in `returnUrl`) will be displayed
|
||||
again.
|
||||
|
||||
In order to utilize this, backend module links set in extensions must pass the `returnUrl`
|
||||
argument. If `returnUrl` is not set, the "close"-button will not be displayed.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Here is an example, using the Fluid :fluid:`<be:moduleLink>` ViewHelper:
|
||||
|
||||
.. code-block:: html
|
||||
:caption: Fluid example
|
||||
|
||||
<a href="{be:moduleLink(route:'web_layout', arguments:'{id:pageUid, returnUrl: returnUrl}')}"
|
||||
class="btn btn-default"
|
||||
title="{f:translate(key: 'LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:title')}">
|
||||
<core:icon identifier="actions-document" size="small"/>
|
||||
</a>
|
||||
|
||||
The behaviour is similar to the :html:`<be:uri.editRecord>` ViewHelper,
|
||||
where setting the `returnUrl` argument will also cause a "close"-button to
|
||||
be displayed.
|
||||
|
||||
.. important::
|
||||
|
||||
When using the :fluid:`<be:uri.editRecord>` ViewHelper, `returnUrl` is
|
||||
passed directly as argument. However, using :fluid:`<be:moduleLink>`, the
|
||||
`returnUrl` argument must be passed as an additional parameter via the Fluid
|
||||
ViewHelper's argument :fluid:`arguments` or :fluid:`query`.
|
||||
|
||||
The `returnUrl` should usually return to the calling (originating) module.
|
||||
|
||||
You can build the `returnUrl` with the Fluid ViewHelper :fluid:`be:uri`:
|
||||
|
||||
.. code-block:: html
|
||||
:caption: Fluid example for building returnUrl to module "linkvalidator"
|
||||
|
||||
<f:be.uri route="web_linkvalidator" parameters="{id: pageUid}"/>
|
||||
|
||||
Here is an example for building the `returnUrl` via PHP:
|
||||
|
||||
.. code-block:: php
|
||||
:caption: Backend module controller
|
||||
|
||||
use TYPO3\CMS\Backend\Routing\UriBuilder;
|
||||
|
||||
public function __construct(
|
||||
protected readonly UriBuilder $uriBuilder
|
||||
) {}
|
||||
|
||||
protected function generateModuleUri(array $parameters = []): string
|
||||
{
|
||||
return $this->uriBuilder->buildUriFromRoute('web_linkvalidator', $parameters);
|
||||
}
|
||||
|
||||
public function __invoke(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
// ...
|
||||
$this->view->assign('returnUrl', $this->generateModuleUri(['pageUid' => $this->id]));
|
||||
// ...
|
||||
}
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
The change has no impact, unless the functionality is being used. Extension
|
||||
authors can make use of the new functionality to also conveniently link back to an originating
|
||||
or custom module for a streamlined linear backend user-experience.
|
||||
|
||||
.. index:: Backend, ext:backend
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104126-1714290385:
|
||||
|
||||
===========================================================================
|
||||
Feature: #104126 - Add configuration setting to define backend-locking file
|
||||
===========================================================================
|
||||
|
||||
See :issue:`104126`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
TYPO3 supports the ability to lock the backend for maintenance reasons. This
|
||||
is controlled with a :file:`LOCK_BACKEND` file that was previously stored in
|
||||
:path:`typo3conf/`.
|
||||
|
||||
With :ref:`<important-104126-1714290385>` this directory is no longer needed,
|
||||
so now the location to this file can be adjusted via the new configuration setting
|
||||
:php:`$GLOBALS['TYPO3_CONF_VARS']['BE']['lockBackendFile']`.
|
||||
|
||||
When empty, it falls back to a file :file:`LOCK_BACKEND`, which is now stored
|
||||
by default in:
|
||||
|
||||
* :path:`var/lock/` for Composer Mode
|
||||
* :path:`config/` for Legacy Mode
|
||||
|
||||
If you previously manually maintained the :file:`LOCK_BACKEND` file (for example via
|
||||
deployment or other maintenance automation), please either adjust
|
||||
your automations to the new file location, or change the setting to the desired file location,
|
||||
or at best use the CLI commands :bash:`vendor/bin/typo3 backend:lock` and
|
||||
:bash:`vendor/bin/typo3 backend:unlock`.
|
||||
|
||||
The backend locking functionality is now contained in a distinct service class
|
||||
:php:`\TYPO3\CMS\Backend\Authentication\BackendLocker` to allow future flexibility.
|
||||
|
||||
When upgrading an installation to Composer Mode with a locked backend in effect,
|
||||
please ensure your backend can remain locked by moving (or copying) the file to the new
|
||||
location :path:`var/lock/`.
|
||||
|
||||
Remember, if you want locked backend state to persist between deployments, ensure that the
|
||||
used directory (:path:`var/lock` by default) is shared between deployment releases.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
The location for :file:`LOCK_BACKEND` to lock (and unlock) the backend can now be controlled
|
||||
by maintainers of a TYPO3 installation, and has moved outside of :path:`typo3conf/` by default
|
||||
to either :path:`var/lock/` (Composer) or :path:`config/` (Legacy).
|
||||
|
||||
.. index:: Backend, CLI, LocalConfiguration, ext:backend
|
||||
@@ -0,0 +1,95 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104168-1719373149:
|
||||
|
||||
=======================================================
|
||||
Feature: #104168 - PSR-14 event for modifying countries
|
||||
=======================================================
|
||||
|
||||
See :issue:`104168`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
A new PSR-14 event :php:`\TYPO3\CMS\Core\Country\Event\BeforeCountriesEvaluatedEvent`
|
||||
has been introduced to modify the list of countries provided by
|
||||
:php:`\TYPO3\CMS\Core\Country\CountryProvider`.
|
||||
|
||||
This event allows to add, remove and alter countries from the list used by the
|
||||
provider class itself and ViewHelpers like :html:`<f:form.countrySelect />`.
|
||||
|
||||
.. note::
|
||||
The DTO :php:`\TYPO3\CMS\Core\Country\Country`
|
||||
uses `EXT:core/Resources/Private/Language/Iso/countries.xlf` for translating
|
||||
the country names.
|
||||
|
||||
If additional countries are added, add translations to `countries.xlf`
|
||||
via :ref:`locallangXMLOverride <t3coreapi:xliff-translating-custom>`.
|
||||
|
||||
|
||||
Example
|
||||
=======
|
||||
|
||||
An example corresponding event listener class:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyVendor\MyExtension\EventListener;
|
||||
|
||||
use TYPO3\CMS\Core\Attribute\AsEventListener;
|
||||
use TYPO3\CMS\Core\Country\Country;
|
||||
use TYPO3\CMS\Core\Country\Event\BeforeCountriesEvaluatedEvent;
|
||||
|
||||
final readonly class EventListener
|
||||
{
|
||||
#[AsEventListener(identifier: 'my-extension/before-countries-evaluated')]
|
||||
public function __invoke(BeforeCountriesEvaluatedEvent $event): void
|
||||
{
|
||||
$countries = $event->getCountries();
|
||||
unset($countries['BS']);
|
||||
$countries['XX'] = new Country(
|
||||
'XX',
|
||||
'XYZ',
|
||||
'Magic Kingdom',
|
||||
'987',
|
||||
'🔮',
|
||||
'Kingdom of Magic and Wonders'
|
||||
);
|
||||
$event->setCountries($countries);
|
||||
}
|
||||
}
|
||||
|
||||
.. code-block:: php
|
||||
:caption: EXT:my_extension/ext_localconf.php
|
||||
|
||||
$GLOBALS['TYPO3_CONF_VARS']['SYS']['locallangXMLOverride']
|
||||
['EXT:core/Resources/Private/Language/Iso/countries.xlf'][]
|
||||
= 'EXT:my_extension/Resources/Private/Language/countries.xlf';
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: EXT:my_extension/Resources/Private/Language/countries.xlf
|
||||
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<xliff version="1.0">
|
||||
<file source-language="en" datatype="plaintext" date="2024-01-08T18:44:59Z" product-name="my_extension">
|
||||
<body>
|
||||
<trans-unit id="XX.name" approved="yes">
|
||||
<source>Magic Kingdom</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="XX.official_name" approved="yes">
|
||||
<source>Kingdom of Magic and Wonders</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Using the PSR-14 event :php-short:`\TYPO3\CMS\Core\Country\Event\BeforeCountriesEvaluatedEvent` allows
|
||||
modification of countries provided by :php-short:`\TYPO3\CMS\Core\Country\CountryProvider`.
|
||||
|
||||
.. index:: PHP-API, ext:core
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104221-1715591178:
|
||||
|
||||
========================================================================
|
||||
Feature: #104221 - PSR-14 events for RTE <-> Persistence transformations
|
||||
========================================================================
|
||||
|
||||
See :issue:`104221`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
When using an RTE HTML content element, two transformations
|
||||
take place within the TYPO3 backend:
|
||||
|
||||
* From database: Fetching the current content from the database (`persistence`) and
|
||||
preparing it to be displayed inside the RTE HTML component.
|
||||
* To database: Retrieving the data returned by the RTE and preparing it to
|
||||
be persisted into the database.
|
||||
|
||||
This takes place in the :php:`\TYPO3\CMS\Core\Html\RteHtmlParser` class, by utilizing the
|
||||
methods :php:`transformTextForRichTextEditor` and :php:`transformTextForPersistence`.
|
||||
|
||||
With :issue:`96107` and :issue:`92992`, the former hook
|
||||
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['transformation']`
|
||||
was removed, which took care of applying custom user-transformations. The suggested replacement
|
||||
for this was to use the actual RTE YAML configuration and API like :php:`allowAttributes`.
|
||||
|
||||
Now, four PSR-14 Events are introduced to allow more granular control over data for
|
||||
`persistence -> RTE` and `RTE -> persistence`. This allows developers to apply
|
||||
more customized transformations, apart from the internal and API ones:
|
||||
|
||||
Modify data when saving RTE content to the database (persistence):
|
||||
|
||||
* :php:`\TYPO3\CMS\Core\Html\Event\BeforeTransformTextForPersistenceEvent`
|
||||
* :php:`\TYPO3\CMS\Core\Html\Event\AfterTransformTextForPersistenceEvent`
|
||||
|
||||
Modify data when retrieving content from the database and pass to the RTE:
|
||||
|
||||
* :php:`\TYPO3\CMS\Core\Html\Event\BeforeTransformTextForRichTextEditorEvent`
|
||||
* :php:`\TYPO3\CMS\Core\Html\Event\AfterTransformTextForRichTextEditorEvent`
|
||||
|
||||
All four events have the same structure (for now):
|
||||
|
||||
* :php:`getHtmlContent()` - retrieve the current HTML content
|
||||
* :php:`setHtmlContent()` - used to set modifications of the HTML content
|
||||
* :php:`getInitialHtmlContent()` - retrieve the untampered initial HTML content
|
||||
* :php:`getProcessingConfiguration()` - retrieve processing configuration array
|
||||
|
||||
The event is meant to be used so that developers can change the HTML content
|
||||
either `before` the internal TYPO3 modifications, or `after` those.
|
||||
|
||||
The `before` events are executed *before* TYPO3 applied any kind of internal transformations,
|
||||
like for links. Event Listeners that want to modify output so that
|
||||
TYPO3 additionally operates on that, should listen to those `before`-Events.
|
||||
|
||||
When Event Listeners want to perform on the final result, the corresponding `after`-Events
|
||||
should be utilized.
|
||||
|
||||
Event listeners can use :php:`$value = $event->getHtmlContent()` to get the current contents,
|
||||
apply changes to `$value` and then store the manipulated data via `$event->setHtmlContent($value)`,
|
||||
see example:
|
||||
|
||||
Example
|
||||
=======
|
||||
|
||||
An event listener class is constructed which will take an RTE input *TYPO3* and internally
|
||||
store it in the database as *[tag:typo3]*. This could allow a content element data processor
|
||||
in the frontend to handle this part of the content with for example internal glossary operations.
|
||||
|
||||
The workflow would be:
|
||||
|
||||
* Editor enters "TYPO3" in the RTE instance.
|
||||
* When saving, this gets stored as "[tag:typo3]".
|
||||
* When the editor sees the RTE instance again, "[tag:typo3]" gets replaced to "TYPO3" again.
|
||||
* So: The editor will always only see "TYPO3" and not know how it is internally handled.
|
||||
* The frontend output receives "[tag:typo3]" and could do its own content element magic,
|
||||
other services accessing the database could also use the parseable representation.
|
||||
|
||||
The corresponding event listener class:
|
||||
|
||||
.. code-block:: php
|
||||
:caption: EXT:MyExtension/Classes/EventListener/TransformListener.php
|
||||
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyVendor\MyExtension\EventListener;
|
||||
|
||||
use TYPO3\CMS\Core\Attribute\AsEventListener;
|
||||
|
||||
class TransformListener
|
||||
{
|
||||
/**
|
||||
* Transforms the current value the RTE delivered into a value that is stored (persisted) in the database.
|
||||
*/
|
||||
#[AsEventListener('rtehtmlparser/modify-data-for-persistence')]
|
||||
public function modifyPersistence(AfterTransformTextForPersistenceEvent $event): void
|
||||
{
|
||||
$value = $event->getHtmlContent();
|
||||
$value = str_replace('TYPO3', '[tag:typo3]', $value);
|
||||
$event->setHtmlContent($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the current persisted value into something the RTE can display
|
||||
*/
|
||||
#[AsEventListener('rtehtmlparser/modify-data-for-richtexteditor')]
|
||||
public function modifyRichTextEditor(AfterTransformTextForRichTextEditorEvent $event): void
|
||||
{
|
||||
$value = $event->getHtmlContent();
|
||||
$value = str_replace('[tag:typo3]', 'TYPO3', $value);
|
||||
$event->setHtmlContent($value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Using the new PSR-14 events
|
||||
|
||||
* :php:`\TYPO3\CMS\Core\Html\Event\BeforeTransformTextForPersistenceEvent`
|
||||
* :php:`\TYPO3\CMS\Core\Html\Event\AfterTransformTextForPersistenceEvent`
|
||||
* :php:`\TYPO3\CMS\Core\Html\Event\BeforeTransformTextForRichTextEditorEvent`
|
||||
* :php:`\TYPO3\CMS\Core\Html\Event\AfterTransformTextForRichTextEditorEvent`
|
||||
|
||||
allows to apply custom transformations for `database <-> RTE content`
|
||||
transformations.
|
||||
|
||||
|
||||
.. index:: Backend, PHP-API, ext:core
|
||||
@@ -0,0 +1,465 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104311-1720176189:
|
||||
|
||||
==================================================
|
||||
Feature: #104311 - Auto created system TCA columns
|
||||
==================================================
|
||||
|
||||
See :issue:`104311`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
There are various :php:`TCA` table :php:`ctrl` settings that define fields used
|
||||
to enable certain TYPO3 table capabilities and to specify the database column
|
||||
to store this row state.
|
||||
|
||||
An example is :php:`$GLOBALS['TCA']['ctrl']['enablecolumns']['starttime'] = 'starttime'`, which
|
||||
makes the table "start time aware", resulting in the automatic exclusion of a record
|
||||
if the given start time is in the future, when rendered in the frontend.
|
||||
|
||||
Such :php:`ctrl` settings require TCA :php:`columns` definitions. Default definitions
|
||||
of such :php:`columns` are now automatically added to :php:`TCA` if not manually
|
||||
configured. Extension developers can now remove and avoid a significant amount
|
||||
of boilerplate field definitions in :php:`columns` and rely on TYPO3 Core to create
|
||||
them automatically. Note the Core does *not* automatically add such columns to TCA
|
||||
:php:`types` or :php:`palettes` definitions: Developers still need to place them,
|
||||
to show the columns when editing record rows, and need to add according access
|
||||
permissions.
|
||||
|
||||
Let us have a quick look on what happened within TCA and its surrounding code lately,
|
||||
to see how this feature embeds within the general TYPO3 Core strategy in this area
|
||||
and why the above feature has been implemented at this point in time:
|
||||
|
||||
TCA has always been a central cornerstone of TYPO3. The TYPO3 Core strives to maintain
|
||||
this central part while simplifying and streamlining less desirable details.
|
||||
|
||||
TYPO3 version v12 aimed to simplify single column definitions by implementing new
|
||||
column types like :php:`file`, :php:`category`, :php:`email`, and more. These are
|
||||
much easier to understand and require far fewer single property definitions than
|
||||
previous solutions. With this in place, auto-creation of database column
|
||||
definitions derived from TCA has been established with TYPO3 v13, making the
|
||||
manual definition of database table schemas in :file:`ext_tables.sql` largely
|
||||
unnecessary. Additionally, an object-oriented approach called
|
||||
:php-short:`\TYPO3\CMS\Core\Schema\TcaSchema` has
|
||||
been introduced to harmonize and simplify information retrieval from TCA.
|
||||
|
||||
With the step described in this document - the auto-creation of TCA columns from
|
||||
:php:`ctrl` properties - the amount of manual boilerplate definitions is
|
||||
significantly reduced, and the TYPO3 Core gains more control over these columns to
|
||||
harmonize these fields throughout the system. Note that the TYPO3 Core has not yet
|
||||
altered the structure of TCA :php:`types` and :php:`palettes`. This will be one of
|
||||
the next steps in this area, but details have not been decided upon yet.
|
||||
|
||||
All these steps streamline TCA and its surrounding areas, simplify the system,
|
||||
and reduce the amount of details developers need to be aware of when defining
|
||||
their own tables and fields.
|
||||
|
||||
This document details the "column auto-creation from 'ctrl' fields" feature: It
|
||||
first lists all affected settings with their derived default definitions. It
|
||||
concludes with a section relevant for instances that still need to override
|
||||
certain defaults of these columns by explaining the order of files and classes
|
||||
involved in building TCA and the available options to change defaults and where
|
||||
to place these changes.
|
||||
|
||||
Auto-created columns from 'ctrl'
|
||||
--------------------------------
|
||||
|
||||
The configuration settings below enable single table capabilities. Their values
|
||||
are a database column name responsible for storing the row data of the capability.
|
||||
|
||||
If a setting is defined in a "base" TCA table file (:path:`Configuration/TCA`, not
|
||||
in :path:`Configuration/TCA/Overrides`), the TYPO3 Core will add default :php:`columns`
|
||||
definition for this field name if no definition exists in a base file.
|
||||
|
||||
`$GLOBALS['TCA']['ctrl']['enablecolumns']['disabled']`
|
||||
......................................................
|
||||
|
||||
This setting makes database table rows "disable aware": A row with this flag
|
||||
being set to 1 is not rendered in the frontend to casual website users.
|
||||
|
||||
Typical usage:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'ctrl' => [
|
||||
'enablecolumns' => [
|
||||
'disabled' => 'disabled',
|
||||
],
|
||||
],
|
||||
|
||||
Default configuration added by the TYPO3 Core:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'disabled' => [
|
||||
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.enabled',
|
||||
'exclude' => true,
|
||||
'config' => [
|
||||
'type' => 'check',
|
||||
'renderType' => 'checkboxToggle',
|
||||
'default' => 0,
|
||||
'items' => [
|
||||
[
|
||||
'label' => '',
|
||||
'invertStateDisplay' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
`$GLOBALS['TCA']['ctrl']['enablecolumns']['starttime']`
|
||||
.......................................................
|
||||
|
||||
This setting makes database table rows "starttime aware": A row having a start
|
||||
time in the future is not rendered in the frontend.
|
||||
|
||||
Typical usage:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'ctrl' => [
|
||||
'enablecolumns' => [
|
||||
'starttime' => 'starttime',
|
||||
],
|
||||
],
|
||||
|
||||
Default configuration added by the TYPO3 Core:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'starttime' => [
|
||||
'exclude' => true,
|
||||
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime',
|
||||
'config' => [
|
||||
'type' => 'datetime',
|
||||
'default' => 0,
|
||||
],
|
||||
],
|
||||
|
||||
`$GLOBALS['TCA']['ctrl']['enablecolumns']['endtime']`
|
||||
.....................................................
|
||||
|
||||
This setting makes database table rows "endtime aware": A row having an end
|
||||
time in the past is not rendered in the frontend.
|
||||
|
||||
Typical usage:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'ctrl' => [
|
||||
'enablecolumns' => [
|
||||
'endtime' => 'endtime',
|
||||
],
|
||||
],
|
||||
|
||||
Default configuration added by the TYPO3 Core:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'endtime' => [
|
||||
'exclude' => true,
|
||||
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime',
|
||||
'config' => [
|
||||
'type' => 'datetime',
|
||||
'default' => 0,
|
||||
'range' => [
|
||||
'upper' => mktime(0, 0, 0, 1, 1, 2106),
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
`$GLOBALS['TCA']['ctrl']['enablecolumns']['fe_group']`
|
||||
......................................................
|
||||
|
||||
This setting makes database table rows "frontend group aware": A row can be defined
|
||||
to be shown only to frontend users who are a member of selected groups.
|
||||
|
||||
Typical usage:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'ctrl' => [
|
||||
'enablecolumns' => [
|
||||
'fe_group' => 'fe_group',
|
||||
],
|
||||
],
|
||||
|
||||
Default configuration added by the TYPO3 Core:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'fe_group' => [
|
||||
'exclude' => true,
|
||||
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.fe_group',
|
||||
'config' => [
|
||||
'type' => 'select',
|
||||
'renderType' => 'selectMultipleSideBySide',
|
||||
'size' => 5,
|
||||
'maxitems' => 20,
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.hide_at_login',
|
||||
'value' => -1,
|
||||
],
|
||||
[
|
||||
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.any_login',
|
||||
'value' => -2,
|
||||
],
|
||||
[
|
||||
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.usergroups',
|
||||
'value' => '--div--',
|
||||
],
|
||||
],
|
||||
'exclusiveKeys' => '-1,-2',
|
||||
'foreign_table' => 'fe_groups',
|
||||
],
|
||||
],
|
||||
|
||||
`$GLOBALS['TCA']['ctrl']['editlock']`
|
||||
.....................................
|
||||
|
||||
This setting makes database table rows "backend lock aware": A row with this
|
||||
being flag enabled can only be edited by backend administrators.
|
||||
|
||||
Typical usage:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'ctrl' => [
|
||||
'editlock' => 'editlock',
|
||||
],
|
||||
|
||||
Default configuration added by the TYPO3 Core:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'endtime' => [
|
||||
'displayCond' => 'HIDE_FOR_NON_ADMINS',
|
||||
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:editlock',
|
||||
'config' => [
|
||||
'type' => 'check',
|
||||
'renderType' => 'checkboxToggle',
|
||||
],
|
||||
],
|
||||
|
||||
`$GLOBALS['TCA']['ctrl']['descriptionColumn']`
|
||||
..............................................
|
||||
|
||||
This setting makes database table rows "description aware": Backend editors
|
||||
have a database field to add row specific notes.
|
||||
|
||||
Typical usage:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'ctrl' => [
|
||||
'descriptionColumn' => 'description',
|
||||
],
|
||||
|
||||
Default configuration added by the TYPO3 Core:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'description' => [
|
||||
'exclude' => true,
|
||||
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.description',
|
||||
'config' => [
|
||||
'type' => 'text',
|
||||
'rows' => 5,
|
||||
'cols' => 30,
|
||||
'max' => 2000,
|
||||
],
|
||||
],
|
||||
|
||||
`$GLOBALS['TCA']`['ctrl']['languageField']` and `transOrigPointerField`
|
||||
.......................................................................
|
||||
|
||||
These setting make database table rows "localization aware": Backend editors
|
||||
can create localized versions of a record. Note when :php:`languageField` is
|
||||
set, and :php:`transOrigPointerField` is not, the TYPO3 Core will automatically set
|
||||
:php:`transOrigPointerField` to :php:`l10n_parent` since both fields must be
|
||||
always set in combination.
|
||||
|
||||
Typical usage:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'ctrl' => [
|
||||
'languageField' => 'sys_language_uid',
|
||||
'transOrigPointerField' => 'l10n_parent',
|
||||
],
|
||||
|
||||
Default configuration added by the TYPO3 Core, note string :php:`$table` corresponds
|
||||
to the current table name.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'sys_language_uid' => [
|
||||
'exclude' => true,
|
||||
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language',
|
||||
'config' => [
|
||||
'type' => 'language',
|
||||
],
|
||||
],
|
||||
'l10n_parent' => [
|
||||
'displayCond' => 'FIELD:sys_language_uid:>:0',
|
||||
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
|
||||
'config' => [
|
||||
'type' => 'select',
|
||||
'renderType' => 'selectSingle',
|
||||
'items' => [
|
||||
[
|
||||
'label' => '',
|
||||
'value' => 0,
|
||||
],
|
||||
],
|
||||
'foreign_table' => $table,
|
||||
'foreign_table_where' => 'AND {#' . $table . '}.{#pid}=###CURRENT_PID### AND {#' . $table . '}.{#' . $languageFieldName . '} IN (-1,0)',
|
||||
'default' => 0,
|
||||
],
|
||||
],
|
||||
|
||||
`$GLOBALS['TCA']['ctrl']['transOrigDiffSourceField']`
|
||||
.....................................................
|
||||
|
||||
This setting makes database table rows "parent language record change aware": Backend
|
||||
editors can have an indicator when the parent column has been changed.
|
||||
|
||||
Typical usage:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'ctrl' => [
|
||||
'transOrigDiffSourceField' = 'l10n_diffsource',
|
||||
],
|
||||
|
||||
Default configuration added by the TYPO3 Core:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'l10n_diffsource' => [
|
||||
'config' => [
|
||||
'type' => 'passthrough',
|
||||
'default' => '',
|
||||
],
|
||||
],
|
||||
|
||||
`$GLOBALS['TCA']['ctrl']['translationSource']`
|
||||
..............................................
|
||||
|
||||
This setting makes database table rows "parent language source aware" to
|
||||
determine the difference between "connected mode" and "free mode".
|
||||
|
||||
Typical usage:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'ctrl' => [
|
||||
'translationSource' = 'l10n_source',
|
||||
],
|
||||
|
||||
Default configuration added by the TYPO3 Core:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'l10n_source' => [
|
||||
'config' => [
|
||||
'type' => 'passthrough',
|
||||
'default' => '',
|
||||
],
|
||||
],
|
||||
|
||||
Load order when building TCA
|
||||
----------------------------
|
||||
|
||||
To understand if and when TCA column auto-creation from :php:`ctrl` definitions
|
||||
kicks in, it is important to have an overview of the order of the single loading
|
||||
steps:
|
||||
|
||||
#. Load single files from extension :file:`Configuration/TCA` files
|
||||
#. NEW - Enrich :php:`columns` from :php:`ctrl` settings
|
||||
#. Load single files from extension :file:`Configuration/TCA/Overrides` files
|
||||
#. Apply TCA migrations
|
||||
#. Apply TCA preparations
|
||||
|
||||
As a result of this strategy, :php:`columns` fields are *not* auto-created, when
|
||||
a :php:`ctrl` capability is added in a :path:`Configuration/TCA/Overrides`
|
||||
file, and *not* in a :path:`Configuration/TCA` "base" file. In general, such
|
||||
capabilities should be set in base files only: Adding them at a later point - for
|
||||
example in a different extension - is brittle and there is a risk the main
|
||||
extension can not deal with such an added capability properly.
|
||||
|
||||
Overriding definitions from auto-created TCA columns
|
||||
----------------------------------------------------
|
||||
|
||||
I most cases, developers do not need to change definitions of :php:`columns`
|
||||
auto-created by the TYPO3 Core. In general, it is advisable to not actively do this.
|
||||
Developers who still want to change detail properties of such columns should
|
||||
generally stick to "display" related details only.
|
||||
|
||||
There are two options to have own definitions: When a column is already defined
|
||||
in a "base" TCA file (:file:`Configuration/TCA`), the TYPO3 Core will not override it.
|
||||
Alternatively, a developer can decide to let the TYPO3 Core auto-create a column, to
|
||||
then override single properties in :file:`Configuration/TCA/Overrides` files.
|
||||
|
||||
As example, "base" :php:`pages` file defines this (step 1 above):
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'ctrl' => [
|
||||
'enablecolumns' => [
|
||||
'disabled' => 'disabled',
|
||||
],
|
||||
],
|
||||
|
||||
The TYPO3 Core thus creates this :php:`columns` definition (step 2 above):
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'columns' => [
|
||||
'disabled' => [
|
||||
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.enabled',
|
||||
'exclude' => true,
|
||||
'config' => [
|
||||
'type' => 'check',
|
||||
'renderType' => 'checkboxToggle',
|
||||
'default' => 0,
|
||||
'items' => [
|
||||
[
|
||||
'label' => '',
|
||||
'invertStateDisplay' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
When an editor creates a new page, it should be "disabled" by default to
|
||||
avoid having a new page online in the website before it is set up completely.
|
||||
A :file:`Configuration/TCA/Overrides/pages.php` file does this:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
// New pages are disabled by default
|
||||
$GLOBALS['TCA']['pages']['columns']['hidden']['config']['default'] = 1;
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Extension developers can typically remove :php:`columns` definitions of all the
|
||||
above fields and rely on TYPO3 Core creating them with a good default
|
||||
definition.
|
||||
|
||||
It is only required to define the desired table capabilities in :php:`ctrl` with
|
||||
its field names, and the system will create the according :php:`columns`
|
||||
definitions automatically.
|
||||
|
||||
|
||||
.. index:: TCA, ext:core
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104321-1720369379:
|
||||
|
||||
====================================================================================
|
||||
Feature: #104321 - Allow handling of argument mapping exceptions in ActionController
|
||||
====================================================================================
|
||||
|
||||
See :issue:`104321`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
A new method :php:`handleArgumentMappingExceptions` has been introduced in
|
||||
Extbase :php:`\TYPO3\CMS\Extbase\Mvc\Controller\ActionController` to improve
|
||||
handling of exceptions that occur during argument mapping.
|
||||
|
||||
The new method supports optional handling of the following exceptions:
|
||||
|
||||
* :php:`\TYPO3\CMS\Extbase\Property\Exception\TargetNotFoundException`,
|
||||
which occurs, when a given object UID can not be resolved to an existing record.
|
||||
* :php:`\TYPO3\CMS\Extbase\Mvc\Controller\Exception\RequiredArgumentMissingException`,
|
||||
which occurs, when a required action argument is missing.
|
||||
|
||||
Handling of the exceptions can be enabled globally with the following TypoScript
|
||||
configuration.
|
||||
|
||||
* :typoscript:`config.tx_extbase.mvc.showPageNotFoundIfTargetNotFoundException = 1`
|
||||
* :typoscript:`config.tx_extbase.mvc.showPageNotFoundIfRequiredArgumentIsMissingException = 1`
|
||||
|
||||
The exception handling can also be configured on extension level with the
|
||||
following TypoScript configuration.
|
||||
|
||||
* :typoscript:`plugin.tx_yourextension.mvc.showPageNotFoundIfTargetNotFoundException = 1`
|
||||
* :typoscript:`plugin.tx_yourextension.mvc.showPageNotFoundIfRequiredArgumentIsMissingException = 1`
|
||||
* :typoscript:`plugin.tx_yourextension_plugin1.mvc.showPageNotFoundIfTargetNotFoundException = 1`
|
||||
* :typoscript:`plugin.tx_yourextension_plugin1.mvc.showPageNotFoundIfRequiredArgumentIsMissingException = 1`
|
||||
|
||||
By default, these options are set to `0`, which will lead to exceptions
|
||||
being thrown (and would lead to errors, if not caught). This is the current
|
||||
behavior of TYPO3.
|
||||
|
||||
When setting one of these values to `1`, the configured exceptions will not be thrown.
|
||||
Instead, a :php:`pageNotFound` response is propagated, resulting in a 404 error being
|
||||
shown.
|
||||
|
||||
Additionally, extension authors can extend or override the method
|
||||
:php:`handleArgumentMappingExceptions` in relevant Controllers in order
|
||||
to implement custom argument mapping exception handling.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Extension authors can now handle exceptions in implementations of a
|
||||
:php-short:`\TYPO3\CMS\Extbase\Mvc\Controller\ActionController`,
|
||||
which are thrown during argument mapping.
|
||||
|
||||
.. index:: Frontend, ext:extbase
|
||||
@@ -0,0 +1,82 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104451-1721646565:
|
||||
|
||||
===========================================================
|
||||
Feature: #104451 - Redis backends support for key prefixing
|
||||
===========================================================
|
||||
|
||||
See :issue:`104451`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
It is now possible to add a dedicated key prefix for all invocations of a Redis
|
||||
cache or session backend. This allows to use the same Redis database for multiple
|
||||
caches or even for multiple TYPO3 instances if the provided prefix is unique.
|
||||
|
||||
Possible use cases are:
|
||||
|
||||
* Using Redis caching for multiple caches, if only one Redis database is available
|
||||
* Pre-fill caches upon deployments using a new prefix (zero downtime deployments)
|
||||
|
||||
.. code-block:: php
|
||||
:caption: additional.php example for using Redis as session backend
|
||||
|
||||
$GLOBALS['TYPO3_CONF_VARS']['SYS']['session']['BE'] = [
|
||||
'backend' => \TYPO3\CMS\Core\Session\Backend\RedisSessionBackend::class,
|
||||
'options' => [
|
||||
'hostname' => 'redis',
|
||||
'database' => '11',
|
||||
'compression' => true,
|
||||
'keyPrefix' => 'be_sessions_',
|
||||
],
|
||||
];
|
||||
$GLOBALS['TYPO3_CONF_VARS']['SYS']['session']['FE'] = [
|
||||
'backend' => \TYPO3\CMS\Core\Session\Backend\RedisSessionBackend::class,
|
||||
'options' => [
|
||||
'hostname' => 'redis',
|
||||
'database' => '11',
|
||||
'compression' => true,
|
||||
'keyPrefix' => 'fe_sessions_',
|
||||
'has_anonymous' => true,
|
||||
],
|
||||
];
|
||||
|
||||
.. code-block:: php
|
||||
:caption: additional.php example for pages cache
|
||||
|
||||
$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['pages'] = [
|
||||
'backend' => \TYPO3\CMS\Core\Cache\Backend\RedisBackend::class,
|
||||
'options' => [
|
||||
'hostname' => 'redis',
|
||||
'database' => 11,
|
||||
'compression' => true,
|
||||
'keyPrefix' => 'pages_';
|
||||
],
|
||||
];
|
||||
|
||||
$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['rootline'] = [
|
||||
'backend' => \TYPO3\CMS\Core\Cache\Backend\RedisBackend::class,
|
||||
'options' => [
|
||||
'hostname' => 'redis',
|
||||
'database' => 11,
|
||||
'compression' => true,
|
||||
'keyPrefix' => 'rootline_';
|
||||
],
|
||||
];
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
The new feature allows to use the same Redis database for multiple caches or even
|
||||
for multiple TYPO3 instances while having no impact on existing configuration.
|
||||
|
||||
.. attention::
|
||||
If you start using the same Redis database for multiple caches or
|
||||
using the same database also for session storage, make sure any involved
|
||||
cache configuration uses **a unique key prefix**.
|
||||
If only one of the caches does not use a key prefix, any cache flush
|
||||
operation will always flush the whole database, hence also all other caches/sessions.
|
||||
|
||||
.. index:: Frontend, LocalConfiguration, ext:core
|
||||
@@ -0,0 +1,87 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104482-1721939108:
|
||||
|
||||
========================================================
|
||||
Feature: #104482 - Add if() support to ExpressionBuilder
|
||||
========================================================
|
||||
|
||||
See :issue:`104482`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The TYPO3 :php:`\TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder`
|
||||
provides a new method to phrase "if-then-else" expressions. Those are translated
|
||||
into :sql:`IF` or :sql:`CASE` statements depending on the used database engine.
|
||||
|
||||
`ExpressionBuilder::if()`
|
||||
-------------------------
|
||||
|
||||
Creates an IF-THEN-ELSE expression.
|
||||
|
||||
.. code-block:: php
|
||||
:caption: Method signature
|
||||
|
||||
/**
|
||||
* Creates IF-THEN-ELSE expression construct compatible with all supported database vendors.
|
||||
* No automatic quoting or escaping is done, which allows to build up nested expression statements.
|
||||
*
|
||||
* **Example:**
|
||||
* ```
|
||||
* $queryBuilder
|
||||
* ->selectLiteral(
|
||||
* $queryBuilder->expr()->if(
|
||||
* $queryBuilder->expr()->eq('hidden', $queryBuilder->createNamedParameter(0, Connection::PARAM_INT)),
|
||||
* $queryBuilder->quote('page-is-visible'),
|
||||
* $queryBuilder->quote('page-is-not-visible'),
|
||||
* 'result_field_name'
|
||||
* ),
|
||||
* )
|
||||
* ->from('pages');
|
||||
* ```
|
||||
*
|
||||
* **Result with MySQL:**
|
||||
* ```
|
||||
* SELECT (IF(`hidden` = 0, 'page-is-visible', 'page-is-not-visible')) AS `result_field_name` FROM `pages`
|
||||
* ```
|
||||
*/
|
||||
public function if(
|
||||
CompositeExpression|\Doctrine\DBAL\Query\Expression\CompositeExpression|\Stringable|string $condition,
|
||||
\Stringable|string $truePart,
|
||||
\Stringable|string $falsePart,
|
||||
\Stringable|string|null $as = null
|
||||
): string {
|
||||
$platform = $this->connection->getDatabasePlatform();
|
||||
$pattern = match (true) {
|
||||
$platform instanceof DoctrineSQLitePlatform => 'IIF(%s, %s, %s)',
|
||||
$platform instanceof DoctrinePostgreSQLPlatform => 'CASE WHEN %s THEN %s ELSE %s END',
|
||||
$platform instanceof DoctrineMariaDBPlatform,
|
||||
$platform instanceof DoctrineMySQLPlatform => 'IF(%s, %s, %s)',
|
||||
default => throw new \RuntimeException(
|
||||
sprintf('Platform "%s" not supported for "%s"', $platform::class, __METHOD__),
|
||||
1721806463
|
||||
)
|
||||
};
|
||||
$expression = sprintf($pattern, $condition, $truePart, $falsePart);
|
||||
if ($as !== null) {
|
||||
$expression = $this->as(sprintf('(%s)', $expression), $as);
|
||||
}
|
||||
return $expression;
|
||||
}
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Extension authors can use the new expression method to build more advanced
|
||||
queries without the requirement to deal with the correct implementation for
|
||||
all supported database vendors.
|
||||
|
||||
.. note::
|
||||
|
||||
No automatic quoting or escaping is done for the condition and true/false
|
||||
part. Extension authors need to ensure proper quoting for each part or use
|
||||
API calls doing the quoting, for example the TYPO3 CompositeExpression or
|
||||
ExpressionBuilder calls.
|
||||
|
||||
.. index:: Database, PHP-API, ext:core
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104493-1722127314:
|
||||
|
||||
=============================================================================
|
||||
Feature: #104493 - Add `castText()` expression support to `ExpressionBuilder`
|
||||
=============================================================================
|
||||
|
||||
See :issue:`104493`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The TYPO3 :php:`\TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder`
|
||||
provides a new method to cast expression results to text like datatypes. This
|
||||
is done to large :sql:`VARCHAR/CHAR` types using the :sql:`CAST/CONVERT` or similar
|
||||
methods based on the used database engine.
|
||||
|
||||
.. note::
|
||||
|
||||
This should not be mixed with :sql:`TEXT`, :sql:`CHAR` or :sql:`VARCHAR`
|
||||
data types for column (fields) definition used to describe the structure
|
||||
of a table.
|
||||
|
||||
`ExpressionBuilder::castText()`
|
||||
-------------------------------
|
||||
|
||||
Creates a :sql:`CAST` expression.
|
||||
|
||||
.. code-block:: php
|
||||
:caption: Method signature
|
||||
|
||||
/**
|
||||
* Creates a cast for the `$expression` result to a text datatype depending on the database management system.
|
||||
*
|
||||
* Note that for MySQL/MariaDB the corresponding CHAR/VARCHAR types are used with a length of `16383` reflecting
|
||||
* 65554 bytes with `utf8mb4` and working with default `max_packet_size=16KB`. For SQLite and PostgreSQL the text
|
||||
* type conversion is used.
|
||||
*
|
||||
* Main purpose of this expression is to use it in a expression chain to convert non-text values to text in chain
|
||||
* with other expressions, for example to {@see self::concat()} multiple values or to ensure the type, within
|
||||
* `UNION/UNION ALL` query parts for example in recursive `Common Table Expressions` parts.
|
||||
*
|
||||
* This is a replacement for {@see QueryBuilder::castFieldToTextType()} with minor adjustments like enforcing and
|
||||
* limiting the size to a fixed variant to be more usable in sensible areas like `Common Table Expressions`.
|
||||
*
|
||||
* Alternatively the {@see self::castVarchar()} can be used which allows for dynamic length setting per expression
|
||||
* call.
|
||||
*
|
||||
* **Example:**
|
||||
* ```
|
||||
* $queryBuilder->expr()->castText(
|
||||
* '(' . '1 * 10' . ')',
|
||||
* 'virtual_field'
|
||||
* );
|
||||
* ```
|
||||
*
|
||||
* **Result with MySQL:**
|
||||
* ```
|
||||
* CAST((1 * 10) AS CHAR(16383) AS `virtual_field`
|
||||
* ```
|
||||
*
|
||||
* @throws \RuntimeException when used with a unsupported platform.
|
||||
*/
|
||||
public function castText(CompositeExpression|\Stringable|string $expression, string $asIdentifier = ''): string
|
||||
{
|
||||
$platform = $this->connection->getDatabasePlatform();
|
||||
if ($platform instanceof DoctrinePostgreSQLPlatform) {
|
||||
return $this->as(sprintf('((%s)::%s)', $expression, 'text'), $asIdentifier);
|
||||
}
|
||||
if ($platform instanceof DoctrineSQLitePlatform) {
|
||||
return $this->as(sprintf('(CAST((%s) AS %s))', $expression, 'TEXT'), $asIdentifier);
|
||||
}
|
||||
if ($platform instanceof DoctrineMariaDBPlatform) {
|
||||
// 16383 is the maximum for a VARCHAR field with `utf8mb4`
|
||||
return $this->as(sprintf('(CAST((%s) AS %s(%s)))', $expression, 'VARCHAR', '16383'), $asIdentifier);
|
||||
}
|
||||
if ($platform instanceof DoctrineMySQLPlatform) {
|
||||
// 16383 is the maximum for a VARCHAR field with `utf8mb4`
|
||||
return $this->as(sprintf('(CAST((%s) AS %s(%s)))', $expression, 'CHAR', '16383'), $asIdentifier);
|
||||
}
|
||||
throw new \RuntimeException(
|
||||
sprintf(
|
||||
'%s is not implemented for the used database platform "%s", yet!',
|
||||
__METHOD__,
|
||||
get_class($this->connection->getDatabasePlatform())
|
||||
),
|
||||
1722105672
|
||||
);
|
||||
}
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Extension authors can use the new expression method to build more advanced
|
||||
queries without the requirement to deal with the correct implementation
|
||||
for all supported database vendors - at least to some grade.
|
||||
|
||||
.. index:: Database, PHP-API, ext:core
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104526-1722603089:
|
||||
|
||||
===============================================================================
|
||||
Feature: #104526 - Provide validators for PSR-7 UploadedFile objects in Extbase
|
||||
===============================================================================
|
||||
|
||||
See :issue:`104526`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
4 new Extbase validators have been added to allow common validation tasks of a
|
||||
PSR-7 :php:`\TYPO3\CMS\Core\Http\UploadedFile` object or an
|
||||
:php:`\TYPO3\CMS\Extbase\Persistence\ObjectStorage` containing PSR-7
|
||||
:php-short:`\TYPO3\CMS\Core\Http\UploadedFile` objects.
|
||||
|
||||
Note, that the new validators can only be applied to the TYPO3 implementation
|
||||
of the PSR-7 :php:`\Psr\Http\Message\UploadedFileInterface` because they validate the uploaded
|
||||
files before it has been moved.
|
||||
|
||||
Custom implementations of the :php-short:`\Psr\Http\Message\UploadedFileInterface` must continue to
|
||||
implement their own validators.
|
||||
|
||||
FileNameValidator
|
||||
-----------------
|
||||
|
||||
This validator ensures, that files with PHP executable file extensions can not
|
||||
be uploaded. The validator has no options.
|
||||
|
||||
FileSizeValidator
|
||||
-----------------
|
||||
|
||||
This validator can be used to validate an uploaded file against a given minimum
|
||||
and maximum file size.
|
||||
|
||||
Validator options:
|
||||
|
||||
* :php:`minimum` - The minimum size as string (e.g. 100K)
|
||||
* :php:`maximum` - The maximum size as string (e.g. 100K)
|
||||
|
||||
MimeTypeValidator
|
||||
-----------------
|
||||
|
||||
This validator can be used to validate an uploaded file against a given set
|
||||
of accepted MIME types. The validator additionally verifies, that the given
|
||||
file extension of the uploaded file matches allowed file extensions for the
|
||||
detected mime type.
|
||||
|
||||
Validator options:
|
||||
|
||||
* :php:`allowedMimeTypes` - An array of allowed MIME types
|
||||
* :php:`ignoreFileExtensionCheck` - If set to "true", it is checked, the file
|
||||
extension check is disabled
|
||||
|
||||
ImageDimensionsValidator
|
||||
------------------------
|
||||
|
||||
This validator can be used to validate an uploaded image for given image
|
||||
dimensions. The validator must only be used, when it is ensured, that the
|
||||
uploaded file is an image (e.g. by validating the MIME type).
|
||||
|
||||
Validator options:
|
||||
|
||||
* :php:`width` - Fixed width of the image as integer
|
||||
* :php:`height` - Fixed height of the image as integer
|
||||
* :php:`minWidth` - Minimum width of the image as integer. Default is `0`
|
||||
* :php:`maxWidth` - Maximum width of the image as integer. Default is `PHP_INT_MAX`
|
||||
* :php:`minHeight` - Minimum height of the image as integer. Default is `0`
|
||||
* :php:`maxHeight` - Maximum height of the image as integer. Default is `PHP_INT_MAX`
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
TYPO3 extension autors can now use the new validators to validate a given
|
||||
:php-short:`\TYPO3\CMS\Core\Http\UploadedFile` object.
|
||||
|
||||
.. index:: Backend, ext:extbase
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104631-1723714985:
|
||||
|
||||
=================================================================
|
||||
Feature: #104631 - Add `UNION Clause` support to the QueryBuilder
|
||||
=================================================================
|
||||
|
||||
See :issue:`104631`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The :sql:`UNION` clause is used to combine the result sets of two or more
|
||||
:sql:`SELECT` statements, which all database vendors support, each with their
|
||||
own specific variations.
|
||||
|
||||
However, there is a commonly shared subset that works across all of them:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
SELECT column_name(s) FROM table1
|
||||
WHERE ...
|
||||
|
||||
UNION <ALL | DISTINCT>
|
||||
|
||||
SELECT column_name(s) FROM table2
|
||||
WHERE ...
|
||||
|
||||
ORDER BY ...
|
||||
LIMIT x OFFSET y
|
||||
|
||||
with shared requirements:
|
||||
|
||||
* Each SELECT must return the same fields in number, naming and order.
|
||||
* Each SELECT must not have ORDER BY, expect MySQL allowing it to be used as sub
|
||||
query expression encapsulated in parentheses.
|
||||
|
||||
Generic :sql:`UNION` clause support has been contributed to `Doctrine DBAL` and
|
||||
is included since `Release 4.1.0 <https://github.com/doctrine/dbal/releases/tag/4.1.0>`__
|
||||
which introduces two new API method on the
|
||||
:php-short:`\Doctrine\DBAL\Query\QueryBuilder`:
|
||||
|
||||
* :php:`union(string|QueryBuilder $part)` to create first UNION query part
|
||||
* :php:`addUnion(string|QueryBuilder $part, UnionType $type = UnionType::DISTINCT)`
|
||||
to add additional :sql:`UNION (ALL|DISTINCT)` query parts with the selected union
|
||||
query type.
|
||||
|
||||
TYPO3 decorates the Doctrine DBAL :php-short:`\Doctrine\DBAL\Query\QueryBuilder`
|
||||
to provide for most API methods automatic
|
||||
quoting of identifiers and values **and** to apply database restrictions automatically
|
||||
for :sql:`SELECT` queries.
|
||||
|
||||
The Doctrine DBAL API has been adopted now to provide the same surface for the
|
||||
TYPO3 :php:`\TYPO3\CMS\Core\Database\Query\QueryBuilder` and the intermediate
|
||||
:php:`\TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder` to make it easier to
|
||||
create :sql:`UNION` clause queries. The API on both methods allows to provide
|
||||
dedicated :php-short:`\TYPO3\CMS\Core\Database\Query\QueryBuilder` instances
|
||||
or direct queries as strings in case it is needed.
|
||||
|
||||
.. note::
|
||||
|
||||
Providing :sql:`UNION` parts as plain string requires the developer to take
|
||||
care of proper quoting and escaping within the query part.
|
||||
|
||||
In queries containing subqueries, only named placeholders (such as `:username`)
|
||||
can be used and must be registered on the outermost
|
||||
:php-short:`\TYPO3\CMS\Core\Database\Query\QueryBuilder` object,
|
||||
similar to advanced query creation with :sql:`SUB QUERIES`.
|
||||
|
||||
|
||||
.. warning::
|
||||
|
||||
:php-short:`\TYPO3\CMS\Core\Database\Query\QueryBuilder` can be used create
|
||||
:sql:`UNION` clause queries not compatible with all database providers,
|
||||
for example using :sql:`LIMIT/OFFSET` in each part query or other stuff.
|
||||
|
||||
UnionType::DISTINCT and UnionType::ALL
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Each subsequent part needs to be defined either as :sql:`UNION DISTINCT` or
|
||||
:sql:`UNION ALL` which could have not so obvious effects.
|
||||
|
||||
For example, using :sql:`UNION ALL` for all parts in between except for the last
|
||||
one would generate larger result sets first, but discards duplicates when adding
|
||||
the last result set. On the other side, using :sql:`UNION ALL` tells the query
|
||||
optimizer **not** to scan for duplicates and remove them at all which can be a
|
||||
performance improvement - if you can deal with duplicates it can be ensured that
|
||||
each part does not produce same outputs.
|
||||
|
||||
Example: Compose a :sql:`UNION` clause query
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: php
|
||||
:caption: Custom service class using a UNION query to retrieve data.
|
||||
|
||||
use Doctrine\DBAL\Query\UnionType;
|
||||
use TYPO3\CMS\Core\Database\Connection;
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
|
||||
final readonly class MyService {
|
||||
public function __construct(
|
||||
private ConnectionPool $connectionPool,
|
||||
) {}
|
||||
|
||||
public function executeUnionQuery(
|
||||
int $pageIdOne,
|
||||
int $pageIdTwo,
|
||||
): ?array {
|
||||
$connection = $this->connectionPool->getConnectionForTable('pages');
|
||||
$unionQueryBuilder = $connection->createQueryBuilder();
|
||||
$firstPartQueryBuilder = $connection->createQueryBuilder();
|
||||
$secondPartQueryBuilder = $connection->createQueryBuilder();
|
||||
// removing automatic TYPO3 restriction for the sake of the example
|
||||
// to match the PLAIN SQL example when executed. Not removing them
|
||||
// will generate corresponding restriction SQL code for each part.
|
||||
$firstPartQueryBuilder->getRestrictions()->removeAll();
|
||||
$secondPartQueryBuilder->getRestrictions()->removeAll();
|
||||
$expr = $unionQueryBuilder->expr();
|
||||
|
||||
$firstPartQueryBuilder
|
||||
// The query parts **must** have the same column counts, and these
|
||||
// columns **must** have compatible types
|
||||
->select('uid', 'pid', 'title')
|
||||
->from('pages')
|
||||
->where(
|
||||
$expr->eq(
|
||||
'pages.uid',
|
||||
// !!! Ensure to use most outer / top / main QueryBuilder
|
||||
// instance for creating parameters and the complete
|
||||
// query can be executed in the end.
|
||||
$unionQueryBuilder->createNamedParameter($pageIdOne, Connection::PARAM_INT),
|
||||
)
|
||||
);
|
||||
$secondPartQueryBuilder
|
||||
->select('uid', 'pid', 'title')
|
||||
->from('pages')
|
||||
->where(
|
||||
$expr->eq(
|
||||
'pages.uid',
|
||||
// !!! Ensure to use most outer / top / main QueryBuilder instance
|
||||
$unionQueryBuilder->createNamedParameter($pageIdTwo, Connection::PARAM_INT),
|
||||
)
|
||||
);
|
||||
|
||||
// Set first and second union part to the main (union)
|
||||
// QueryBuilder and return the retrieved rows.
|
||||
return $unionQueryBuilder
|
||||
->union($firstPartQueryBuilder)
|
||||
->addUnion($secondPartQueryBuilder, UnionType::DISTINCT)
|
||||
->orderBy('uid', 'ASC')
|
||||
->executeQuery()
|
||||
->fetchAllAssociative();
|
||||
}
|
||||
}
|
||||
|
||||
This would create the following query for MySQL with :php:`$pageIdOne = 100` and
|
||||
:php:`$pageIdTwo = 10`:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
(SELECT `uid`, `pid`, `title` FROM pages WHERE `pages`.`uid` = 100)
|
||||
UNION
|
||||
(SELECT `uid`, `pid`, `title` FROM pages WHERE `pages`.`uid` = 10)
|
||||
ORDER BY `uid` ASC
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Extension authors can use the new
|
||||
:php-short:`\TYPO3\CMS\Core\Database\Query\QueryBuilder` methods to build more
|
||||
advanced queries.
|
||||
|
||||
.. index:: Database, PHP-API, ext:core
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104655-1724859386:
|
||||
|
||||
========================================================================
|
||||
Feature: #104655 - Add console command to mark upgrade wizards as undone
|
||||
========================================================================
|
||||
|
||||
See :issue:`104655`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
A new CLI command :bash:`typo3 upgrade:mark:undone` has been
|
||||
introduced. It allows to mark a previously executed upgrade wizard as "undone",
|
||||
so it can be run again.
|
||||
|
||||
This makes the existing functionality from the install tool also available on
|
||||
CLI.
|
||||
|
||||
.. note::
|
||||
|
||||
Bear in mind that wizards theoretically can cause data inconsistencies when
|
||||
being run again. Also, a wizard may not run properly again when its
|
||||
pre-requisites no longer apply after its first run.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
You can now mark an already executed upgrade wizard as "undone" with
|
||||
:bash:`typo3 upgrade:mark:undone <wizardIdentifier>`
|
||||
|
||||
.. index:: CLI, ext:install
|
||||
@@ -0,0 +1,59 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104773-1724939348:
|
||||
|
||||
=======================================
|
||||
Feature: #104773 - Generic view factory
|
||||
=======================================
|
||||
|
||||
See :issue:`104773`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Class :php:`\TYPO3\CMS\Core\View\ViewFactoryInterface` has been added as a
|
||||
generic view interface to create views that return an instance of
|
||||
:php:`\TYPO3\CMS\Core\View\ViewInterface`. This implements the "V" of "MVC"
|
||||
in a generic way and is used throughout the TYPO3 Core.
|
||||
|
||||
This obsoletes all custom view instance creation approaches within the TYPO3 Core
|
||||
and within TYPO3 extensions. Extensions should retrieve view instances based
|
||||
on this :php-short:`\TYPO3\CMS\Core\View\ViewFactoryInterface`.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Instances of this interface should be injected using dependency injection. The
|
||||
default injected implementation is a Fluid view, and can be reconfigured using
|
||||
dependency injection configuration, typically in a :file:`Services.yaml` file.
|
||||
|
||||
A casual example to create and render a view looks like this.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use TYPO3\CMS\Core\View\ViewFactoryInterface;
|
||||
|
||||
class MyController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ViewFactoryInterface $viewFactory,
|
||||
) {}
|
||||
|
||||
public function myAction(ServerRequestInterface $request): string
|
||||
{
|
||||
$viewFactoryData = new ViewFactoryData(
|
||||
templateRootPaths: ['EXT:myExt/Resources/Private/Templates'],
|
||||
partialRootPaths: ['EXT:myExt/Resources/Private/Partials'],
|
||||
layoutRootPaths: ['EXT:myExt/Resources/Private/Layouts'],
|
||||
request: $request,
|
||||
);
|
||||
$view = $this->viewFactory->create($viewFactoryData);
|
||||
$view->assign('myData', 'myData');
|
||||
return $view->render('path/to/template');
|
||||
}
|
||||
}
|
||||
|
||||
Note Extbase-based extensions create a view instance based on this factory
|
||||
by default and are accessible as :php:`$this->view`.
|
||||
|
||||
.. index:: Fluid, PHP-API, ext:core
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104789-1725194699:
|
||||
|
||||
========================================================================
|
||||
Feature: #104789 - Support for contentArgumentName in AbstractViewHelper
|
||||
========================================================================
|
||||
|
||||
See :issue:`104789`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
ContentArgumentName has been a feature on Fluid ViewHelpers for some time now.
|
||||
It allows ViewHelpers to link a ViewHelper argument to the children of the
|
||||
ViewHelper name. As a result, an input value can either be specified as an
|
||||
argument or as the ViewHelper's children, leading to the same result.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: html
|
||||
<!-- Tag syntax -->
|
||||
<f:format.json value="{data}" />
|
||||
<f:format.json>{data}</f:format.json>
|
||||
|
||||
<!-- Inline syntax -->
|
||||
{f:format.json(value: data)}
|
||||
{data -> f:format.json()}
|
||||
|
||||
Previously, this feature was only available to ViewHelpers using the trait
|
||||
:php-short:`\TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithContentArgumentAndRenderStatic`.
|
||||
It is now available to all ViewHelpers since it has been integrated into the
|
||||
:php-short:`\TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper`. The
|
||||
trait is no longer necessary.
|
||||
|
||||
To use the new feature, all the ViewHelper implementation needs to do is to define
|
||||
a method `getContentArgumentName()` which returns the name of the argument to be
|
||||
linked to the ViewHelper's children:
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: php
|
||||
public function getContentArgumentName(): string
|
||||
{
|
||||
return 'value';
|
||||
}
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
ViewHelpers using the trait
|
||||
:php-short:`\TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithContentArgumentAndRenderStatic`
|
||||
should be migrated to the new feature.
|
||||
|
||||
:php-short:`\TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithContentArgumentAndRenderStatic`
|
||||
will continue to work in Fluid v4, but will log a deprecation level error message.
|
||||
It will be removed in Fluid v5.
|
||||
|
||||
.. index:: Fluid, ext:fluid
|
||||
@@ -0,0 +1,116 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104794-1725980585:
|
||||
|
||||
=================================================
|
||||
Feature: #104794 - Introduce Site Settings Editor
|
||||
=================================================
|
||||
|
||||
See :issue:`104794`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
A new Site Settings editor has been introduced that allows to configure per-site
|
||||
settings in file:`config/sites/*/settings.yaml`.
|
||||
|
||||
The new backend module :guilabel:`Site Management > Settings`
|
||||
provides an overview of sites which offer configurable settings and makes
|
||||
them editable based on
|
||||
:doc:`Site Set provided Settings Definitions <../13.1/Feature-103437-IntroduceSiteSets>`.
|
||||
|
||||
The editor shows a list of settings categories and respective settings. It will
|
||||
persist all settings into :file:`config/sites/*/settings.yaml`. The module will
|
||||
only persist settings that deviate from the site-scoped default value. That
|
||||
means it will only change the minimal difference to the settings set defined
|
||||
by the active sets for the respective site.
|
||||
|
||||
The backend module is currently available for administrators only, but will
|
||||
likely be extended to be made available for editors in future.
|
||||
|
||||
Anonymous (undefined) site settings – as supported since TYPO3 v10 –
|
||||
will not be made editable, but will be preserved as-is when persisting changes
|
||||
through the settings editor.
|
||||
|
||||
|
||||
Categorization
|
||||
--------------
|
||||
|
||||
Sets can define categories and settings definitions can reference the category
|
||||
by ID in order to assign a setting to a specific category.
|
||||
These definitions are placed in :file:`settings.definitions.yaml`
|
||||
next to the site set file :file:`config.yaml`.
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: EXT:my_extension/Configuration/Sets/MySet/settings.definitions.yaml
|
||||
|
||||
categories:
|
||||
myCategory:
|
||||
label: 'My Category'
|
||||
|
||||
settings:
|
||||
my.example.setting:
|
||||
label: 'My example setting'
|
||||
category: myCategory
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
my.seoRelevantSetting:
|
||||
label: 'My SEO relevant setting'
|
||||
# show in EXT:seo provided category "seo"
|
||||
category: seo
|
||||
type: int
|
||||
default: 5
|
||||
|
||||
The settings ordering is defined through the loading order of extensions and by
|
||||
the order of categories. Uncategorized settings will be grouped into a virtual
|
||||
"Other" category and shown at the end of the list of available settings.
|
||||
|
||||
Readonly
|
||||
--------
|
||||
|
||||
Site settings can be made readonly. They can be overridden only by editing
|
||||
the :file:`config/sites/my-site/settings.yaml` but not from within the editor.
|
||||
|
||||
The value of the field is displayed in a readonly field in the settings editor.
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: EXT:my_extension/Configuration/Sets/MySet/settings.definitions.yaml
|
||||
|
||||
settings:
|
||||
my.readonlySetting:
|
||||
label: 'My readonly setting'
|
||||
type: int
|
||||
default: 5
|
||||
readonly: true
|
||||
|
||||
Enumeration of strings
|
||||
----------------------
|
||||
|
||||
Site settings can provide possible options via the `enum` specifier, that will
|
||||
be selectable in the editor GUI:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: EXT:my_extension/Configuration/Sets/MySet/settings.definitions.yaml
|
||||
|
||||
settings:
|
||||
my.enumSetting:
|
||||
label: 'My setting with options'
|
||||
type: string
|
||||
enum:
|
||||
valueA: 'Label of value A'
|
||||
valueB: 'Label of value B'
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Site-scoped settings will most likely be the place to configure site-wide
|
||||
configuration, which was previously only possible to modify via Constant Editor,
|
||||
modifying TypoScript constants.
|
||||
|
||||
It is recommended to use site-sets and their UI configuration in favor of
|
||||
TypoScript Constants in the future.
|
||||
|
||||
|
||||
.. index:: Backend, Frontend, YAML, ext:backend
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104814-1725444916:
|
||||
|
||||
===================================================================
|
||||
Feature: #104814 - Automatically add system fields to content types
|
||||
===================================================================
|
||||
|
||||
See :issue:`104814`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
All content elements types (:php:`CType`) are usually equipped with the same
|
||||
system fields (`language`, `hidden`, etc.) - see also :ref:`feature-104311-1720176189`.
|
||||
Adding them to the editor form has previously been done by adding those fields
|
||||
to each content types' :php:`showitem` definition.
|
||||
|
||||
In the effort to simplify content element creation, to unify the available
|
||||
fields and position for the editor and to finally reduce configuration effort
|
||||
for integrators, those system fields are now added automatically based
|
||||
on the :php:`ctrl` definition.
|
||||
|
||||
.. note::
|
||||
|
||||
The fields are added to the :php:`showitem` through their corresponding
|
||||
palettes. In case such palette has been changed by extensions, the required
|
||||
system fields are added individually to corresponding tabs.
|
||||
|
||||
The following tabs / palettes are now added automatically:
|
||||
|
||||
* The :guilabel:`General` tab with the `general` palette at the very beginning
|
||||
* The :guilabel:`Language` tab with the `language` palette after custom fields
|
||||
* The :guilabel:`Access` tab with the `hidden` and `access` palettes
|
||||
* The :guilabel:`Notes` tab with the `rowDescription` field
|
||||
|
||||
As mentioned, in case one of those palettes has been changed to no longer
|
||||
include the corresponding system fields, those fields are added individually
|
||||
depending on their definition in the table's :php:`ctrl` section:
|
||||
|
||||
* The :php:`ctrl[type]` field (usually :php:`CType`)
|
||||
* The :php:`colPos` field
|
||||
* The :php:`ctrl[languageField]` (usually :php:`sys_language_uid`)
|
||||
* The :php:`ctrl[editlock]` field (usually :php:`editlock`)
|
||||
* The :php:`ctrl[enablecolumns][disabled]` field (usually :php:`hidden`)
|
||||
* The :php:`ctrl[enablecolumns][starttime]` field (usually :php:`starttime`)
|
||||
* The :php:`ctrl[enablecolumns][endtime]` field (usually :php:`endtime`)
|
||||
* The :php:`ctrl[enablecolumns][fe_group]` field (usually :php:`fe_group`)
|
||||
* The :php:`ctrl[descriptionColumn]` field (usually :php:`rowDescription`)
|
||||
|
||||
By default, all custom fields - the ones still defined in :php:`showitem` - are
|
||||
added after the `general` palette and are therefore added to the
|
||||
:guilabel:`General` tab, unless a custom tab (e.g. :guilabel:`Plugin`,
|
||||
or :guilabel:`Categories`) is defined in between. It is also possible to start
|
||||
with a custom tab by defining a `--div--` as the first item in the
|
||||
:php:`showitem`. In this case, the :guilabel:`General` tab will be omitted.
|
||||
|
||||
All those system fields, which are added based on the :php:`ctrl` section are
|
||||
also automatically removed from any custom palette and from the customized
|
||||
type's :php:`showitem` definition.
|
||||
|
||||
If the content element defines the :guilabel:`Extended` tab, it will be
|
||||
inserted at the end, including all fields added to the type via API methods,
|
||||
without specifying a position, e.g. via
|
||||
:php:`ExtensionManagementUtility::addToAllTcaTypes()`.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Creating content elements has been simplified by removing the need to
|
||||
define the system fields for each element again and again. This shrinks
|
||||
down a content element's :php:`showitem` to just the element specific fields.
|
||||
|
||||
A usual migration will therefore look like the following:
|
||||
|
||||
Before:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'slider' => [
|
||||
'showitem' => '
|
||||
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general,
|
||||
--palette--;;general,
|
||||
--palette--;;headers,
|
||||
slider_elements,
|
||||
bodytext;LLL:EXT:awesome_slider/Resources/Private/Language/locallang_ttc.xlf:bodytext.ALT.slider_description,
|
||||
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:appearance,
|
||||
--palette--;;frames,
|
||||
--palette--;;appearanceLinks,
|
||||
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language,
|
||||
--palette--;;language,
|
||||
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access,
|
||||
--palette--;;hidden,
|
||||
--palette--;;access,
|
||||
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:categories,
|
||||
categories,
|
||||
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:notes,
|
||||
rowDescription,
|
||||
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:extended,
|
||||
',
|
||||
],
|
||||
|
||||
After:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'slider' => [
|
||||
'showitem' => '
|
||||
--palette--;;headers,
|
||||
slider_elements,
|
||||
bodytext;LLL:EXT:awesome_slider/Resources/Private/Language/locallang_ttc.xlf:bodytext.ALT.slider_description,
|
||||
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:categories,
|
||||
categories,
|
||||
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:extended,
|
||||
',
|
||||
],
|
||||
|
||||
Since all fields, palettes and tabs, which are defined in the :php:`showitem`
|
||||
are added after the :php:`general` palette, also the :guilabel:`Categories` tab
|
||||
- if defined - is displayed before the system tabs / fields. The only special
|
||||
case is the :guilabel:`Extended` tab, which is always added at the end.
|
||||
|
||||
.. important::
|
||||
|
||||
For consistency reasons, custom labels for system fields are no
|
||||
longer preserved.
|
||||
|
||||
.. index:: PHP-API, TCA, ext:core
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104832-1725537890:
|
||||
|
||||
==========================================================================
|
||||
Feature: #104832 - PSR-14 Event to alter the results of PageTreeRepository
|
||||
==========================================================================
|
||||
|
||||
See :issue:`104832`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Until TYPO3 v9, it was possible to alter the rendering of one of TYPO3's
|
||||
superpowers — the page tree in the TYPO3 Backend User Interface.
|
||||
|
||||
This was done via a "Hook", but was removed due to the migration towards an
|
||||
SVG-based tree rendering.
|
||||
|
||||
As the Page Tree Rendering has evolved, and the hook system has been replaced
|
||||
in favor of PSR-14 Events, a new event :php:`\TYPO3\CMS\Backend\Tree\Repository\AfterRawPageRowPreparedEvent`
|
||||
has been introduced.
|
||||
|
||||
|
||||
Example
|
||||
=======
|
||||
|
||||
The event listener class, using the PHP attribute :php:`#[AsEventListener]` for
|
||||
registration, will remove any children for displaying for the page with the
|
||||
UID 123:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use TYPO3\CMS\Core\Attribute\AsEventListener;
|
||||
use TYPO3\CMS\Backend\Tree\Repository\AfterRawPageRowPreparedEvent;
|
||||
|
||||
final class MyEventListener
|
||||
{
|
||||
#[AsEventListener]
|
||||
public function __invoke(AfterRawPageRowPreparedEvent $event): void
|
||||
{
|
||||
$rawPage = $event->getRawPage();
|
||||
if ((int)$rawPage['uid'] === 123) {
|
||||
$rawPage['_children'] = [];
|
||||
$event->setRawPage($rawPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Using the new PSR-14 event, it is now possible to modify the populated
|
||||
:php:`page` properties or its children records.
|
||||
|
||||
.. index:: Backend, PHP-API, ext:backend
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104844-1725617507:
|
||||
|
||||
====================================================================================
|
||||
Feature: #104844 - Add widgets for listing all the sys_notes inside the TYPO3 system
|
||||
====================================================================================
|
||||
|
||||
See :issue:`104844`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
To make it easier for TYPO3 users to view all the internal notes (EXT:sys_note) in
|
||||
their TYPO3 system, TYPO3 now offers dashboard widgets for each internal note type.
|
||||
The backend user must have access to the sys_note table and view permission to the
|
||||
page where the record is located.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
TYPO3 users who have access to the :guilabel:`Dashboard` module and are
|
||||
granted access to the new widgets can now add and use these widgets.
|
||||
|
||||
.. index:: Backend, ext:dashboard
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104846-1725631434:
|
||||
|
||||
===============================================================
|
||||
Feature: #104846 - Custom field transformations for new records
|
||||
===============================================================
|
||||
|
||||
See :issue:`104846`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
With :issue:`103783` the new :php:`\TYPO3\CMS\Core\Domain\Record` object has been introduced, which
|
||||
is an object representing a raw database record based on TCA and is usually
|
||||
used in the frontend (via Fluid Templates).
|
||||
|
||||
Since :ref:`feature-103581-1723209131` the properties of those
|
||||
:php-short:`\TYPO3\CMS\Core\Domain\Record`
|
||||
objects are transformed / expanded from their raw database value into
|
||||
"rich-flavored" values. Those values might be relations to e.g.
|
||||
:php-short:`\TYPO3\CMS\Core\Domain\Record`,
|
||||
:php-short:`\TYPO3\CMS\Core\Resource\FileReference`,
|
||||
:php-short:`\TYPO3\CMS\Core\Resource\Folder` or :php:`\DateTimeImmutable` objects.
|
||||
|
||||
However, TYPO3 does not know about custom field meanings, e.g. latitude and
|
||||
longitude information, stored in an input field or user settings stored as
|
||||
JSON in an TCA type `json` field. For such custom needs, the new
|
||||
PSR-14 :php:`\TYPO3\CMS\Core\Domain\Event\RecordCreationEvent` has been
|
||||
introduced. It is dispatched right before a
|
||||
:php-short:`\TYPO3\CMS\Core\Domain\Record` is created and
|
||||
therefore allows to fully manipulate any property, even the ones already
|
||||
transformed by TYPO3.
|
||||
|
||||
The new event is stoppable (implementing :php-short:`\Psr\EventDispatcher\StoppableEventInterface`), which
|
||||
allows listeners to actually create a :php-short:`\TYPO3\CMS\Core\Domain\Record` object completely on their
|
||||
own.
|
||||
|
||||
.. important::
|
||||
|
||||
The event operates on the :php-short:`\TYPO3\CMS\Core\Domain\RecordInterface` instead of an actual
|
||||
implementation. This way, extension authors are able to set custom records,
|
||||
implementing the interface.
|
||||
|
||||
|
||||
The new event features the following methods:
|
||||
|
||||
* :php:`setRecord()` - Manually adds a :php-short:`\TYPO3\CMS\Core\Domain\RecordInterface`
|
||||
object (stops the event propagation)
|
||||
* :php:`hasProperty()` - Whether a property exists
|
||||
* :php:`setProperty()` - Add or overwrite a property
|
||||
* :php:`setProperties()` - Set properties for the :php-short:`\TYPO3\CMS\Core\Domain\RecordInterface`
|
||||
* :php:`unsetProperty()` - Unset a single property
|
||||
* :php:`getProperty()` - Get the value for a single property
|
||||
* :php:`getProperties()` - Get all properties
|
||||
* :php:`getRawRecord()` - Get the :php:`RawRecord` object
|
||||
* :php:`getSystemProperties()` - Get the calculated :php:`SystemProperties`
|
||||
* :php:`getContext()` - Get the current :php:`Context` (used to fetch the raw database row)
|
||||
* :php:`isPropagationStopped()` - Whether the event propagation is stopped
|
||||
|
||||
Example
|
||||
=======
|
||||
|
||||
The event listener class, using the PHP attribute :php:`#[AsEventListener]` for
|
||||
registration, creates a :php:`Coordinates` object based on the field value of
|
||||
the :php:`coordinates` field for the custom :php:`maps` content type.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
final class RecordCreationEventListener
|
||||
{
|
||||
#[AsEventListener]
|
||||
public function __invoke(\TYPO3\CMS\Core\Domain\Event\RecordCreationEvent $event): void
|
||||
{
|
||||
$rawRecord = $event->getRawRecord();
|
||||
|
||||
if ($rawRecord->getMainType() === 'tt_content' && $rawRecord->getRecordType() === 'maps' && $event->hasProperty('coordinates')) {
|
||||
$event->setProperty(
|
||||
'coordinates',
|
||||
new Coordinates($event->getProperty('coordinates'))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Using the new PSR-14 :php-short:`\TYPO3\CMS\Core\Domain\Event\RecordCreationEvent`,
|
||||
extension authors are able to apply any field transformation to any property before a
|
||||
:php-short:`\TYPO3\CMS\Core\Domain\Record` is created.
|
||||
|
||||
It is even possible to completely create a new
|
||||
:php-short:`\TYPO3\CMS\Core\Domain\RecordInterface` object on their own.
|
||||
|
||||
.. index:: PHP-API, ext:core
|
||||
@@ -0,0 +1,30 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104868-1725912804:
|
||||
|
||||
=============================================
|
||||
Feature: #104868 - Add color scheme switching
|
||||
=============================================
|
||||
|
||||
See :issue:`104868`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Options have been added to switch between the available color schemes in TYPO3. A set of buttons
|
||||
for each available color scheme in the user dropdown at the top right and a setting in User Settings.
|
||||
|
||||
As the dark color scheme is currently regarded experimental until further notice, color scheme switching logic is
|
||||
currently hidden behind the UserTS setting :typoscript:`setup.fields.colorScheme.disabled`.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
.. warning::
|
||||
If you don't want the automatic switching and don't include the `setup` core extension in your environment,
|
||||
you need to manually disable the feature yourself using the UserTS configuration
|
||||
:typoscript:`setup.fields.colorScheme.disabled = 1`!
|
||||
|
||||
It is now possible to switch to an automatic, light or dark color scheme for use in the backend.
|
||||
|
||||
.. index:: Backend, ext:backend
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104878-1725993353:
|
||||
|
||||
===========================================================================
|
||||
Feature: #104878 - Introduce dashboard widget for pages with latest changes
|
||||
===========================================================================
|
||||
|
||||
See :issue:`104878`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
To make it easier for TYPO3 users to view the latest changed pages in their
|
||||
TYPO3 system, TYPO3 now offers a dashboard widget that lists the latest
|
||||
changed pages.
|
||||
|
||||
Widget Options:
|
||||
- `limit` The limit of pages, displayed in the widget, default is 10
|
||||
- `historyLimit` The maximum number of history records to check, default 1000
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
TYPO3 users who have access to the :guilabel:`Dashboard` module and are
|
||||
granted access to the new widgets can now add and use this widget.
|
||||
|
||||
.. index:: Backend, ext:dashboard
|
||||
@@ -0,0 +1,62 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104896-1726046146:
|
||||
|
||||
================================================
|
||||
Feature: #104896 - Raise Fluid Standalone to 4.0
|
||||
================================================
|
||||
|
||||
See :issue:`104896`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
TYPO3 13 now uses Fluid 4 as the new base version. Old TYPO3 versions
|
||||
will keep using Fluid 2, which will still receive bugfixes if necessary.
|
||||
For detailed information about this release, please refer to the
|
||||
`dedicated release notes on GitHub <https://github.com/TYPO3/Fluid/releases/tag/4.0.0>`_.
|
||||
|
||||
With the update to Fluid 4, tag-based ViewHelpers now have proper
|
||||
support for boolean attributes. Before this change, it was very
|
||||
cumbersome to generate these with Fluid, now it is implemented similar
|
||||
to popular JavaScript frameworks by using the newly introduced
|
||||
boolean literals:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<my:viewhelper async="{true}" />
|
||||
Result: <tag async="async" />
|
||||
|
||||
<my:viewhelper async="{false}" />
|
||||
Result: <tag />
|
||||
|
||||
|
||||
Of course, any variable containing a boolean can be supplied as well:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<my:viewhelper async="{isAsync}" />
|
||||
|
||||
|
||||
This can also be used in combination with variable casting:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<my:viewhelper async="{myString as boolean}" />
|
||||
|
||||
|
||||
For compatibility reasons empty strings still lead to the attribute
|
||||
being omitted from the tag.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
For existing installations, negative consequences of this update should be
|
||||
minimal as deprecated features will still work. Users are however advised
|
||||
to look into the already announced deprecations and to update their code
|
||||
accordingly. This update helps with this by now writing log messages to the
|
||||
deprecation log (if activated) if any deprecated feature is used in the
|
||||
TYPO3 instance.
|
||||
|
||||
.. index:: Fluid, ext:fluid
|
||||
@@ -0,0 +1,31 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104904-1726049662:
|
||||
|
||||
===========================================================
|
||||
Feature: #104904 - Ignore Fluid syntax error in <f:comment>
|
||||
===========================================================
|
||||
|
||||
See :issue:`104904`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Fluid 4 brings a new template processor
|
||||
:php:`\TYPO3Fluid\Fluid\Core\Parser\TemplateProcessor\RemoveCommentsTemplateProcessor`
|
||||
which removes Fluid comments created with the
|
||||
:ref:`Debug ViewHelper <f:debug> <t3viewhelper:typo3-fluid-debug>` from the template source
|
||||
string before the parsing process starts. It retains the original line breaks to ensure
|
||||
that error messages still refer to the correct line in the template.
|
||||
|
||||
By applying this template processor to all Fluid instances in the Core, it is now
|
||||
possible to use invalid Fluid code inside :fluid:`<f:comment>` without triggering a Fluid error.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
This feature is helpful during template development because developers don't need to
|
||||
take care for commented-out code being valid Fluid code.
|
||||
|
||||
.. index:: Fluid, ext:fluid
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104914-1726075631:
|
||||
|
||||
=====================================================================================================
|
||||
Feature: #104914 - Updated HTTP headers for frontend rendering and new TypoScript setting for proxies
|
||||
=====================================================================================================
|
||||
|
||||
See :issue:`104914`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
In a typical frontend rendering scenario, TYPO3 sends HTTP response headers to
|
||||
deny caching to clients (= browsers) when e.g. a frontend user is logged in,
|
||||
a backend user is previewing a page, or a non-cacheable plugin is on a page.
|
||||
|
||||
When a frontend page is "client-cacheable", TYPO3 does not send any HTTP headers
|
||||
by default, but only when :typoscript:`config.sendCacheHeaders = 1` is set
|
||||
via TypoScript.
|
||||
|
||||
In this case, TYPO3 sends the following HTTP Headers (example):
|
||||
|
||||
.. code-block:: plaintext
|
||||
|
||||
Expires: Thu, 26 Aug 2024 08:52:00 GMT
|
||||
ETag: "d41d8cd98f00b204ecs00998ecf8427e"
|
||||
Cache-Control: max-age=86400
|
||||
Pragma: public
|
||||
|
||||
However, in the past, this could lead to problems, because recurring website
|
||||
users might see outdated content for up to 24 hours (by default) or even longer,
|
||||
even if other website visitors already see new content, depending on various
|
||||
cache_timeout settings.
|
||||
|
||||
Thus, :typoscript:`config.sendCacheHeaders = 1` should be used with extreme care.
|
||||
|
||||
However, this option was also used when a proxy / CDN / shared cache such as
|
||||
Varnish was put in between TYPO3 / the webserver and the client. The reverse
|
||||
proxy can then evaluate the HTTP Response Headers sent by TYPO3 frontend, put
|
||||
the TYPO3 response from the actual webserver into its "shared cache" and send
|
||||
a manipulated / adapted response to the client.
|
||||
|
||||
However, when working with proxies, it is much more helpful to take load
|
||||
off of TYPO3 / the webserver by keeping a cached version for a period of
|
||||
time and answering requests from the client, while still telling the
|
||||
client to not cache the response inside the browser cache.
|
||||
|
||||
This is now achieved with a new option
|
||||
:typoscript:`config.sendCacheHeadersForSharedCaches = auto`.
|
||||
|
||||
With this option enabled, TYPO3 now evaluates if the current TYPO3 frontend
|
||||
request is executed behind a Reverse Proxy, and if so, TYPO3 sends the following
|
||||
HTTP Response Headers at a cached response:
|
||||
|
||||
Expires: Thu, 26 Aug 2024 08:52:00 GMT
|
||||
ETag: "d41d8cd98f00b204ecs00998ecf8427e"
|
||||
Cache-Control: max-age=0, s-maxage=86400
|
||||
Pragma: public
|
||||
|
||||
With :typoscript:`config.sendCacheHeadersForSharedCaches = force` the reverse
|
||||
proxy evaluation can be omitted, which can be used for local webserver internal
|
||||
caches.
|
||||
|
||||
"s-maxage" is a directive to tell shared caches - CDNs and reverse proxies - to keep
|
||||
a cached version of the HTTP response for a period of time (based on various
|
||||
cache settings) in their shared cache, while max-age=0 is evaluated at the
|
||||
client level. See
|
||||
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control for more
|
||||
details and if your reverse proxy supports this directive.
|
||||
|
||||
The new option takes precedence over :typoscript:`config.sendCacheHeaders = 1`
|
||||
if running behind a reverse proxy.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
By utilizing the new TypoScript setting, TYPO3 caches cacheable contents,
|
||||
and also instructs shared caches such as reverse proxies or CDNs to cache
|
||||
the HTTP Response, while always delivering fresh content to the client,
|
||||
if certain routines for cache invalidation are in place. The latter is
|
||||
typically handled by TYPO3 extensions which hook into the cache invalidation
|
||||
process of TYPO3 to also invalidate cache entries in the reverse proxies.
|
||||
|
||||
In addition, compared to previous TYPO3 versions, client-cacheable HTTP Responses
|
||||
now send "Cache-Control: private, no-store" if no option applies.
|
||||
|
||||
.. index:: Frontend, TypoScript, ext:frontend
|
||||
@@ -0,0 +1,27 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104935-1726135959:
|
||||
|
||||
==============================================================
|
||||
Feature: #104935 - Allow moving content elements via page tree
|
||||
==============================================================
|
||||
|
||||
See :issue:`104935`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
To make managing content across pages easier, a backend user may now drag
|
||||
content elements from the :guilabel:`Web > Page` module into a page in the page tree.
|
||||
|
||||
Once dropped, a modal window opens, allowing the backend user to select the
|
||||
position for placing the content element and to change the target page if needed.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Content elements can be moved from the :guilabel:`Web > Page` module into the
|
||||
page tree to initiate the moving process.
|
||||
|
||||
.. index:: Backend, ext:backend
|
||||
@@ -0,0 +1,49 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104973-1726393875:
|
||||
|
||||
=====================================================================
|
||||
Feature: #104973 - Activate the shipped LintYaml executable for TYPO3
|
||||
=====================================================================
|
||||
|
||||
See :issue:`104973`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The :bash:`typo3` executable received a new command `lint:yaml` to ease and encourage
|
||||
linting of YAML files before deploying to production and therefore avoid failures.
|
||||
|
||||
Usage as follows:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# Validates a single file
|
||||
bin/typo3 lint:yaml path/to/file.yaml
|
||||
|
||||
# Validates multiple files
|
||||
bin/typo3 lint:yaml path/to/file1.yaml path/to/file2.yaml
|
||||
|
||||
# Validates all files in a directory (also in sub-directories)
|
||||
bin/typo3 lint:yaml path/to/directory
|
||||
|
||||
# Validates all files in multiple directories (also in sub-directories)
|
||||
bin/typo3 lint:yaml path/to/directory1 path/to/directory2
|
||||
|
||||
# Exclude one or more files from linting
|
||||
bin/typo3 lint:yaml path/to/directory --exclude=path/to/directory/foo.yaml --exclude=path/to/directory/bar.yaml
|
||||
|
||||
# Show help
|
||||
bin/typo3 lint:yaml --help
|
||||
|
||||
The `help` argument will list possible usage elements.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Integrate easy made linting of YAML files from Core, custom extensions or
|
||||
any other source into your quality assurance workflow in the known format
|
||||
of the :bash:`typo3` executable.
|
||||
|
||||
.. index:: CLI, YAML
|
||||
@@ -0,0 +1,43 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-104990-1726495719:
|
||||
|
||||
===================================================
|
||||
Feature: #104990 - Automatic frontend cache tagging
|
||||
===================================================
|
||||
|
||||
See :issue:`104990`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
When database records are used in the frontend, and the rendered result is put
|
||||
into caches like the page cache, the TYPO3 frontend now automatically tags cache
|
||||
entries with lists of used records.
|
||||
|
||||
When changing such records in the backend, affected cache entries are dropped,
|
||||
leading to automatic cache eviction.
|
||||
|
||||
This is a huge improvement to previous TYPO3 versions where tagging and cache
|
||||
eviction had to configured manually.
|
||||
|
||||
This feature - automatically tagging cache entries - is the final solution to
|
||||
consistent caches at any point in time. It is however a bit tricky to get right
|
||||
in a performant way: There are still details to rule out, and the core will
|
||||
continue to improve in this area. The basic implementation in TYPO3 v13 however
|
||||
already resolves many use cases. Core development now goes ahead to see how this
|
||||
features behaves in the wild.
|
||||
|
||||
This feature is encapsulated in the feature toggle :php:`frontend.cache.autoTagging`:
|
||||
It is enabled by default with new instances based on TYPO3 v13, and needs to be
|
||||
manually enabled for instances being upgrades from previous versions.
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Instances configured with the feature toggle automatically tag caches. Affected
|
||||
cache entries will be removed when changing records.
|
||||
|
||||
|
||||
.. index:: Frontend, ext:core
|
||||
@@ -0,0 +1,52 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-83835-1711517686:
|
||||
|
||||
=====================================================
|
||||
Feature: #83835 - Check more fields in Link Validator
|
||||
=====================================================
|
||||
|
||||
See :issue:`83835`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Some additional fields were added to Page TSconfig
|
||||
:typoscript:`mod.linkvalidator.searchFields`:
|
||||
|
||||
* :typoscript:`pages = canonical_link`
|
||||
* :typoscript:`sys_redirect = target`
|
||||
* :typoscript:`sys_file_reference = link`
|
||||
|
||||
Two special fields are currently defined, but are
|
||||
not checked yet due to their TCA configuration. For forward
|
||||
compatibility, these are kept in the field configuration:
|
||||
|
||||
* :typoscript:`pages = media` has TCA `type="file"`
|
||||
* :typoscript:`tt_content = records` has TCA `type="group"`
|
||||
|
||||
The following fields could theoretically be included in
|
||||
custom configurations, as their type / softref is available,
|
||||
but they are specifically not added in the default configuration:
|
||||
|
||||
* :typoscript:`sys_webhook = url` (webhook should not be invoked)
|
||||
* :typoscript:`tt_content = subheader` (has softref `email[subst]`
|
||||
which is not a supported link type)
|
||||
* :typoscript:`pages = tsconfig_includes` (system configuration)
|
||||
* :typoscript:`sys_template = constants, include_static_file, config`
|
||||
(system configuration)
|
||||
* :typoscript:`tx_scheduler_task_group = groupName` (scheduler
|
||||
system configuration)
|
||||
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
Broken links in `sys_file_reference.link`, `sys_redirect.target` and
|
||||
`pages.canonical_link` will now be checked.
|
||||
|
||||
Any enabled field will only be checked, if there is TCA configured,
|
||||
so for example `pages.canonical_link` will only be checked if `EXT:seo` is
|
||||
installed.
|
||||
|
||||
.. index:: ext:linkvalidator
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-93100-1710488213:
|
||||
|
||||
==================================================================
|
||||
Feature: #93100 - Allow to directly declare static route variables
|
||||
==================================================================
|
||||
|
||||
See :issue:`93100`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Instead of having to use custom route aspect mappers, implementing
|
||||
:php:`\TYPO3\CMS\Core\Routing\Aspect\StaticMappableAspectInterface`,
|
||||
to avoid having `&cHash=` signatures
|
||||
being applied to the generated URL, variables now can be simply declared
|
||||
`static` in the corresponding route enhancer configuration.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
By using the new `static` route configuration directive, custom aspect
|
||||
mapper implementations can be avoided. However, static route variables
|
||||
are only applied for a particular variable name if
|
||||
|
||||
* there is no aspect mapper configured - aspect mappers are
|
||||
considered more specific and will take precedence
|
||||
* there is a companion `requirements` definition which narrows the
|
||||
set of possible values, and should be as restrictive as possible
|
||||
to avoid potential cache flooding - `static` routes variables are
|
||||
ignored, if there is no corresponding `requirements` definition
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
routeEnhancers:
|
||||
Verification:
|
||||
type: Simple
|
||||
routePath: '/verify/{code}'
|
||||
static:
|
||||
code: true
|
||||
requirements:
|
||||
# only allows SHA1-like hex values - which still allows lots
|
||||
# of possible combinations - thus, for this particular example
|
||||
# the handling frontend controller should be uncached as well
|
||||
#
|
||||
# hint: if `static` is set, `requirements` must be set as well
|
||||
code: '[a-f0-9]{40}'
|
||||
|
||||
As a result, using the URI query parameters `&code=11f6ad8ec52a2984abaafd7c3b516503785c2072`
|
||||
would generate the URL `https://example.org/verify/11f6ad8ec52a2984abaafd7c3b516503785c2072`.
|
||||
|
||||
.. index:: Frontend, YAML, ext:core
|
||||
@@ -0,0 +1,23 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-99418-1722544152:
|
||||
|
||||
============================================
|
||||
Feature: #99418 - Enable recycler by default
|
||||
============================================
|
||||
|
||||
See :issue:`99418`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The TYPO3 system extension :composer:`typo3/cms-recycler` is now enabled by default for new TYPO3 installations.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
New composer-based TYPO3 installations based on the TYPO3 CMS Base Distribution,
|
||||
and new legacy installations (tarball / zip download) have the system extension `recycler`
|
||||
enabled by default.
|
||||
|
||||
.. index:: Backend, ext:recycler
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _feature-99510-1716815124:
|
||||
|
||||
================================================================
|
||||
Feature: #99510 - Add file embedding option to asset ViewHelpers
|
||||
================================================================
|
||||
|
||||
See :issue:`99510`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The ViewHelpers :ref:`<f:asset.css> <t3viewhelper:typo3-fluid-asset-css>`
|
||||
and :ref:`<f:asset.script> <t3viewhelper:typo3-fluid-asset-script>` have
|
||||
been extended with a new argument :fluid:`inline`. If this argument is set,
|
||||
the referenced asset file is rendered inline.
|
||||
|
||||
Setting the argument will therefore load the file content of the defined
|
||||
:fluid:`href` / :fluid:`src` as inline style or script. This is especially
|
||||
useful for content elements which are used as first element on a page and
|
||||
need some custom CSS to improve the Cumulative Layout Shift (CLS).
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
To add inline styles and scripts from a referenced file, the new :fluid:`inline`
|
||||
argument can be set. For example, to add above-the-fold styles, the
|
||||
:fluid:`priority` option can be set, which will put the file contents of
|
||||
:file:`EXT:sitepackage/Resources/Public/Css/my-hero.css` as inline styles
|
||||
to the :html:`<head>` section.
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<f:asset.css identifier="my-hero" href="EXT:sitepackage/Resources/Public/Css/my-hero.css" inline="1" priority="1"/>
|
||||
|
||||
To add JavaScript:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<f:asset.script identifier="my-hero" src="EXT:sitepackage/Resources/Public/Js/my-hero.js" inline="1" priority="1"/>
|
||||
|
||||
.. index:: Fluid, Frontend, ext:fluid
|
||||
@@ -0,0 +1,36 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _important-101535-1726059919:
|
||||
|
||||
=============================================================
|
||||
Important: #101535 - Unused DB fields from tt_content removed
|
||||
=============================================================
|
||||
|
||||
See :issue:`101535`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The database table `tt_content` contains all necessary fields for rendering
|
||||
content elements.
|
||||
|
||||
Back with TYPO3 v4.7, a major feature to render certain Content Types in a more
|
||||
accessible way, funded by the German Government (BLE_) with the
|
||||
"Konjunkturpaket II" was merged into CSS Styled Content.
|
||||
|
||||
In this procedure, certain Content Types received new fields and rendering definitions, which
|
||||
were stored in the database fields `accessibility_title`, `accessibility_bypass`
|
||||
and `accessibility_bypass_text`.
|
||||
|
||||
When CSS Styled Content was removed in favor of Fluid Styled Content in TYPO3 v8, the DB
|
||||
fields continued to exist in TYPO3 Core, so a migration from CSS Styled Content was possible.
|
||||
|
||||
However, the DB fields are not evaluated anymore since then, and are removed, along with
|
||||
their TCA definition in `tt_content`.
|
||||
|
||||
If these fields are still relevant for a custom legacy installation, these DB fields need to be
|
||||
re-created via TCA for further use in a third-party extension.
|
||||
|
||||
.. _BLE: https://typo3.org/article/typo3-receives-german-governmental-funding-for-accessibility-and-usability-project
|
||||
|
||||
.. index:: Database, PHP-API, ext:frontend
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _important-104126-1714290385:
|
||||
|
||||
============================================================================================
|
||||
Important: #104126 - Drop "typo3conf" directory from system status check and backend locking
|
||||
============================================================================================
|
||||
|
||||
See :issue:`104126`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
The directory :path:`typo3conf` is no longer needed in Composer Mode.
|
||||
Checking for the existence of this directory is no longer performed in the
|
||||
Environment and Install Tool.
|
||||
|
||||
Previously it contained:
|
||||
|
||||
* extensions (which are now Composer packages stored in :file:`vendor/`),
|
||||
* the configuration files (which are now part of the :file:`config/` tree)
|
||||
* language labels and some artifact states (now part of :file:`var/`)
|
||||
* a "backend lock" file (:file:`LOCK_BACKEND`)
|
||||
|
||||
The location to this file can be adjusted via the new configuration setting
|
||||
:php:`$GLOBALS['TYPO3_CONF_VARS']['BE']['lockBackendFile']`. See
|
||||
:ref:`<feature-104126-1714290385>` for details on this setting and location.
|
||||
|
||||
By default, :file:`LOCK_BACKEND` is now located here:
|
||||
|
||||
* :path:`var/lock/` for Composer Mode
|
||||
* :path:`config/` for Legacy Mode
|
||||
|
||||
.. index:: Backend, CLI, LocalConfiguration, ext:backend
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _important-60357-1777301944:
|
||||
|
||||
==================================================================
|
||||
Important: #60357 - CType and colPos locked for translated content
|
||||
==================================================================
|
||||
|
||||
See :issue:`60357`
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Starting with TYPO3 v13.3, the fields :sql:`CType` and :sql:`colPos` of
|
||||
connected :sql:`tt_content` translations are locked to the values of their
|
||||
default-language parent. Both fields are now configured with
|
||||
:php:`'l10n_mode' => 'exclude'` and
|
||||
:php:`'l10n_display' => 'defaultAsReadonly'`
|
||||
in :file:`EXT:frontend/Configuration/TCA/tt_content.php`.
|
||||
|
||||
This prevents editors from accidentally assigning a different content element
|
||||
type or column position to a translated record, which previously caused silent
|
||||
rendering inconsistencies: when the default-language record changed its
|
||||
:sql:`CType`, the translated overlay would keep the old type and could render
|
||||
incorrectly or not at all.
|
||||
|
||||
Impact
|
||||
======
|
||||
|
||||
In the TYPO3 backend, the :guilabel:`Type` and :guilabel:`Column` selectors
|
||||
are now read-only when editing a translated content element in connected
|
||||
translation mode.
|
||||
|
||||
An upgrade wizard (:php:`synchronizeColPosAndCTypeWithDefaultLanguage`)
|
||||
is provided to synchronize connected :sql:`tt_content` translations
|
||||
whose :sql:`CType` or :sql:`colPos` differs from their default-language
|
||||
parent.
|
||||
|
||||
.. warning::
|
||||
|
||||
The upgrade wizard **overwrites** :sql:`CType` and :sql:`colPos` on
|
||||
every connected translation that currently differs from its parent —
|
||||
including records where the difference was intentional. Back up the
|
||||
database and review affected records before executing the wizard.
|
||||
|
||||
Extensions or integrations with connected translations that deliberately
|
||||
use different :sql:`CType` values should align their content to use the
|
||||
same :sql:`CType` across languages.
|
||||
|
||||
.. index:: Database, TCA, ext:frontend
|
||||
@@ -0,0 +1,52 @@
|
||||
:template: changelogOverview.html
|
||||
.. include:: /Includes.rst.txt
|
||||
.. _changelog-13-3:
|
||||
|
||||
============
|
||||
13.3 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, with aiming for as little 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