Breaking: Settings apply after the TCA overrides 

Description 

The validators of Configuration/AcademicPersons/Settings.yaml set required and readOnly of a column, and the email and number flags its type, in the TCA of the six person tables. They used to be applied by the TCA files of academic_persons themselves, before any Configuration/TCA/Overrides file of another package ran. They are now applied once the TCA is compiled, by a listener of the PSR-14 event \TYPO3\CMS\Core\Configuration\Event\AfterTcaCompilationEvent with the identifier academic-persons/apply-settings-to-tca. That is after every TCA override, and the result is what the TCA cache and the TCA schema cache hold. The identifier is public API, listed on the extension points page of academic_base. The listener class is not.

Impact 

The settings win over a TCA override of the keys they set. Every field of the settings writes required and readOnly of its column, also when they are false. A site package that sets either of them on a configured column in its TCA overrides loses that value. A column the override replaces as a whole, for a label or a rich text configuration of its own, keeps what the settings say about it now, where the replacement used to drop it silently.

A site package that copies a person column into a table of its own in a TCA override used to copy it with the required and readOnly of the settings, and now copies it without them.

A field of the settings whose column the TCA does not have no longer adds an incomplete column without a type to the TCA. Such a field used to stop the TCA build of the whole installation with Missing "type" in TCA of field.

The TCA listener of content_blocks runs before the TCA overrides and is not affected. The listener of academic_persons is ordered after the identifier content-blocks-tca in case that extension moves its listener to the same event.

Affected Installations 

Installations whose site package changes required or readOnly of a column of a person table in Configuration/TCA/Overrides, or replaces such a column as a whole, where the settings configure a field for that column. The tables are tx_academicpersons_domain_model_profile , tx_academicpersons_domain_model_contract , tx_academicpersons_domain_model_email , tx_academicpersons_domain_model_phone_number , tx_academicpersons_domain_model_address and tx_academicpersons_domain_model_profile_information .

Migration 

Move the lock or the requirement into the settings of the site package, where it reaches the backend form and the profile editor alike:

EXT:my_sitepackage/Configuration/AcademicPersons/Settings.yaml
profile:
  title:
    validators:
      - readonly
Copied!

A value that has to differ from the settings in the backend only is set by a listener of AfterTcaCompilationEvent of the site package, ordered after academic-persons/apply-settings-to-tca:

EXT:my_sitepackage/Classes/EventListener/KeepTitleEditable.php
use TYPO3\CMS\Core\Attribute\AsEventListener;
use TYPO3\CMS\Core\Configuration\Event\AfterTcaCompilationEvent;

final class KeepTitleEditable
{
    #[AsEventListener(
        identifier: 'my-sitepackage/keep-title-editable',
        after: 'academic-persons/apply-settings-to-tca',
    )]
    public function __invoke(AfterTcaCompilationEvent $event): void
    {
        $tca = $event->getTca();
        $tca['tx_academicpersons_domain_model_profile']['columns']['title']['config']['readOnly'] = false;
        $event->setTca($tca);
    }
}
Copied!

Flush the TYPO3 caches afterwards, the compiled TCA is cached.