Skip to content

Commit 086dcda

Browse files
authored
[FEATURE] Enable custom field transformation (#5139)
* [FEATURE] Enable custom field transformation Resolves: TYPO3-Documentation/Changelog-To-Doc#1031 Releases: main, 13.4 * Update Documentation/ApiOverview/DatabaseRecords/RecordObjects.rst
1 parent ebdab6f commit 086dcda

File tree

8 files changed

+198
-15
lines changed

8 files changed

+198
-15
lines changed

Documentation/ApiOverview/DatabaseRecords/RecordObjects.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ to pass record objects to the Fluid templating engine.
3535
Provide records in PHP
3636
======================
3737

38-
.. note::
39-
Creating record objects in PHP is considered experimental.
40-
4138
In PHP a record object can be created by the
4239
:php:`\TYPO3\CMS\Core\Domain\RecordFactory`.
4340

41+
The event :ref:`RecordCreationEvent` can be used to influence or replace
42+
the Record object and its properties during creation.
43+
4444
.. _record_objects_fluid:
4545

4646
Use records in Fluid
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
.. include:: /Includes.rst.txt
2+
.. index:: Events; RecordCreationEvent
3+
.. _RecordCreationEvent:
4+
5+
===================
6+
RecordCreationEvent
7+
===================
8+
9+
.. versionadded:: 13.3
10+
The PSR-14 :php-short:`\TYPO3\CMS\Core\Domain\Event\RecordCreationEvent` is introduced in
11+
order to allow the manipulation of any property
12+
before being used to create a
13+
`Database Record <https://docs.typo3.org/permalink/t3coreapi:database-records>`_ object.
14+
15+
The `Database Record <https://docs.typo3.org/permalink/t3coreapi:database-records>`_ object, which
16+
represents a raw database record based on TCA and is usually used in the
17+
frontend (via Fluid Templates).
18+
19+
The properties of those Record
20+
objects are transformed / expanded from their raw database value into
21+
"rich-flavored" values. Those values might be relations to Record objects implementing
22+
:php-short:`\TYPO3\CMS\Core\Domain\RecordInterface`,
23+
:php-short:`\TYPO3\CMS\Extbase\Domain\Model\FileReference`,
24+
:php:`\TYPO3\CMS\Core\Resource\Folder` or :php:`\DateTimeImmutable` objects.
25+
26+
TYPO3 does not know about custom field meanings, for example latitude and
27+
longitude information, stored in an input field or user settings stored as
28+
JSON in a TCA type `json <https://docs.typo3.org/permalink/t3tca:columns-json>`_
29+
field.
30+
31+
This event is dispatched right before a Record object is created and
32+
therefore allows to fully manipulate any property, even the ones already
33+
transformed by TYPO3.
34+
35+
The new event is stoppable (implementing :php-short:`\Psr\EventDispatcher\StoppableEventInterface`), which
36+
allows listeners to actually create a Record object, implementing
37+
:php:`\TYPO3\CMS\Core\Domain\RecordInterface` completely on their
38+
own.
39+
40+
.. _RecordCreationEvent-example:
41+
42+
Example
43+
=======
44+
45+
The event listener class, using the PHP attribute :php:`#[AsEventListener]` for
46+
registration, creates a :php:`Coordinates` object based on the field value of
47+
the :php:`coordinates` field for the custom :php:`maps` content type.
48+
49+
.. literalinclude:: _RecordCreationEvent/_MyEventListener.php
50+
:caption: EXT:my_extension/Classes/Domain/EventListener/MyEventListener.php
51+
52+
.. include:: /_includes/EventsAttributeAdded.rst.txt
53+
54+
The model could for example look like this:
55+
56+
.. literalinclude:: _RecordCreationEvent/_Coordinates.php
57+
:caption: EXT:my_extension/Classes/Domain/Model/Coordinates.php
58+
59+
.. _RecordCreationEvent-api:
60+
61+
API
62+
===
63+
64+
.. include:: /CodeSnippets/Events/Core/RecordCreationEvent.rst.txt
65+
66+
.. important::
67+
68+
The event operates on the :php-short:`\TYPO3\CMS\Core\Domain\RecordInterface`
69+
instead of an actual implementation. This way, extension authors are able
70+
to set custom records, implementing the interface.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MyVendor\MyExtension\Domain\Model;
6+
7+
class Coordinates
8+
{
9+
public float $latitude = 0.0;
10+
public float $longitude = 0.0;
11+
12+
/**
13+
* @param mixed $value - Accepts a string (e.g., "12.34,56.78")
14+
*/
15+
public function __construct(mixed $value)
16+
{
17+
if (is_string($value)) {
18+
$parts = explode(',', $value);
19+
if (count($parts) === 2) {
20+
$this->latitude = (float)trim($parts[0]);
21+
$this->longitude = (float)trim($parts[1]);
22+
}
23+
}
24+
}
25+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MyVendor\MyExtension\Domain\Access;
6+
7+
use MyVendor\MyExtension\Domain\Model\Coordinates;
8+
use TYPO3\CMS\Core\Attribute\AsEventListener;
9+
use TYPO3\CMS\Core\Domain\Event\RecordCreationEvent;
10+
11+
final readonly class MyEventListener
12+
{
13+
#[AsEventListener]
14+
public function __invoke(RecordCreationEvent $event): void
15+
{
16+
$rawRecord = $event->getRawRecord();
17+
if ($rawRecord->getMainType() !== 'tt_content') {
18+
return;
19+
}
20+
if ($rawRecord->getRecordType() !== 'maps') {
21+
return;
22+
}
23+
if (!$event->hasProperty('coordinates')) {
24+
return;
25+
}
26+
$event->setProperty(
27+
'coordinates',
28+
new Coordinates($event->getProperty('coordinates')),
29+
);
30+
}
31+
}

Documentation/ApiOverview/SiteHandling/_Sets/_site-package/_config.rst.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
:caption: EXT:site_package/Configuration/Sets/SitePackage/config.yaml
66
77
name: t3docs/site-package
8-
label: Example site package set
8+
label: 'Site Package'
99
dependencies:
1010
- typo3/fluid-styled-content
1111
- typo3/fluid-styled-content-css

Documentation/ApiOverview/SiteHandling/_Sets/_site-package/_settings.rst.txt

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
:caption: EXT:site_package/Configuration/Sets/SitePackage/settings.yaml
66
77
styles:
8-
templates:
9-
layoutRootPath: EXT:site_package/Resources/Private/ContentElements/Layouts
10-
partialRootPath: EXT:site_package/Resources/Private/ContentElements/Partials
11-
templateRootPath: EXT:site_package/Resources/Private/ContentElements/Templates
12-
content:
13-
textmedia:
14-
maxW: 1200
15-
maxWInText: 600
16-
linkWrap:
17-
lightboxEnabled: true
18-
lightboxCssClass: lightbox
8+
templates:
9+
layoutRootPath: EXT:site_package/Resources/Private/ContentElements/Layouts
10+
partialRootPath: EXT:site_package/Resources/Private/ContentElements/Partials
11+
templateRootPath: EXT:site_package/Resources/Private/ContentElements/Templates
12+
content:
13+
textmedia:
14+
maxW: 1200
15+
maxWInText: 600
16+
linkWrap:
17+
lightboxEnabled: true
18+
lightboxCssClass: lightbox

Documentation/CodeSnippets/Config/Api/Events/EventsCore.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,4 +338,10 @@
338338
'targetFileName' => 'CodeSnippets/Events/Core/Country/BeforeCountriesEvaluatedEvent.rst.txt',
339339
'withCode' => false,
340340
],
341+
[
342+
'action' => 'createPhpClassDocs',
343+
'class' => \TYPO3\CMS\Core\Domain\Event\RecordCreationEvent::class,
344+
'targetFileName' => 'CodeSnippets/Events/Core/RecordCreationEvent.rst.txt',
345+
'withCode' => false,
346+
],
341347
];
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
.. Generated by https://github.com/TYPO3-Documentation/t3docs-codesnippets
2+
.. php:namespace:: TYPO3\CMS\Core\Domain\Event
3+
4+
.. php:class:: RecordCreationEvent
5+
6+
Event which allows to manipulate the properties to be used for a new Record.
7+
8+
With this event, it's even possible to create a new Record manually.
9+
10+
.. php:method:: setRecord(\TYPO3\CMS\Core\Domain\RecordInterface $record)
11+
12+
:param $record: the record
13+
14+
.. php:method:: isPropagationStopped()
15+
:returns: `bool`
16+
17+
.. php:method:: hasProperty(string $name)
18+
:returns: `bool`
19+
20+
:param $name: the name
21+
22+
.. php:method:: setProperty(string $name, ?mixed $propertyValue)
23+
24+
:param $name: the name
25+
:param $propertyValue: the propertyValue
26+
27+
.. php:method:: setProperties(array $properties)
28+
29+
:param $properties: the properties
30+
31+
.. php:method:: unsetProperty(string $name)
32+
:returns: `bool`
33+
34+
:param $name: the name
35+
36+
.. php:method:: getProperty(string $name)
37+
:returns: `?mixed`
38+
39+
:param $name: the name
40+
41+
.. php:method:: getProperties()
42+
:returns: `array`
43+
44+
.. php:method:: getRawRecord()
45+
:returns: `\TYPO3\CMS\Core\Domain\RawRecord`
46+
47+
.. php:method:: getSystemProperties()
48+
:returns: `\TYPO3\CMS\Core\Domain\Record\SystemProperties`
49+
50+
.. php:method:: getContext()
51+
:returns: `\TYPO3\CMS\Core\Context\Context`

0 commit comments

Comments
 (0)