---
title: "ModifyProfileTitlePlaceholderReplacementEvent"
manual: "Academic Profiles"
version: "main"
permalink: "https://docs.typo3.org/permalink/fgtclb/academic-persons:developers-event-modify-profile-title-placeholder-replacement-event@main"
source: "Developers/Events/ModifyProfileTitlePlaceholderReplacementEvent.rst"
rendered: "2026-10-15T10:24:29+00:00"
---

# ModifyProfileTitlePlaceholderReplacementEvent {#developers-event-modify-profile-title-placeholder-replacement-event}

`\FGTCLB\AcademicPersons\Event\ModifyProfileTitlePlaceholderReplacementEvent`
lets a listener decide what a placeholder of the page title format of the
detail view is replaced with. It is the way to give the format placeholders of
a project's own, without replacing the page title provider.

## When it is dispatched {#when-it-is-dispatched}

The detail action of the detail plugin and of the list-and-detail plugin sets
the page title of the profile it shows, before it renders. The title is built
from the page title format of the content element, from the setting
`plugin.tx_academicpersons.settings.pageTitleFormat` while the
content element sets none, or from the built-in format
`%%TITLE%% %%FIRST_NAME%% %%MIDDLE_NAME%% %%LAST_NAME%%`.

The event is dispatched once for every placeholder of the format, a text
between two `%%`, in the order the placeholders appear. Before it, the
extension has already replaced what it knows:

1.  A placeholder that names a getter of the profile is replaced by its value:
    `%%FIRST_NAME%%` by `getFirstName()`.
1.  A placeholder that starts with `LLL:EXT:` is replaced by the translation
    of that label in the language of the site.
1.  The event is dispatched with what these two steps produced.

The detail view never dispatches the event for a profile that does not exist:
it answers with the page-not-found response of the site before.

## What a listener reads and changes {#what-a-listener-reads-and-changes}

| Method | What it does |
| --- | --- |
| `getPlaceholder()` | The placeholder as it stands in the format, without the surrounding `%%`, for example `FIRST_NAME`. |
| `getReplacement()` | The value the placeholder is going to be replaced with. Equal to `getPlaceholder()` while nothing replaced it. |
| `setReplacement()` | Sets that value. |
| `getProfile()` | The profile of the detail view, in the language of the page. |
| `getPluginControllerActionContext()` | The plugin the title is built for, see [The plugin action context](https://docs.typo3.org/permalink/fgtclb/academic-persons:developers-plugin-action-context@main). Never `null` here. |

## Example {#example}

A site wants the organisational unit of the first contract in the title of the
detail page, with the format
`%%FIRST_NAME%% %%LAST_NAME%% - %%ORGANISATIONAL_UNIT%%`. The profile has no
getter of that name, so the placeholder reaches the listener unreplaced:

**EXT:my_extension/Classes/EventListener/ReplaceOrganisationalUnitPlaceholder.php**

```php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\EventListener;

use FGTCLB\AcademicPersons\Domain\Model\Contract;
use FGTCLB\AcademicPersons\Event\ModifyProfileTitlePlaceholderReplacementEvent;
use TYPO3\CMS\Core\Attribute\AsEventListener;

final class ReplaceOrganisationalUnitPlaceholder
{
    #[AsEventListener(identifier: 'my-extension/replace-organisational-unit-placeholder')]
    public function __invoke(ModifyProfileTitlePlaceholderReplacementEvent $event): void
    {
        if ($event->getPlaceholder() !== 'ORGANISATIONAL_UNIT') {
            return;
        }
        $unitName = '';
        foreach ($event->getProfile()->getContracts() as $contract) {
            if ($contract instanceof Contract && $contract->getOrganisationalUnit() !== null) {
                $unitName = $contract->getOrganisationalUnit()->getUnitName();
                break;
            }
        }
        $event->setReplacement($unitName);
    }
}
```

An empty replacement removes the placeholder from the title. Spaces at the
start and the end of the title are removed and repeated spaces are collapsed
into one, so a missing middle name leaves no gap. The dash of the format above
stays, though, when the profile has no unit.

## Rules and pitfalls {#rules-and-pitfalls}

-   **A replacement equal to the placeholder counts as no replacement.** The
    placeholder then stays in the title as it is, with its `%%`. A listener
    that wants a placeholder gone sets an empty string.
-   Name a placeholder of your own so that it matches no getter of the profile:
    a placeholder that matches one is replaced by the value of that getter
    before the listener is called, and the listener sees that value as the
    replacement.
-   The event is dispatched for every placeholder, the shipped ones included.
    Return early for every placeholder the listener does not handle.
-   A placeholder may contain letters, digits, the underscore, spaces and the
    characters `;:./-\`. Anything else ends the match, and the text stays in
    the title.
-   The context declares the interface of this extension, which is deprecated.
    Type code that receives it against the interface of
    **academic_base**, see [The plugin action context](https://docs.typo3.org/permalink/fgtclb/academic-persons:developers-plugin-action-context@main).

## Introduced in {#introduced-in}

-   [Feature: Introduce PSR-14 ModifyProfileTitlePlaceholderReplacementEvent in ProfileTitleProvider](https://docs.typo3.org/permalink/fgtclb/academic-persons:feature-1746706500@main) (2.1) introduced the event.
-   [Feature: Introduce localized pageTitleFormat placeholder (LLL:EXT:)](https://docs.typo3.org/permalink/fgtclb/academic-persons:feature-1746706600@main) (2.1) added the `LLL:EXT:` placeholders that
    are replaced before it.
-   [Breaking: The persons plugin action context extends the one of academic_base](https://docs.typo3.org/permalink/fgtclb/academic-persons:breaking-plugin-controller-action-context-interface-extends-base@main)
    made its context satisfy the interface of **academic_base** in
    3.0.
-   [Deprecation: The plugin action context of academic_persons](https://docs.typo3.org/permalink/fgtclb/academic-persons:deprecation-persons-plugin-controller-action-context@main) deprecates the
    context interface it declares.
-   [Breaking: The list, detail and selection events of the plugins are gone](https://docs.typo3.org/permalink/fgtclb/academic-persons:breaking-removed-profile-view-events@main) points the removed page title
    methods of the detail event here.
