Feature: Narrow the profiles and contracts a plugin shows 

Description 

\FGTCLB\AcademicPersons\Event\ModifyProfileQueryEvent and \FGTCLB\AcademicPersons\Event\ModifyContractQueryEvent are PSR-14 events dispatched immediately before a plugin query is executed. A listener adds conditions to it, and the records that do not satisfy them are not shown.

The profile event covers every plugin that lists profiles: the list, the list-and-detail, the card and the selected-profiles plugin. The contract event covers the selected-contracts plugin. Neither is dispatched for the detail view, which resolves its profile through Extbase argument mapping.

A listener builds its conditions on the query the event carries and hands each of them to addConstraint() :

EXT:my_extension/Classes/EventListener/ShowOnlyProfilesWithAWebsite.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\EventListener;

use FGTCLB\AcademicPersons\Event\ModifyProfileQueryEvent;

final class ShowOnlyProfilesWithAWebsite
{
    public function __invoke(ModifyProfileQueryEvent $event): void
    {
        $query = $event->getQuery();
        $event->addConstraint($query->logicalNot($query->equals('website', '')));
    }
}
Copied!
EXT:my_extension/Configuration/Services.yaml
services:
  MyVendor\MyExtension\EventListener\ShowOnlyProfilesWithAWebsite:
    tags:
      - name: event.listener
        identifier: 'my-extension/show-only-profiles-with-a-website'
        event: FGTCLB\AcademicPersons\Event\ModifyProfileQueryEvent
Copied!

\TYPO3\CMS\Core\Attribute\AsEventListener does not exist on TYPO3 v12, so a listener that has to run on both supported versions is registered with the tag rather than with the attribute.

getDemand() of the profile event is the list demand behind a query, and null for the lookup of the uids an editor selected, because a selected-profiles plugin knows no demand. ModifyContractQueryEvent has no demand at all, for the same reason: a contract query is only ever such a lookup.

Impact 

The conditions a listener adds are combined with the ones the extension builds itself with a logical AND: the storage folders, the organisational unit and function type filters of the content element, the letter filter, the hidden records setting and the language handling. A constraint therefore only ever narrows a result, and it cannot remove a condition the extension put there.

They apply before pagination, so the number of pages and the profiles on each page follow them. A list of five profiles that a listener reduces to two, paginated two per page, is one page and not three.

Nothing changes in an installation that has no listener, and nothing in this release is breaking: no repository signature moved, and both uid lookups keep their signature and their callers.

The ordering stays with the extension. setOrderings() is called on the query after the event, so a listener that sets an ordering of its own is overwritten without a notice. The order of a list is what the editor chose in the content element.

Affected Installations 

Installations that want to narrow the profiles or contracts the plugins of this extension show, beyond what the content element offers.