Feature: Change the program list, finder and page by event 

Description 

Three PSR-14 events let a project change what the program plugins query and what a program page shows, without replacing a class of the extension:

  • \FGTCLB\AcademicPrograms\Event\ModifyProgramDemandEvent fires in the Course List and the Course Finder after the demand has been built from the content element settings and the request, and before the programs are queried. The demand a listener hands back is the one that is queried, and in the list the one assigned to the view as {demand} .
  • \FGTCLB\AcademicPrograms\Event\ModifyProgramListEvent fires in both after the query and before the view variables are assigned. A listener replaces the programs, replaces the applicable categories, which are the filter options of the list and the select options of the finder, or assigns further view variables.
  • \FGTCLB\AcademicPrograms\Event\ModifyProgramDataEvent fires on a program page once the data processor program-data has built the data of the page from the page record, and before the facts of the page are built from it. The data a listener hands back is what the page template receives as {program} , and the facts show it.

The list and finder events carry \FGTCLB\AcademicBase\Domain\Model\Dto\PluginControllerActionContextInterface , so a listener knows the request, the site, the content element, its settings and whether the list or the finder is rendering. The page event carries the page record and the request.

The events have the names, the arguments and the rules of the partner and project list events. \FGTCLB\AcademicPrograms\Domain\Model\Dto\ProgramDemand and \FGTCLB\AcademicPrograms\Domain\Model\ProgramData , which they hand over, are public API from this version on. The events, their rules and an example listener for each are described in ModifyProgramDemandEvent, ModifyProgramListEvent and ModifyProgramDataEvent.

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

declare(strict_types=1);

namespace MyVendor\MyExtension\EventListener;

use FGTCLB\AcademicPrograms\Event\ModifyProgramDataEvent;
use TYPO3\CMS\Core\Attribute\AsEventListener;

final class ReplaceProgramSubtitle
{
    #[AsEventListener(identifier: 'my-extension/replace-program-subtitle')]
    public function __invoke(ModifyProgramDataEvent $event): void
    {
        $page = $event->getPageRecord();
        if (($page['nav_title'] ?? '') !== '') {
            $event->getProgram()->setSubtitle((string)$page['nav_title']);
        }
    }
}
Copied!

Impact 

Nothing changes in an installation that has no listener. A project that queries the database from a ViewHelper for data of the program page, or replaces the data processor of the program page, can listen instead. A project that subclasses ProgramController to adjust the demand, the result or the view variables has to listen instead, because the controller is final in 3.0 and the subclass no longer loads, see Breaking: The program controllers are final.

The constructor of \FGTCLB\AcademicPrograms\DataProcessing\ProgramDataProcessor takes two more arguments, both resolved by dependency injection:

public function __construct(
    ProgramFactsBuilder $programFactsBuilder,
    ProgramDataFactory $programDataFactory,
    EventDispatcherInterface $eventDispatcher,
)
Copied!

A project that extends the processor and calls the parent constructor passes them on. The processor is no public API, and a listener of ModifyProgramDataEvent replaces such a subclass.