Skip to content

Commit

Permalink
[Backport 13.4] [FEATURE] Enable custom field transformation (#5142)
Browse files Browse the repository at this point in the history
* [FEATURE] Enable custom field transformation

Resolves: TYPO3-Documentation/Changelog-To-Doc#1031
Releases: main, 13.4

* Update Documentation/ApiOverview/DatabaseRecords/RecordObjects.rst

---------

Co-authored-by: lina.wolf <[email protected]>
Co-authored-by: Lina Wolf <[email protected]>
  • Loading branch information
3 people authored Dec 11, 2024
1 parent fcd5ce7 commit 35aa8dc
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 15 deletions.
6 changes: 3 additions & 3 deletions Documentation/ApiOverview/DatabaseRecords/RecordObjects.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ to pass record objects to the Fluid templating engine.
Provide records in PHP
======================

.. note::
Creating record objects in PHP is considered experimental.

In PHP a record object can be created by the
:php:`\TYPO3\CMS\Core\Domain\RecordFactory`.

The event :ref:`RecordCreationEvent` can be used to influence or replace
the Record object and its properties during creation.

.. _record_objects_fluid:

Use records in Fluid
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
.. include:: /Includes.rst.txt
.. index:: Events; RecordCreationEvent
.. _RecordCreationEvent:

===================
RecordCreationEvent
===================

.. versionadded:: 13.3
The PSR-14 :php-short:`\TYPO3\CMS\Core\Domain\Event\RecordCreationEvent` is introduced in
order to allow the manipulation of any property
before being used to create a
`Database Record <https://docs.typo3.org/permalink/t3coreapi:database-records>`_ object.

The `Database Record <https://docs.typo3.org/permalink/t3coreapi:database-records>`_ object, which
represents a raw database record based on TCA and is usually used in the
frontend (via Fluid Templates).

The properties of those Record
objects are transformed / expanded from their raw database value into
"rich-flavored" values. Those values might be relations to Record objects implementing
:php-short:`\TYPO3\CMS\Core\Domain\RecordInterface`,
:php-short:`\TYPO3\CMS\Extbase\Domain\Model\FileReference`,
:php:`\TYPO3\CMS\Core\Resource\Folder` or :php:`\DateTimeImmutable` objects.

TYPO3 does not know about custom field meanings, for example latitude and
longitude information, stored in an input field or user settings stored as
JSON in a TCA type `json <https://docs.typo3.org/permalink/t3tca:columns-json>`_
field.

This event is dispatched right before a Record object 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 Record object, implementing
:php:`\TYPO3\CMS\Core\Domain\RecordInterface` completely on their
own.

.. _RecordCreationEvent-example:

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.

.. literalinclude:: _RecordCreationEvent/_MyEventListener.php
:caption: EXT:my_extension/Classes/Domain/EventListener/MyEventListener.php

.. include:: /_includes/EventsAttributeAdded.rst.txt

The model could for example look like this:

.. literalinclude:: _RecordCreationEvent/_Coordinates.php
:caption: EXT:my_extension/Classes/Domain/Model/Coordinates.php

.. _RecordCreationEvent-api:

API
===

.. include:: /CodeSnippets/Events/Core/RecordCreationEvent.rst.txt

.. 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.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Domain\Model;

class Coordinates
{
public float $latitude = 0.0;
public float $longitude = 0.0;

/**
* @param mixed $value - Accepts a string (e.g., "12.34,56.78")
*/
public function __construct(mixed $value)
{
if (is_string($value)) {
$parts = explode(',', $value);
if (count($parts) === 2) {
$this->latitude = (float)trim($parts[0]);
$this->longitude = (float)trim($parts[1]);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Domain\Access;

use MyVendor\MyExtension\Domain\Model\Coordinates;
use TYPO3\CMS\Core\Attribute\AsEventListener;
use TYPO3\CMS\Core\Domain\Event\RecordCreationEvent;

final readonly class MyEventListener
{
#[AsEventListener]
public function __invoke(RecordCreationEvent $event): void
{
$rawRecord = $event->getRawRecord();
if ($rawRecord->getMainType() !== 'tt_content') {
return;
}
if ($rawRecord->getRecordType() !== 'maps') {
return;
}
if (!$event->hasProperty('coordinates')) {
return;
}
$event->setProperty(
'coordinates',
new Coordinates($event->getProperty('coordinates')),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
:caption: EXT:site_package/Configuration/Sets/SitePackage/config.yaml
name: t3docs/site-package
label: Example site package set
label: 'Site Package'
dependencies:
- typo3/fluid-styled-content
- typo3/fluid-styled-content-css
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
:caption: EXT:site_package/Configuration/Sets/SitePackage/settings.yaml
styles:
templates:
layoutRootPath: EXT:site_package/Resources/Private/ContentElements/Layouts
partialRootPath: EXT:site_package/Resources/Private/ContentElements/Partials
templateRootPath: EXT:site_package/Resources/Private/ContentElements/Templates
content:
textmedia:
maxW: 1200
maxWInText: 600
linkWrap:
lightboxEnabled: true
lightboxCssClass: lightbox
templates:
layoutRootPath: EXT:site_package/Resources/Private/ContentElements/Layouts
partialRootPath: EXT:site_package/Resources/Private/ContentElements/Partials
templateRootPath: EXT:site_package/Resources/Private/ContentElements/Templates
content:
textmedia:
maxW: 1200
maxWInText: 600
linkWrap:
lightboxEnabled: true
lightboxCssClass: lightbox
6 changes: 6 additions & 0 deletions Documentation/CodeSnippets/Config/Api/Events/EventsCore.php
Original file line number Diff line number Diff line change
Expand Up @@ -338,4 +338,10 @@
'targetFileName' => 'CodeSnippets/Events/Core/Country/BeforeCountriesEvaluatedEvent.rst.txt',
'withCode' => false,
],
[
'action' => 'createPhpClassDocs',
'class' => \TYPO3\CMS\Core\Domain\Event\RecordCreationEvent::class,
'targetFileName' => 'CodeSnippets/Events/Core/RecordCreationEvent.rst.txt',
'withCode' => false,
],
];
51 changes: 51 additions & 0 deletions Documentation/CodeSnippets/Events/Core/RecordCreationEvent.rst.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
.. Generated by https://github.com/TYPO3-Documentation/t3docs-codesnippets
.. php:namespace:: TYPO3\CMS\Core\Domain\Event
.. php:class:: RecordCreationEvent
Event which allows to manipulate the properties to be used for a new Record.

With this event, it's even possible to create a new Record manually.

.. php:method:: setRecord(\TYPO3\CMS\Core\Domain\RecordInterface $record)
:param $record: the record

.. php:method:: isPropagationStopped()
:returns: `bool`

.. php:method:: hasProperty(string $name)
:returns: `bool`

:param $name: the name

.. php:method:: setProperty(string $name, ?mixed $propertyValue)
:param $name: the name
:param $propertyValue: the propertyValue

.. php:method:: setProperties(array $properties)
:param $properties: the properties

.. php:method:: unsetProperty(string $name)
:returns: `bool`

:param $name: the name

.. php:method:: getProperty(string $name)
:returns: `?mixed`

:param $name: the name

.. php:method:: getProperties()
:returns: `array`

.. php:method:: getRawRecord()
:returns: `\TYPO3\CMS\Core\Domain\RawRecord`

.. php:method:: getSystemProperties()
:returns: `\TYPO3\CMS\Core\Domain\Record\SystemProperties`

.. php:method:: getContext()
:returns: `\TYPO3\CMS\Core\Context\Context`

0 comments on commit 35aa8dc

Please sign in to comment.