ModifyProfileQueryEvent
Narrowing what a plugin shows
\FGTCLB\ and
\FGTCLB\ are dispatched
immediately before a plugin query is executed, and a listener adds conditions
to it. They are the supported way to make a plugin show fewer records than it
would, by a consent flag, a site the profile belongs to or an editorial state.
| Event | Dispatched for |
|---|---|
Modify | the profile query of the list, list-and-detail and card plugins, the letter query of the two list plugins (see Which letters lead somewhere), and the uid lookup of the selected-profiles plugin |
Modify | the uid lookup of the selected-contracts plugin |
When it is dispatched
Profile dispatches the event once for every profile query it
runs for a plugin, after the query settings and the conditions of the plugin
are prepared and before they are applied:
- List and list-and-detail plugins, list action: once for the profiles of the list, after ModifyProfileDemandEvent. While the content element shows the letter navigation and no profiles are selected by hand, once more for the letters, see Which letters lead somewhere.
- Card plugin: once for the profiles the card shows, also after
Modify.Profile Demand Event - Selected-profiles plugin: once for the uid lookup of the selected profiles. No demand event precedes it.
The detail view is not covered, see the rules below.
Modify follows when the action renders, see
ModifyPluginViewEvent.
Code that calls
Profile or
Profile outside the plugins dispatches the
event as well, without a plugin context.
What a listener reads and changes
| Method | What it does |
|---|---|
get | The Extbase
Query of the profiles, to build the
conditions on. |
add | Adds a condition. Every listener may add any number of them. |
get | The conditions the listeners added so far. |
get | The list demand the query is built from, after the listeners of
Modify.
null
for the uid lookup
of the selected-profiles plugin, which knows no demand. |
get | The plugin the query is rendered for, see
The plugin action context.
null
where the
query has no plugin behind it. |
The context carries the plugin name, the settings of the content element, the
request, the site, the language and the content object.
ModifyContractQueryEvent has the same methods
apart from
get.
Example
A site that lists only the profiles of persons who agreed to be published
keeps the agreement in a column of its own, here
public_
on the profile table. The listener restricts the two list plugins to those
profiles and leaves the card and the selected profiles alone, which an editor
fills by hand:
<?php
declare(strict_types=1);
namespace MyVendor\MyExtension\EventListener;
use FGTCLB\AcademicPersons\Event\ModifyProfileQueryEvent;
use TYPO3\CMS\Core\Attribute\AsEventListener;
final class ShowOnlyConsentingProfiles
{
#[AsEventListener(identifier: 'my-extension/show-only-consenting-profiles')]
public function __invoke(ModifyProfileQueryEvent $event): void
{
// The two list plugins only. The card plugin of the same page keeps everything.
if (!in_array($event->getPluginControllerActionContext()?->getPluginName(), ['List', 'ListAndDetail'], true)) {
return;
}
$query = $event->getQuery();
$event->addConstraint($query->equals('publicDisplayConsent', true));
}
}
get is the name a plugin is registered with, not its
content element type. The six names are listed in
The plugin names. The letter query of the list carries the same
context as the list query, so the listener narrows the letters in the same
way.
Rules and pitfalls
The collected conditions are combined with a logical AND with the ones the extension builds itself: the storage folders, the organisational unit and function type filters of the content element, the letter filter, hidden records and the language handling. They are applied before pagination. A constraint therefore only ever narrows a result, and it cannot drop a condition the extension put there.
Warning
That guarantee covers the constraints, and nothing else about the query.
set is called on the query after the event, so a
listener that sets an ordering is overwritten without a notice. The
ordering belongs to the plugin: it is what the editor chose in the content
element, and a listener that changed it would override that choice for
every element at once.
A condition set with
matching instead of
add is
folded into the same AND rather than dropped, so it narrows like any
other. Use
add anyway:
matching replaces what
is on the query, so two listeners doing it leave only the last one's
condition standing, while
add collects.
The query settings, the limit and the offset are live.
get hands out the object the query is parsed from,
and it is read after this event, so a listener that calls
set or
set
on it widens the result past the content element, and a listener that
calls
set cuts it. Nothing guards any of this. It is the same
object because a listener needs it to build an expression in the first
place. Add constraints and leave the rest of the query alone.
The detail view is not covered: neither event is dispatched for it. It resolves its profile through Extbase argument mapping, and the one finder it does use, for a hidden profile while the plugin's "show hidden records" is on, builds its own query and never goes through the shared path these events sit in. So a profile a listener hides from the lists is still reachable through its own detail URL. A condition that has to hold there as well belongs in an access check, not in these events.
A listener that answers the list query and the letter query differently makes the letter navigation offer letters that lead to an empty list, or hide letters that do not. Answer both calls alike.
A project that narrowed the plugins by subclassing or XCLASSing the repositories moves that code here, see Breaking: The plugins call different repository finders.
Introduced in
- Feature: Narrow the profiles and contracts a plugin shows (2.4) introduced the event.
- Feature: The query events say which plugin is asking added the plugin context in 3.0.
- Breaking: The plugins call different repository finders describes the finders that hand the context over.
- Feature: The letter navigation knows which letters lead somewhere dispatches it for the letters as well.
- Important: The profile queries see a letter switching off the pagination makes the list query see a letter switching the pagination off.