---
title: "Upgrading from 2.3 to 2.4"
manual: "Academic Jobs"
version: "3.0"
permalink: "https://docs.typo3.org/permalink/fgtclb/academic-jobs:upgrade-from-2-3-to-2-4@3.0"
source: "Upgrade/From23To24.rst"
rendered: "2026-10-26T17:55:19+00:00"
---

# Upgrading from 2.3 to 2.4 {#upgrade-from-2-3-to-2-4}

Version 2.4 delivers the configuration of **academic_jobs** per
component, hides its content elements until a site enables them and repairs the
job contacts and the jobs of the old new job form with two upgrade wizards.
Work through the sections in order. Skip a step that does not apply to the
installation.

## Before you start {#upgrade-from-2-3-to-2-4-before-you-start}

Version 2.4 runs on TYPO3 12.4 from 12.4.22 on and on TYPO3 13.4, with PHP 8.1
or later. That is the same as for 2.3, so the TYPO3 core does not have to
change for this upgrade.

**academic_jobs** 2.4 needs these packages. Upgrade them first or in
the same deployment, in this order:

-   [`fgtclb/environment-state-manager`](https://packagist.org/packages/fgtclb/environment-state-manager) 1.x, new in 2.4, which
    **academic_base** 2.4 requires. Composer installs it on its own. A
    classic installation installs **environment_state_manager** before
    it activates **academic_base** 2.4.
-   [`fgtclb/academic-base`](https://packagist.org/packages/fgtclb/academic-base) 2.4, the same release as this extension.

`ext_emconf.php` now names the system extensions **rte_ckeditor**
and **fluid_styled_content** by their extension keys. A classic
installation resolves its dependencies from that file, so both have to be
active. See [Important: Dependencies are named by their extension keys](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-1790336613@3.0).

## Update the package {#upgrade-from-2-3-to-2-4-package}

```bash
composer require -W \
    'fgtclb/academic-base':'~2.4.0' \
    'fgtclb/academic-jobs':'~2.4.0'
```

A project that requires branch `2` as `2.x-dev` keeps an inline alias such
as `2.x-dev as 2.4.x-dev` working, see [Important: The development branch installs as 2.4.x-dev](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-1790796662@3.0).

On a classic installation, install **environment_state_manager** 1.x
from the TER in **Admin Tools > Extensions** first, then update
**academic_base** and **academic_jobs** there, in this order.
Run the commands of this page with `typo3/sysext/core/bin/typo3` instead
of `vendor/bin/typo3`.

```bash
vendor/bin/typo3 cache:flush
```

## Update the database {#upgrade-from-2-3-to-2-4-database}

Apply the database changes in **Admin Tools > Maintenance > Analyze
Database Structure**, or on the command line:

```bash
vendor/bin/typo3 extension:setup
```

For this extension the comparison adds and changes:

-   `company_name`, `sector`, `required_degree` and
    `contractual_relationship` of `tx_academicjobs_domain_model_job`
    become nullable. No data is converted, see [Important: Four job columns are nullable now](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-1785882500@3.0).
-   `l10n_source` is added to the same table, where a translation records
    the record it was made from. Existing rows get `0`, see
    [Important: The job table records its translation source](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-ace-463-academic-jobs@3.0).

> [!WARNING]
> Do not remove the old job contact table and field yet. Version 2.1 dropped
> `tx_academicjobs_domain_model_contact` and the field `contact` of
> the job table, and the analyzer offers both in its remove section, first
> to rename them to `zzz_deleted_tx_academicjobs_domain_model_contact`
> and `zzz_deleted_contact`, then to drop them. Renaming is harmless.
> Dropping them deletes the contacts the wizard of the next section still
> has to copy, see [Important: The job contact wizard finds the renamed old schema](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-job-contact-wizard-finds-renamed-table@3.0).
> `extension:setup` removes nothing, it applies additions and changes
> only.

## Run the upgrade wizards {#upgrade-from-2-3-to-2-4-wizards}

Both wizards need the database changes of the previous section. Run them in
this order, in **Admin Tools > Upgrade > Upgrade Wizard** or on the
command line.

1.  `academicJobs_contactRelation`, **Migrate job contact records
    from relation to fields directly in the job record**. It copies the contact
    record of a job into the contact fields of the job. Up to 2.3 it left out
    every job that was hidden, scheduled or expired while it ran, which
    includes every job submitted through the frontend form and not yet
    approved. It now reads every job and leaves a job alone that has a contact
    of its own. An installation that already ran it has it recorded as done
    and marks it undone first. TYPO3 13 marks a wizard undone with
    `vendor/bin/typo3 upgrade:mark:undone academicJobs_contactRelation`.
    TYPO3 12 has no such command: open
    **Admin Tools > Upgrade > Upgrade Wizard**, find the wizard under
    **Wizards marked as done** and choose **Mark undone**. For
    a wizard that was never marked done, the TYPO3 13 command reports an
    error, which is harmless. Then run the wizard:

    ```bash
    vendor/bin/typo3 upgrade:run academicJobs_contactRelation
    ```

    Read [Important: The job contact wizard migrates invisible jobs](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-job-contact-wizard-migrates-invisible-jobs@3.0) before
    running it: a job whose contact fields an editor emptied on purpose gets
    its old contact back.
1.  `academicJobs_repairNewJobFormValues`, **Repair the jobs stored
    by the old new job form of academic jobs**. It moves the start date and the
    application deadline the old form stored with the time of day of the
    submission to whole days, and lists the jobs that kept an unchosen
    **Employment Type** or **Job Type** for an editor. It
    writes the database directly, in the time zone of the process that runs
    it, and a wrong zone moves the dates in a way that cannot be taken back.
    Check the time zone its description names first. If it is not the zone
    the form ran in, set
    `$GLOBALS['TYPO3_CONF_VARS']['SYS']['phpTimeZone']`, or run the
    wizard from the upgrade module, which runs in the web server like the form
    did:

    ```bash
    vendor/bin/typo3 upgrade:list
    vendor/bin/typo3 upgrade:run academicJobs_repairNewJobFormValues
    vendor/bin/typo3 cache:flush
    ```

    Keep the list of jobs it prints, it is shown once. Correct those jobs in
    the backend. See [Important: A wizard repairs the jobs of the old new job form](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-repair-wizard-for-jobs-of-the-old-form@3.0)
    and [Important: The new job form stores the chosen values](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-new-job-form-stores-the-chosen-values@3.0).

## Adapt the configuration {#upgrade-from-2-3-to-2-4-configuration}

The TypoScript and the page TSconfig are now delivered per content element,
and the three content elements are hidden in the whole installation until the
page TSconfig of their component is included. See
[Breaking: Site sets and static templates have been restructured](https://docs.typo3.org/permalink/fgtclb/academic-jobs:breaking-site-sets-and-static-templates-restructured@3.0).

### Include the components {#upgrade-from-2-3-to-2-4-components}

-   **Site set, TYPO3 13 only.** A site that depends on the set
    `fgtclb/academic-jobs` needs no change. The set keeps its name and now
    brings the page TSconfig of all three content elements along.
-   **Static template.** The stored entry of 2.3 keeps working as
    **Academic Jobs: Shared plugin settings (academic_jobs)**. Replace
    it with **Academic Jobs: All components (academic_jobs)**, or with
    the entries of the content elements the site uses, in the field
    **Include TypoScript sets** on the tab
    **Advanced Options** of the template record.
-   **Page TSconfig.** A site without the site set, which is every site on
    TYPO3 12, adds **Academic Jobs: All components (academic_jobs)**
    in the field **Include static Page TSconfig (from extensions)** on
    the tab **Resources** of its root page, see
    [Include static page TSconfig](https://docs.typo3.org/permalink/fgtclb/academic-jobs:static-pagetsconfig@3.0). Without it the content elements are not offered
    for new content.
-   Use one of the two mechanisms per site, see
    [Do not combine both](https://docs.typo3.org/permalink/fgtclb/academic-jobs:one-mechanism-per-site@3.0).

Until a component is included, an existing content element of it keeps
rendering and keeps its type: **academic_base** 2.4 shows the stored
type in the field **Type** followed by **(not enabled on this
page)**, and saving keeps it. The warning of the changelog entry that saving
such a record rewrites its type describes the state before that fix. A content
element that an older version or a page TSconfig of your own already turned
into another type is not repaired. Correct it by hand from its record history.

### Adjust your own configuration {#upgrade-from-2-3-to-2-4-own-configuration}

-   The page TSconfig directory is `Configuration/TSconfig/` now, and its
    files were reorganised. Take the new path of every `@import`
    from the table of
    [Breaking: Site sets and static templates have been restructured](https://docs.typo3.org/permalink/fgtclb/academic-jobs:breaking-site-sets-and-static-templates-restructured@3.0), see also
    [Important: The page TSconfig directory is now spelled TSconfig](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-1787141400@3.0). An import of a missing file fails silently.
-   A site whose content element layout renders no header sets
    `plugin.tx_academicjobs.renderContentElementHeader = 1`, on
    TYPO3 13 also available as a site setting. The plugins no longer render the
    header themselves, see [Important: The job plugins leave the content element header to the layout](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-1790323400@3.0).
-   Label overrides move from `plugin.tx_academic_jobs._LOCAL_LANG`
    to `plugin.tx_academicjobs._LOCAL_LANG`, see
    [Important: Label overrides are read from the documented path](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-label-overrides-use-the-documented-path@3.0).
-   An empty
    `plugin.tx_academicjobs.jobAvatarImage.validation.mimeType.allowedMimeTypes`
    accepts every media type now. List the accepted types to keep restricting
    the logo, see [Important: An empty mime type list accepts every upload](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-ace-267-academic-jobs@3.0).
-   A site package that ships its own
    `Configuration/AcademicJobs/Settings.yaml` changes the keyword of
    `contactPhone` from `number` to `tel`, see
    [Important: The new job form stores the chosen values](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-new-job-form-stores-the-chosen-values@3.0).
-   The job detail page answers `404` without a job. Hide it in menus, a menu
    link carries no job. The label
    `tx_academicjobs.fe.alert.job_not_found.body` it showed before is
    removed, so an override of it has no effect any more. See
    [Important: The job detail answers "not found" without a job](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-job-detail-answers-not-found-without-a-job@3.0).
-   The job detail page sets the page title. A site whose own page title
    provider has to win orders it before `academicJobs`, see
    [Important: The job detail sets the page title](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-job-detail-sets-the-page-title@3.0).
-   A site that imports `Configuration/Routes/Detail.yaml` needs no
    change. A site that copied the route enhancer into its own configuration
    sets `defaultController: 'Job::show'` in the copy, the value the
    shipped file carries since 2.4. See [Route enhancers](https://docs.typo3.org/permalink/fgtclb/academic-jobs:configuration-route-enhancers@3.0).

## Adapt templates and assets {#upgrade-from-2-3-to-2-4-templates}

The editor script of the new job form moved:

| Old path | New path |
| --- | --- |
| `EXT:academic_jobs/Resources/Public/JavaScript/CKEditor.js` | `EXT:academic_jobs/Resources/Public/JavaScript/frontend/ckeditor.js` |

An override of `Templates/Job/New.html`, or a site package that loads the
script itself, takes over the new path. Otherwise the rich text fields fall
back to plain text areas. See [Breaking: The editor configuration moved](https://docs.typo3.org/permalink/fgtclb/academic-jobs:breaking-ckeditor-configuration-moved@3.0).

Version 2.4 changes these templates and partials. A copy of one of them in a
site package keeps rendering the copy, so compare each copy with the shipped
file and take over the changes. The paths below are relative to
`Resources/Private/`:

| File | What changed | Entry |
| --- | --- | --- |
| `Templates/Job/List.html`, `Templates/Job/Show.html`, `Templates/Job/New.html` | The header renders only with `settings.renderContentElementHeader`. | [Important: The job plugins leave the content element header to the layout](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-1790323400@3.0) |
| `Templates/Job/Show.html` | The contact box renders only for a job with contact data. | [Important: The job headings and the contact box are corrected](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-ace-316-academic-jobs@3.0) |
| `Templates/Job/New.html` | Loads the moved editor script. | [Breaking: The editor configuration moved](https://docs.typo3.org/permalink/fgtclb/academic-jobs:breaking-ckeditor-configuration-moved@3.0) |
| `Templates/Job/New.html` | Renders the confirmation for a visitor who returns to the form, with `<f:flashMessages queueIdentifier="academic_jobs.new_job_form.confirmation" />`. A copy without this line shows no confirmation. | [Important: The job form returns to its page with the confirmation](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-job-form-returns-to-its-page@3.0) |
| `Partials/Job/Item.html` | The heading level is corrected, the flags and the link row are new, and a hidden job is not linked. | [Important: The job headings and the contact box are corrected](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-ace-316-academic-jobs@3.0), [Important: Job views label flags and render the link](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-ace-596-academic-jobs@3.0), [Important: The job detail answers "not found" without a job](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-job-detail-answers-not-found-without-a-job@3.0) |
| `Partials/Job/Information.html` | The flags and the link row are new. | [Important: Job views label flags and render the link](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-ace-596-academic-jobs@3.0) |
| `Partials/Job/Contact.html` | The heading level is corrected, and the phone link is dialable. | [Important: The job headings and the contact box are corrected](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-ace-316-academic-jobs@3.0), [Important: The job contact phone link is dialable](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-job-contact-phone-link-is-dialable@3.0) |
| `Partials/Job/Properties/Job.html` | `richtext: 1` for TYPO3 12, and a **Please choose** option for the two selects. | [Important: The rich text fields now start on TYPO3 v12](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-new-job-form-rich-text-starts-on-typo3-v12@3.0), [Important: New job form offers an unchosen option](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-new-job-form-offers-an-unchosen-option@3.0) |
| `Partials/Job/Forms/*.html` | Rejected fields carry `is-invalid` and their message, rendered by the new partial `Partials/Job/Forms/ErrorMessage.html`. A stylesheet that styles `f3-form-error` styles `is-invalid` instead. | [Important: The new job form marks rejected fields](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-new-job-form-marks-rejected-fields@3.0) |

Every template and partial also passes the extension name
`AcademicJobs` to its translations now, see
[Important: Label overrides are read from the documented path](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-label-overrides-use-the-documented-path@3.0).

## Adapt your code {#upgrade-from-2-3-to-2-4-code}

-   A class that extends
    `\FGTCLB\AcademicJobs\Domain\Repository\JobRepository` and overrides
    `findByJobType()` adds the parameter
    `bool $includeHidden = false`. One that declares `findAllJobs()`
    or `findUidsWithHiddenDefaultRecord()` renames it. See
    [Breaking: Extended JobRepository method signatures](https://docs.typo3.org/permalink/fgtclb/academic-jobs:breaking-ace-250-academic-jobs@3.0).
-   A listener of `\FGTCLB\AcademicJobs\Event\AfterSaveJobEvent` that
    sets a redirect page of `0` or below now sends the visitor back to the
    form page, which shows the form and the confirmation, see
    [Important: A redirect page of 0 or below from a listener means none](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-redirect-page-zero-from-a-listener-means-none@3.0).
-   Code that reads the answer to a submitted job gets an empty `303` now,
    and a page that renders the messages of the form no longer gets the error
    message of Extbase after a rejected submission, see
    [Important: The job form returns to its page with the confirmation](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-job-form-returns-to-its-page@3.0).
-   A listener of
    `\FGTCLB\AcademicBase\Event\ModifyTcaSelectFieldItemsEvent` that
    changes the job types of the job record changes the option
    **Job Type** of the job list as well now. One meant for the record
    alone returns early when `flexParentDatabaseRow` is set, see
    [Important: Job list offers the job types of listeners](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-job-list-offers-the-job-types-of-listeners@3.0).
-   A listener of
    `\FGTCLB\AcademicJobs\Event\ModifyJobControllerNewActionViewEvent`
    that fills a date field from an assigned job gets the date as `Y-m-d`
    in the form now, see
    [Important: The new job form marks rejected fields](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-new-job-form-marks-rejected-fields@3.0).

## Check the result {#upgrade-from-2-3-to-2-4-check}

-   The content elements **Jobs New**, **Jobs List** and
    **Jobs Detail** are offered for new content on the pages that
    should have them, and existing ones keep their type.
-   Jobs that were hidden, scheduled or expired when the contact wizard first
    ran show their contact.
-   The jobs the repair wizard listed carry a chosen employment type and job
    type.
-   The header of the job content elements appears once.
-   A job submitted through a form without a redirect page returns the
    visitor to the form, which shows the confirmation.
-   On a site with more than one language, the redirect page of every form
    exists in every language of the form. A redirect page the form cannot
    link returns the visitor to the form and logs a warning, see
    [Important: The job form returns to its page when the redirect page cannot be linked](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-job-form-returns-when-redirect-page-cannot-be-linked@3.0).
-   A job submitted through the form reaches the editors. A notification mail
    that cannot be sent is logged now instead of failing the form, so check
    the log after a change of the mail configuration, see
    [Important: A notification mail that cannot be sent no longer fails the form](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-failing-job-mail-is-logged@3.0).
-   Jobs submitted before the update may share one logo file. The query in
    [Important: An uploaded job logo no longer replaces an existing file](https://docs.typo3.org/permalink/fgtclb/academic-jobs:important-uploaded-job-logo-keeps-existing-files@3.0) finds them.
