---
title: "Important: The contract publish wizard has to be registered by hand"
manual: "Academic Profiles"
version: "main"
source: "Changelog/3.0/Important-ContractPublishToHiddenWizard.rst"
rendered: "2026-10-02T20:47:49+00:00"
---

# Important: The contract publish wizard has to be registered by hand {#important-contract-publish-to-hidden-wizard}

## Description {#description}

> [!WARNING]
> Do not register the wizard on an installation whose own code never gave the
> contract field `publish` a meaning. Every contract of such an
> installation carries the default "not published", and the wizard hides
> **all of them**.

[Breaking: The contract field "publish" has been removed](Breaking-ContractPublishFieldRemoved.html#breaking-contract-publish-field-removed) removes the contract field
`publish` in favour of the visibility of the contract. The upgrade wizard
`academicPersons_migrateContractPublishToHidden` carries the flag over: a
contract that was not published is hidden. It is meant for a project whose own
code honoured the flag, for example a template or a query that left
unpublished contracts out.

The wizard ships **unregistered**. The core does not list it in
**Admin Tools > Upgrade > Upgrade Wizard**, and
`vendor/bin/typo3 upgrade:run` does not run it. A project that wants it
declares the class in the `Configuration/Services.yaml` of its site
package:

**EXT:my_sitepackage/Configuration/Services.yaml**

```yaml
services:
  FGTCLB\AcademicPersons\Upgrades\MigrateContractPublishToHiddenUpgradeWizard:
    autowire: true
    autoconfigure: true
```

`autoconfigure` registers it under its identifier, on TYPO3 v13 and v14.
Flush the caches afterwards, so the service container is built again.

## The order {#the-order}

1.  Update the database schema without removing anything. The analyzer offers
    `publish` for removal, do not accept that yet.
1.  Register the wizard as above and flush the caches.
1.  Run it:

    ```bash
    vendor/bin/typo3 upgrade:run academicPersons_migrateContractPublishToHidden
    ```
1.  Flush the frontend caches. The wizard writes the database directly, so a
    page cached before still shows the contracts it hid.
1.  Remove the code of the project that read or wrote the flag, and the
    registration of the wizard.
1.  Let the analyzer drop the column.

The analyzer renames a column to `zzz_deleted_publish` before it drops it.
The wizard reads that name as well, so a renamed column is still migrated. Once
the column is dropped, the flag is gone and nothing can be migrated any more.

## What the wizard does {#what-the-wizard-does}

-   A contract that was not published is hidden. A published contract keeps its
    visibility, hidden or not.
-   The contract in the default language decides, and its translations follow
    it. `hidden` is shared by every language of a contract, so a
    translation that was not published while its default language contract was
    stays visible. The flag of a translation is not read, unless the translation
    has no default language contract, then it decides for itself.
-   Live records, workspace versions and deleted records are all migrated, so a
    version that is published later or a record that is restored keeps the
    meaning it had. A workspace version of a translation follows the version of
    its default language contract in the same workspace, and the live contract
    where that workspace has none.
-   It writes the database directly, not through the `DataHandler`, and it
    writes the translations itself: the core copies `hidden` into the
    translations only when the `DataHandler` saves a contract.
-   Running it again changes nothing.

A contract that was hidden by mistake is shown again in the backend or with the
hide action of the frontend editor.
