Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Enable custom field transformation #5139

Merged
merged 2 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 during creation.
linawolf marked this conversation as resolved.
Show resolved Hide resolved
linawolf marked this conversation as resolved.
Show resolved Hide resolved

.. _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)
linawolf marked this conversation as resolved.
Show resolved Hide resolved
{
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`
Loading