BeforeProfileMappedFromFrontendUserEvent
\FGTCLB\
hands a listener the data of a frontend user before the frontend user
synchronisation maps it onto a profile. A listener adds values of its own,
which the map then reads like columns, changes values, or skips the frontend
user.
When it is dispatched
Abstract dispatches the event, so every factory extending
it does, a project's factory included, unless it overrides
create or
update without calling
the parent method:
academic:: once per frontend user, before a profile is created for it.createprofiles academic:: once per synchronised profile of the frontend user, before the profile is updated. Not for a profile whoseupdateprofiles skip_flag is set.sync
It is step 2 of the run described in Taking part in the frontend user synchronisation, after ChooseProfileFactoryEvent and before AfterProfileMappedFromFrontendUserEvent.
What a listener reads and changes
| Method | What it does |
|---|---|
get,
set | The data the map reads, the
fe_ record of the
frontend user plus what listeners added. |
get |
Profile or
Profile. |
get | The profile about to be updated,
null
when a profile is
created. |
skip,
is | Skips the frontend user on creation and the profile on update, and tells whether a listener did. |
Adding values
A value a listener adds is read by the map like a column of the frontend user.
Name it {source}., for example ldap.: no column of a TYPO3
table contains a dot, so such a key never hides a real column. The convention
is not enforced. Keep
uid
and
pid
as they are, the default
factory stores the profile on the page
pid
and names the imported
records after
uid
.
The default factory refuses a map that reads a key the data does not have,
with the code 1790142326. A listener that adds a key the map reads
therefore adds it for every frontend user, as '' when its source has no
value.
frontendUserSync:
contract:
room: ldap.room
Skipping
After
skip on creation,
academic: creates no
profile for the frontend user and goes on with the next one. The next run asks
again, because the frontend user still has no profile. On update, the event
belongs to one profile, and
academic: leaves that profile
as it is and does not announce it, like a profile whose
skip_ flag
is set. The other profiles of the frontend user are updated as usual, so a
listener that should skip the whole frontend user skips every one of its
events. Listeners after the one that skipped still run, and
is
tells them.
Example
A site reads the room and the gender of its staff from a directory service. Listeners are shared services, one object for the whole run and every frontend user of it. Keep nothing of one frontend user in a property of the listener, and fetch what it needs per event:
<?php
declare(strict_types=1);
namespace MyVendor\MySitepackage\EventListener;
use FGTCLB\AcademicPersons\Event\BeforeProfileMappedFromFrontendUserEvent;
use FGTCLB\AcademicPersons\Profile\ProfileActionType;
use MyVendor\MySitepackage\Directory\DirectoryClient;
use TYPO3\CMS\Core\Attribute\AsEventListener;
final readonly class AddDirectoryData
{
public function __construct(
private DirectoryClient $directoryClient,
) {}
#[AsEventListener(identifier: 'my-sitepackage/add-directory-data')]
public function __invoke(BeforeProfileMappedFromFrontendUserEvent $event): void
{
$frontendUserData = $event->getFrontendUserData();
$entry = $this->directoryClient->findByUsername((string)$frontendUserData['username']);
if ($entry === null && $event->getAction() === ProfileActionType::Create) {
// Unknown to the directory: no profile is created for the frontend user.
$event->skip();
return;
}
// An existing profile keeps being updated, with empty directory values when the entry is gone.
$event->setFrontendUserData([
...$frontendUserData,
'ldap.room' => $entry?->room ?? '',
'ldap.gender' => $entry?->gender ?? '',
]);
}
}
The value ldap. is translated into one the profile offers by the
example of AfterProfileMappedFromFrontendUserEvent.
Rules and pitfalls
- On update, each event starts from the data of the frontend user, not from what a listener set for the profile before.
- A factory that implements
Profiledirectly dispatches the event only if it does so itself.Factory Interface - Listeners of one event are ordered with the
beforeandafterarguments of#. Use TYPO3's attribute,[As Event Listener] \TYPO3\: Symfony's registers nothing, and the listener never runs.CMS\ Core\ Attribute\ As Event Listener
Introduced in
- Feature: Events to add data to the synchronisation and adjust profiles introduced the event.