Academic Jobs 

Extension key

academic_jobs

Package name

fgtclb/academic-jobs

Version

main

Language

en

Author

FGTCLB

License

This document is published under the Creative Commons BY 4.0 license.

Rendered

Tue, 25 Aug 2026 09:56:50 +0000


This TYPO3 extension allows the entry of external job offers by front-end users in TYPO3 using a form. The job offers can then be checked and published through an approval process.

Records can be created, edited and displayed in the frontend, with both a list and a detail view available.


Introduction 

What the extension does and the main concepts behind it.

Installation 

Install academic_jobs via Composer, the Extension Manager or a TER upload.

Configuration 

Configure the extension and its plugins for your installation.

Templates 

Override and customise the frontend templates.

Known problems 

Known issues and information about them.

Changelog 

Learn about what has changed and which actions are required to upgrade.

What does it do? 

This TYPO3 extension allows the entry of external job offers by front-end users in TYPO3 using a form. The job offers can then be checked and published through an approval process.

Records can be created, edit and displayed in the frontend and there are a list- and a detail view for the frontend.

Jobs can be created using TYPO3 backend accounts and also using the Form in the Frontend. In this case you need to configure a page where the plugin is inserted and a page where the jobs are created.

Lists, tables, tile and detailed views are available for displaying the job offers. The following data is available for job advertisements:

  • Job type: Job, Part-time job, Thesis
  • Job title
  • Type of job offer
  • Job description - Rich text editor
  • Start date
  • Location
  • link
  • Image / Logo
  • Organization
  • Sector
  • Required degree
  • Contractual relationship
  • Alumni recommended
  • Internationals welcome
  • Publication date
  • Expiration date
  • Contact details
    • Your name
    • e-mail address
    • Phone number
    • Additional information
    • Link / Slug

Installation 

The extension has to be installed like any other TYPO3 CMS extension. You can download and install it using one of the following methods.

Install the stable release
composer require 'fgtclb/academic-jobs':'^2'
Copied!
  1. Switch to the module Admin Tools > Extensions.
  2. Switch to Get Extensions.
  3. Search for the extension key academic_jobs.
  4. Import the extension from the repository.
  1. Get the current version from TER by downloading the ZIP version. Alternatively, get the ZIP from the GitHub Releases page.
  2. Switch to the module Admin Tools > Extensions.
  3. Enable Upload Extension.
  4. Select or drag the extension ZIP archive and upload the file.

Configuration 

This extension ships its frontend TypoScript and its backend page TSconfig in two forms: as TYPO3 site sets, and as classic static templates plus page TSconfig files that are selected on a page. Both forms read the very same files, so they configure an installation identically.

Pick one of them per site and stay with it — see Do not combine both for what happens otherwise.

What the sets contain 

This extension ships three content elements, so it ships three component sets and one aggregate set that depends on all of them.

All three are driven by one Extbase plugin, so they share one TypoScript block, plugin.tx_academicjobs . That block is shipped once, in Configuration/TypoScript/, and every component includes it. Which component sets a site names therefore decides which content elements the backend offers, not how much TypoScript is loaded.

Set Delivers
fgtclb/academic-jobs-new-job-form The Jobs New content element, the frontend form a job offer is entered with.
fgtclb/academic-jobs-list The Jobs List content element.
fgtclb/academic-jobs-detail The Jobs Detail content element.
fgtclb/academic-jobs Everything above. This is the set to use unless you deliberately want a subset, and it is the name this extension published before the sets were cut per component — a site configuration that depends on it needs no change.

Every component set depends on fgtclb/academic-base-ctype-group, the set of EXT:academic_base that labels the content element group all academic extensions sort their elements into.

The site settings of this extension — the storage, detail, list and redirect pages, the notification e-mail and the job avatar upload — are declared with the aggregate set. A site that depends on a single component set still gets the shipped defaults, but can only override them in Site Settings when it depends on fgtclb/academic-jobs.

The content elements are hidden by default 

EXT:academic_jobs hides all three of its content elements for the whole installation and brings them back per component. Whichever of the two mechanisms below you use, it is what makes an element selectable in the backend again — without one of them the content element is not offered, and existing records keep rendering.

Include the site set 

Add the set to the config.yaml of the site that should offer the content elements:

config/sites/my-site/config.yaml (diff)
 base: 'https://example.com/'
 rootPageId: 1
+dependencies:
+  - fgtclb/academic-jobs
Copied!

See also TYPO3 Explained, Using a site set as dependency in a site.

Include static templates 

For an installation that still configures its frontend through sys_template records, the same files are registered as static templates and as selectable page TSconfig files.

Include static TypoScript 

Edit the sys_template record of the site root and add the entry to Include static (from extensions):

Entry Delivers
Academic Jobs: Jobs New (academic_jobs) The TypoScript of the Jobs New content element.
Academic Jobs: Jobs List (academic_jobs) The TypoScript of the Jobs List content element.
Academic Jobs: Jobs Detail (academic_jobs) The TypoScript of the Jobs Detail content element.
Academic Jobs: All components (academic_jobs) Every component this extension ships, in one entry.
Academic Jobs: Shared plugin settings (academic_jobs) The shared plugin.tx_academicjobs block on its own. This is the entry an installation stored before the configuration was cut per component, and it keeps working — but it does not make any content element selectable, which the page TSconfig below does.

Include static page TSconfig 

Edit the page record of the site root, tab Resources, field Page TSconfig, and add the entry:

Entry Delivers
Academic Jobs: Jobs New (academic_jobs) Makes the Jobs New content element selectable, and configures its entry in the new content element wizard.
Academic Jobs: Jobs List (academic_jobs) The same for Jobs List.
Academic Jobs: Jobs Detail (academic_jobs) The same for Jobs Detail.
Academic Jobs: All components (academic_jobs) Every component this extension ships, in one entry.

The setting is inherited by every page below the one it is set on.

Do not combine both 

A site that uses the site set and the static template reads the shipped files twice. The site set is applied before the sys_template record, so the second read happens after the site settings and after config/sites/<site>/constants.typoscript — and it resets every constant the extension ships a default for back to that default. For this extension that is the whole plugin.tx_academicjobs constants block: the Fluid root paths, the storage and target page ids, the notification e-mail and the job avatar upload settings.

Nothing else is damaged: the Constants and Setup fields of the sys_template record, the page TSconfig of a page and the page TSconfig files selected on a page are all applied afterwards and still win. Use one mechanism per site and the question does not arise.

General configuration 

...

Validation settings 

Configuration/AcademicJobs/Settings.yaml describes which fields of a job record are required, and how they are rendered in the public new job form.

The file 

The shipped configuration defines a single set, job . Its keys are property names in camel case, each carrying a list of flags:

validations:
  job:
    title:
      - required
    link:
      - url
    contactEmail:
      - email
    contactPhone:
      - number
Copied!

A property that is not listed is neither required nor specially rendered.

Where the settings take effect 

The configuration is read in three independent places, and — this is the important part — they do not all understand the same keywords:

Keyword New job form Server side validation Backend (TCA)
required Marks the field with an asterisk Value must not be empty Not applied
email Renders <input type="email"> Value must be an email address Not applied
url Renders <input type="url"> Value must be a URL Not applied
number Renders <input type="number"> No validation Not applied

Server side validation runs when a job is created through the frontend form. It does not run for records edited in the TYPO3 backend.

Current limitations 

Further points to be aware of:

  • Keywords are case sensitive. Required or EMAIL are silently ignored. Always write them in lower case.
  • Any unknown keyword becomes an HTML input type in the new job form, as described in the warning above. A typo therefore produces an invalid input type rather than being ignored.
  • number marks the field as numeric in the form but adds no server side validation, so a non-numeric value submitted by other means is accepted.
  • required cannot detect an unselected value for the job type and employment type fields, because those are stored as numbers and an unset selection is indistinguishable from a valid zero.
  • The configuration is not applied to the TYPO3 backend. Required fields in the backend record editor are configured separately in the extension's TCA, and the two may differ.

Overriding the settings 

Settings are collected from all installed extensions. Every package that contains Configuration/AcademicJobs/Settings.yaml contributes, and the package loaded last wins.

To change them for an installation:

  1. Add Configuration/AcademicJobs/Settings.yaml to your site package.
  2. Make the site package depend on academic_jobs in its composer.json or ext_emconf.php, so that it is loaded after it.
  3. Repeat the complete validations block, see the warning below.
  4. Flush the TYPO3 caches — the parsed settings are cached, and a changed file has no effect until the cache is cleared.

There is no TypoScript and no site set equivalent for these settings.

Route enhancers 

This extension ships one ready made route enhancer in Configuration/Routes/Detail.yaml. TYPO3 does not read that file on its own — it is a fragment that has to be imported from the configuration of the site which shows the plugin.

What the file enhances 

The file declares a single enhancer of type Extbase named AcademicJobsDetailPlugin , bound to the plugin Detail of the extension AcademicJobs . That pair determines the argument namespace the enhancer works on — tx_academicjobs_detail .

It registers one route for the show action of \FGTCLB\AcademicJobs\Controller\JobController :

EXT:academic_jobs/Configuration/Routes/Detail.yaml
routes:
  - routePath: '/{job_title}'
    _controller: 'Job::show'
    _arguments:
      job_title: 'job'
Copied!

The path segment is resolved by a PersistedAliasMapper on tx_academicjobs_domain_model_job over the field slug , so the speaking part of the URL is the slug of the job record rather than its uid.

No enhancer is shipped for the other two plugins, and none is needed: the List plugin has neither pagination nor a filter, so its action takes no arguments at all, and the NewJobForm plugin submits its form by POST.

Importing it into a site configuration 

Add the resource to the imports of the site that contains the page with the job detail plugin:

config/sites/my_site/config.yaml
imports:
  - resource: 'EXT:academic_jobs/Configuration/Routes/Detail.yaml'
Copied!

Limiting the enhancer to its page 

TYPO3 offers every enhancer declared in a site configuration to every page of that site unless the enhancer says otherwise, and it takes the first candidate route whose path matches and whose aspects resolve. Distinct enhancer keys keep the entries apart in the YAML — they are not what keeps their routes apart while a URL is resolved.

The route of this extension is /{job_title} . Its path variable comes from an aspect and carries no requirements entry of its own, which makes it compile to .+ — a pattern that crosses slashes. What keeps it from answering a URL meant for another extension is only that its PersistedAliasMapper rejects a segment which is not a job slug, so the candidate is skipped and the next one is tried. That is a thin guarantee: a slug value that exists in both tables makes the two routes compete, and the enhancer imported first wins.

limitToPages settles it by naming the pages the enhancer applies to:

config/sites/my_site/config.yaml
imports:
  - resource: 'EXT:academic_jobs/Configuration/Routes/Detail.yaml'

routeEnhancers:
  AcademicJobsDetailPlugin:
    limitToPages: [17]
Copied!

The uid is the one of the page carrying the detail plugin, and it is the uid of the default language: matching derives the page as l10n_parent ?: uid , so a single entry covers every translation of that page. Plain page uids work on every TYPO3 version this extension supports.

In academic_persons the same mechanism is not a precaution but a requirement — that extension ships three enhancers whose routes overlap each other by construction. See its route enhancer documentation.

What the URLs look like 

Assuming the detail plugin sits on a page with the slug /jobs/detail, a link from the list to a job is built without the enhancer as:

/jobs/detail?tx_academicjobs_detail%5Bjob%5D=17
Copied!

and with the enhancer imported as:

/jobs/detail/research-assistant-biology
Copied!

Caveats 

  • The route needs a slug. PersistedAliasMapper resolves the path segment against the slug field of the job record, so a job whose slug is empty cannot be reached through the enhanced URL. A record saved in the backend gets one from the TCA slug field; a record created by the frontend form of the NewJobForm plugin does not go through the DataHandler at all and gets one from the event listener \FGTCLB\AcademicJobs\EventListener\GenerateJobSlug instead. Records that predate the slug field have to be updated once, for example by emptying the field in the backend form so it is generated again.
  • Jobs entered through the frontend form are created hidden, so they only become reachable — enhanced URL or not — once they were approved in the backend.
  • The list plugin renders its links with the detail plugin name and the page from the plugin setting detailPid . Enhancing the detail page therefore changes the links of an unmodified list template without any further configuration.

Overriding templates 

EXT:academic_jobs is using Fluid as template engine.

This documentation won't bring you all information about Fluid but only the most important things you need for using it. You can get more information in the section Fluid templates of the Sitepackage tutorial. A complete reference of Fluid ViewHelpers provided by TYPO3 can be found in the ViewHelper Reference

Change the templates using TypoScript constants 

As any Extbase based extension, you can find the templates in the directory Resources/Private/.

If you want to change a template, copy the desired files to the directory where you store the templates.

We suggest that you use a sitepackage extension. Learn how to Create a sitepackage extension.

# TypoScript constants
plugin.tx_academicjobs {
    view {
        templateRootPath = EXT:mysitepackage/Resources/Private/Extensions/myextension/Templates/
        partialRootPath = EXT:mysitepackage/Resources/Private/Extensions/myextension/Partials/
        layoutRootPath = EXT:mysitepackage/Resources/Private/Extensions/myextension/Layouts/
    }
}
Copied!

Known problems 

Please note that this extension is still in development. Changes to existing code may appear in upcoming versions.

If you run into a bug or a feature that would be helpful, please use the issue tracker.

3.0 Changes 

Table of contents

Breaking Changes 

Features 

Deprecation 

Important 

Breaking: The editor configuration is an ES module 

Description 

The script configuring the CKEditor instances of the frontend form is now compiled from a TypeScript source and is an ES module:

EXT:academic_jobs/Resources/Public/JavaScript/CKEditor.js
->  EXT:academic_jobs/Resources/Public/JavaScript/frontend/rich-text.js
Copied!

It is registered in Configuration/JavaScriptModules.php and addressed by the bare specifier @fgtclb/academic-jobs/frontend/rich-text.js.

The name avoids ckeditor.js on purpose. CKEditor 4 derives its own installation directory from the first script tag of the document whose source ends in that name, and an import mapped module is rendered before the plain script assets of a page — so a module of that name would send the editor looking for its skin and its language files below this extension (ACE-469).

CKEditor itself is still loaded from a content delivery network by the same template, unchanged.

Impact 

An installation that uses the shipped template needs to do nothing.

An installation that references the old path loads a file that no longer exists, and the rich text fields fall back to plain textareas.

Affected installations 

Installations that override Templates/Job/New.html or reference CKEditor.js from their own site package.

Migration 

In an overridden template, replace the reference:

<f:asset.module identifier="@fgtclb/academic-jobs/frontend/rich-text.js" />
Copied!

<f:asset.script> cannot be used any more, because a classic script tag does not execute an ES module. The frontend-editor identifier and the async / defer attributes are gone with it: a module is deferred by definition.

Breaking: Extbase plugins require CType on TYPO3 v14 

Description 

TYPO3 v14 removed the tt_content sub-type feature (the list_type column) and changed ExtensionManagementUtility::addPlugin() accordingly. The academic plugins have been registered as first-class content elements (CType) since the 2.1 version line (see the 2.1 breaking note about migrating from list_type to CType); for TYPO3 v14 support the internal registration was adapted to the new addPlugin() signature and the vestigial list_type handling was dropped.

Impact 

On TYPO3 v14 the tt_content.list_type column no longer exists. Any content records still stored as CType=list with a list_type of one of the plugins below will no longer resolve, and custom TypoScript, TSconfig, page TSconfig or SQL that references list_type for these plugins stops working.

The change relates to the following plugins:

  • academicjobs_newjobform
  • academicjobs_list
  • academicjobs_detail

Affected Installations 

Installations that upgrade to TYPO3 v14 and still hold content elements stored as CType=list + list_type=<plugin>, or that reference list_type for these plugins in their own configuration.

Migration 

Run the provided upgrade wizard academicJobs_pluginContent before upgrading to TYPO3 v14 (it requires the list_type column, which v14 removes) to migrate the tt_content records to the dedicated CType values. Update any custom configuration referencing list_type to match on CType instead.

Breaking: Removed TYPO3 v12 support 

Description 

Support for TYPO3 v12 has been removed for the 3.x version line, based on the dual TYPO3 core version support per major version of the academic extensions support matrix.

This includes removing build, test and configuration parts only required for TYPO3 v12. Version specific code paths are dropped in a dedicated step.

Impact 

TYPO3 v12 or older instances can no longer install or update to the 3.x version of the academic extensions and are required to upgrade TYPO3 first.

The extension cannot be installed on TYPO3 v12 anymore but does not break otherwise.

Affected installations 

All installations using an academic extension on TYPO3 v12 that want to upgrade to the 3.x version line.

Migration 

Upgrade the TYPO3 installation to a supported version (TYPO3 v13) beforehand or within the same upgrade step.

Important: Four job columns are nullable now 

Description 

Four columns of tx_academicjobs_domain_model_job were declared as TEXT with a default value:

company_name text NOT NULL DEFAULT '',
sector text NOT NULL DEFAULT '',
required_degree text NOT NULL DEFAULT '',
contractual_relationship text NOT NULL DEFAULT '',
Copied!

MySQL cannot store a default value on a TEXT column. TYPO3 works around that from v13 on, by expressing the default in the DEFAULT ('') syntax MySQL 8.0.13 introduced — so the declarations are harmless on every core version this release supports. On TYPO3 v12 they were not: the columns ended up NOT NULL with no default at all, and every statement that did not name them was rejected with Field 'company_name' doesn't have a default value . Imports and data sets were the reachable case; the frontend form persists a full record, and the backend fills the columns from their default in TCA.

The columns keep their type and lose the default instead:

company_name text DEFAULT NULL,
sector text DEFAULT NULL,
required_degree text DEFAULT NULL,
contractual_relationship text DEFAULT NULL,
Copied!

The change is carried here as well so that both maintained branches declare the columns identically.

Impact 

Records written without naming a column now store NULL where they previously stored an empty string. Existing rows are not changed, so a column can hold both. The domain model is unaffected — Extbase casts NULL to an empty string for its string properties — but code reading the columns directly should compare with empty() rather than with '' .

Affected Installations 

All installations of this extension. The database schema has to be updated, either in the maintenance area of the install tool or with typo3 extension:setup . The change only relaxes the columns, so no data is converted and nothing can be lost.

Important: Job image upload uses native Extbase upload handling 

Description 

The job avatar image upload of the academicjobs_newjobform plugin was handled by the custom type converter FGTCLB\AcademicBase\Extbase\Property\TypeConverter\FileUploadConverter (EXT:academic_base). It has been replaced with the native Extbase file upload handling introduced in TYPO3 v13.3 (FileUploadConfiguration, see TYPO3 feature forge#103511).

The TypoScript configuration is unchanged. settings.jobAvatarImage.uploadFolder, settings.jobAvatarImage.validation.fileSize.maximum and settings.jobAvatarImage.validation.mimeType.allowedMimeTypes keep their names and meaning and are now mapped onto the core FileSizeValidator and MimeTypeValidator. The form template, the Job domain model and the plugin itself are untouched, so no integration or template change is required.

Impact 

The upload behaves differently in three ways:

  • Stored file names change. The custom converter stored the file under the name supplied by the client and replaced an existing file of the same name. The native handling appends a random suffix and renames on conflict instead, so two visitors uploading logo.png no longer overwrite each other in the shared upload folder.
  • The mime type is detected from the file content. The custom converter trusted the media type sent by the browser, which can be spoofed. The core MimeTypeValidator inspects the uploaded file itself and additionally cross-checks the file extension. An upload whose real content does not match an allowed mime type is now rejected, even if the browser announced an allowed one. Uploads that only passed because of a faked header stop working — this is intended.
  • The file is only stored once the whole form validates. Previously the file was imported into FAL while mapping the request, so a job that failed validation afterwards left an unreferenced file behind in the upload folder. The file is now imported after successful validation, which avoids those orphaned files but requires the visitor to select the file again when the form is redisplayed with validation errors.

An empty allowedMimeTypes setting continues to mean "no mime type restriction".

Affected Installations 

Installations using the job creation form (academicjobs_newjobform) with image uploads. Installations that rely on the uploaded file keeping its original name — for example when referencing those files by a fixed path outside of FAL — need to review that assumption.

Migration 

No configuration change is required. Files uploaded before this change keep their existing names and references.

Important: The page TSconfig directory is now spelled TSconfig 

Description 

The extensions of this set spelled their page TSconfig directory in three different ways — TsConfig, TSconfig and TSConfig. They now all use TSconfig, which is how TYPO3 spells the term and what the core documentation uses.

In this extension the directory was Configuration/TSConfig.

Nothing was broken before, because every import matched the directory it pointed at. The reason to change it is that a filesystem is case sensitive on Linux and case insensitive on macOS and Windows, so a path copied between two of these extensions resolved on one machine and silently not on another — and a page TSconfig @import that does not resolve raises no error, the configuration is simply absent.

Impact 

Every file this extension ships moved with the directory. The imports inside the extension were updated in the same change, so an installation that only installs the extension has nothing to do.

An integrator who references these paths from their own configuration has to update them, because the old path no longer exists. The files below the directory were reorganised in the same release, so the new path is not the old one with the spelling corrected — take it from the table in Breaking: Site sets and static templates have been restructured:

Page TSconfig of your own site package
# before
@import 'EXT:academic_jobs/Configuration/TSConfig/page.tsconfig'
# after
@import 'EXT:academic_jobs/Configuration/TSconfig/Full/page.tsconfig'

# before
@import 'EXT:academic_jobs/Configuration/TSConfig/Plugins/*.tsconfig'
# after
@import 'EXT:academic_jobs/Configuration/TSconfig/Full/page.tsconfig'
Copied!

Affected Installations 

Every installation that imports a page TSconfig file of this extension by path, or that copied such a path into its own site package. An installation that relies only on the auto-included Configuration/page.tsconfig of the extension, or on its site set, is unaffected.

Important: Plugins assign a record view variable 

Description 

TYPO3 v14 rewrote the header partial of EXT:fluid_styled_content. Where v13 Header/All.html reads {data.header}, the v14 Header/All.fluid.html renders header and subheader with {record -> f:render.text(...)}, and that ViewHelper requires a record object.

Content elements based on lib.contentElement receive that record from the record-transformation data processor, but an Extbase plugin view assigns only the data array. Templates of this extension render the shared header partial, so on TYPO3 v14 they aborted with

The record argument must be an instance of ... Given: null
Copied!

The plugin controllers now assign an additional record view variable, built from the tt_content row of the current content element. TYPO3 v13 ignores it, its header partial keeps reading data, so one implementation serves both core versions.

Impact 

The affected plugins render again on TYPO3 v14. Nothing was removed or renamed, so no configuration or template override needs to be adapted.

Custom templates and template overrides may use the new {record} variable, for example with <f:render.text record="{record}" field="header" />.

Affected Installations 

Installations running the plugins of this extension on TYPO3 v14. TYPO3 v13 installations are unaffected.

Migration 

None required.

ChangeLog v2 

Every change to the Academic Jobs extension is documented here.

Also available 

Breaking: Site sets and static templates have been restructured 

Description 

The TypoScript of this extension was shipped twice: the static template read Configuration/TypoScript/, and the site set fgtclb/academic-jobs shipped its own constants.typoscript and setup.typoscript, each of them a single @import of that folder. The page TSconfig was not selectable on a page at all — it existed only as the three wizard files under Configuration/TSconfig/Plugins/, glob imported into the always-included Configuration/page.tsconfig.

Both mechanisms now read one physical copy of every file, and both of them deliver the extension per component instead of as one block:

  • Configuration/TypoScript/NewJobForm/, Configuration/TypoScript/List/ and Configuration/TypoScript/Detail/ are what the static templates register and what the sets point their typoscript key at.
  • Configuration/TSconfig/NewJobForm/page.tsconfig, Configuration/TSconfig/List/page.tsconfig and Configuration/TSconfig/Detail/page.tsconfig hold the page TSconfig of a component and are what the page field Page TSconfig offers and what the sets point their pagets key at.
  • Configuration/TypoScript/Full/ and Configuration/TSconfig/Full/page.tsconfig are the aggregates for installations that do not use site sets.

All three content elements are driven by one Extbase plugin and share one plugin.tx_academicjobs block. That block did not move: it stays in Configuration/TypoScript/, which is the value every sys_template record that selected the static template of this extension already stores. Each component folder is a subfolder of it and names it in a one-line include_static_file.txt, so the block exists once and is delivered by both mechanisms alike.

The content elements are now hidden by default. The always-included Configuration/page.tsconfig removes academicjobs_newjobform , academicjobs_list and academicjobs_detail from the selectable content element types, and the page TSconfig of a component adds its own element back — so an element is offered where it is wanted instead of on every page of every installation. The wizard entry of an element moved into the same file, so it arrives with the component instead of with every installation. The TCA registration itself did not move, so the frontend renders existing records exactly as before. Editing such a record in the backend is a different matter — read the warning below before upgrading.

Four constants changed their shipped default from empty to 0 : plugin.tx_academicjobs.persistence.storagePid , plugin.tx_academicjobs.detailPid , plugin.tx_academicjobs.listPid and plugin.tx_academicjobs.saveForm.fallbackRedirectPageId . The site settings of this extension always declared them as 0 , and a site that uses both delivery mechanisms had the declared default reset to empty by the second read. Every consumer of the four reads an empty value and a 0 as "no page selected", so the change is a reconciliation, not a behaviour change.

Impact 

A sys_template record that selected the static template of this extension keeps its stored value, and that value keeps delivering the shared plugin configuration — but it delivers nothing else, and it never made a content element selectable.

A site package that imported one of the shipped page TSconfig files by path fails to resolve it. @import of a missing file is silent, so this shows up as missing configuration rather than as an error message.

The three content elements are no longer offered in the backend until the page TSconfig of the component is included, through the site set or through the page field Page TSconfig.

The set fgtclb/academic-jobs keeps its name and keeps delivering everything, so a site configuration that depends on it needs no change.

Affected Installations 

Installations that use one of the content elements of this extension without including its page TSconfig, and installations that import one of the shipped page TSconfig files from an own site package.

Migration 

The static template entry does not have to be replaced — but selecting one of the new entries instead documents what a site actually uses:

Old entry New entry
Academic Jobs (academic_jobs), stored as EXT:academic_jobs/Configuration/TypoScript Academic Jobs: All components (academic_jobs), stored as EXT:academic_jobs/Configuration/TypoScript/Full — or one of Academic Jobs: Jobs New, Academic Jobs: Jobs List, Academic Jobs: Jobs Detail. The old value stays registered as Academic Jobs: Shared plugin settings (academic_jobs) and keeps delivering the shared plugin block.

Add the page TSconfig entry, which did not exist before, in the page record of the site root, tab Resources, field Page TSconfig: Academic Jobs: All components (academic_jobs), stored as EXT:academic_jobs/Configuration/TSconfig/Full/page.tsconfig. Without it the content elements are not selectable any more, and existing records of them lose their CType when they are saved from the backend form.

Sites that use the site set instead need no migration — but they must not use both mechanisms at once, see the Configuration chapter.

Adjust every @import in an own site package:

Old path New path
EXT:academic_jobs/Configuration/TypoScript/constants.typoscript unchanged
EXT:academic_jobs/Configuration/TypoScript/setup.typoscript unchanged
EXT:academic_jobs/Configuration/TSconfig/page.tsconfig EXT:academic_jobs/Configuration/TSconfig/Full/page.tsconfig
EXT:academic_jobs/Configuration/TSconfig/Plugins/NewJobsForm.tsconfig EXT:academic_jobs/Configuration/TSconfig/NewJobForm/page.tsconfig
EXT:academic_jobs/Configuration/TSconfig/Plugins/List.tsconfig EXT:academic_jobs/Configuration/TSconfig/List/page.tsconfig
EXT:academic_jobs/Configuration/TSconfig/Plugins/Detail.tsconfig EXT:academic_jobs/Configuration/TSconfig/Detail/page.tsconfig

A site configuration may name the new component sets instead of the aggregate:

Set Delivers
fgtclb/academic-jobs Unchanged in name, now delivers through the component sets below.
fgtclb/academic-jobs-new-job-form The Jobs New content element only.
fgtclb/academic-jobs-list The Jobs List content element only.
fgtclb/academic-jobs-detail The Jobs Detail content element only.

Feature: "Show hidden records" plugin option for the jobs list 

Description 

A new boolean plugin option Show hidden records ( settings.showHiddenRecords , checkbox/toggle, default off) was added to the following plugin:

  • Jobs List ( academicjobs_list )

When the option is enabled, the frontend job listing includes hidden (disabled) records, independent of the Context API visibility settings. Only the hidden enable column (disabled) is ignored; the deleted, starttime/endtime and fe_group restrictions stay in effect.

The option is core-version-aware and available in both the TYPO3 v12 and v13 flexform data structures of the plugin.

Impact 

Editors can now opt in per plugin instance to display hidden jobs in the frontend, for example to preview upcoming or intentionally hidden records without changing the global preview settings. The option is off by default, so existing plugin instances keep their current behaviour.

Affected Installations 

All installations using the EXT:academic_jobs extension starting with version 2.4. No action is required for existing installations.

Important: Extended JobRepository method signatures 

Description 

To support the new "Show hidden records" plugin option, the \FGTCLB\AcademicJobs\Domain\Repository\JobRepository gained an extended and a new method:

  • findByJobType(int $jobType, bool $includeHidden = false): QueryResultInterface — the new optional $includeHidden parameter was appended.
  • findAllJobs(bool $includeHidden = false): QueryResultInterface — new method used on the no-filter listing path in place of the inherited findAll() , so the option can be honoured there as well.

When $includeHidden is true , the query ignores only the disabled (hidden) enable field via the Extbase query settings.

Impact 

The change is non-breaking: the new parameter has a default value and the additional method does not alter existing signatures. Projects that extend or replace JobRepository should adopt the same signatures when overriding these methods.

Affected Installations 

Only installations that extend or override \FGTCLB\AcademicJobs\Domain\Repository\JobRepository need to take the extended signatures into account. All other installations are unaffected.

Important: The job table records its translation source 

Description 

tx_academicjobs_domain_model_job declared a languageField and a transOrigPointerField , and no translationSource . It was the only table of the academic extensions without one.

The two answer different questions. l10n_parent says which record a translation belongs to; l10n_source says which record it was written from. They hold the same value when a translation was made from the default language and different ones when it was made from another translation, and without the second key that information is not recorded at all.

The ctrl section of the table now carries:

'translationSource' => 'l10n_source',
Copied!

Impact 

TYPO3 adds an l10n_source column to the table on the next database comparison, as int unsigned NOT NULL DEFAULT 0 with an index. The column is derived from the TCA by DefaultTcaSchema , so there is nothing to add to ext_tables.sql.

The backend gains the "source language" half of the localization state selector for job records, and a translation made from another translation is recorded as such.

Affected Installations 

All installations of this extension.

No migration is needed, and none is offered. Existing rows get the column default 0 :

  • On a default language record that is the correct value, permanently - such a record has no source.
  • On a translation that predates this change it means "not recorded". Every reader in the TYPO3 core guards for that with a > 0 check, so nothing fails: the backend simply does not offer the source language comparison for those particular records, and still offers the default language one.

Translations created from now on record their source. A record whose value matters can be re-translated, or the column set by hand; neither is required for the extension to work.

Breaking: Migrated extbase plugins from list_type to CType 

Description 

TYPO3 v13 deprecated the tt_content sub-type feature, only used for CType=list sub-typing also known as list_type and mostly used based on old times for extbase based plugins. It has been possible since the very beginning to register Extbase Plugins directly as CType instead of CType=list sub-type, which has now done.

Technically this is a breaking change, and instances upgrading from 1.x version of the plugin needs to update corresponding tt_content records in the database and eventually adopt addition, adjustments or overrides requiring to use the correct CType.

Impact 

The change relates to following plugins:

  • academicjobs_newjobform
  • academicjobs_list
  • academicjobs_detail

Affected Installations 

All installations using the above listed plugins prior V2.1.

Migration 

A TYPO3 UpgradeWizard academicJobs_pluginUpgradeWizard is provided to migrate plugins from CType=list to dedicated CTypes matching the new registration.

Breaking: Removed ImageUploadConverter 

Description 

Custom ImageUploadConverter implementation is removed in favour of the shared EXT:academic_base/Classes/Extbase/Property/TypeConverter/FileUploadConterter. The dropped implementation is considerable an internal implementation, but was never flagged internal and is therefore mentioned as breaking and added to the semver breaking exemption.

Impact 

The change relates usages of the ImageUploadConverter implementation.

Affected Installations 

All installations using the ImageUploadConverter.

Migration 

Use the shared \FGTCLB\AcademicBase\Extbase\Property\TypeConverter\FileUploadConverter provided by EXT:academic_base.

Breaking: Removed tx_academicjobs_domain_model_contact 

Description 

As the relation between database tables tx_academicjobs_domain_model_job and tx_academicjobs_domain_model_contact is 1:1 and there is no reuse of contact records, it does not make sense to have a separate table and record for these contacts. Therefore the relation was resolved and an upgrade wizard handles the migration to the new fields in the tx_academicjobs_domain_model_job .

Impact 

The change relates all records of type tx_academicjobs_domain_model_contact .

Affected Installations 

All installations using the database table tx_academicjobs_domain_model_contact .

Migration 

A TYPO3 UpgradeWizard academicJobs_contactRelation is provided to migrate contact records from relation to fields directly in the job record.

Feature: Dispatch ModifyTcaSelectFieldItemsEvent in TypeItems and EmploymentTypeItems 

Description 

Following provided itemsProcFunc handlers now dispatches the new PSR-14 FGTCLBAcademicBaseEventModifyTcaSelectFieldItemsEvent:

  • \FGTCLB\AcademicJobs\Backend\FormEngine\EmploymentTypeItems
  • \FGTCLB\AcademicJobs\Backend\FormEngine\TypeItems

Impact 

This allows projects to modify the available select items for the backend (FormEngine) and also for the frontend using a PSR-14 event listener:

EXT:my_ext/Classes/EventListener/ModifyJobTypeItemsListener.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExt\EventListener;

use FGTCLB\AcademicBase\Event\ModifyTcaSelectFieldItemsEvent;
use FGTCLB\AcademicJobs\Domain\Model\JobType;

final class ModifyJobTypeItemsListener
{
    public function __invoke(ModifyTcaSelectFieldItemsEvent $event): void
    {
        if ($event->getFieldName() === 'type') {
            $items = $event->getItems();
            $items[] = [
                'Custom Type',
                JobType::CUSTOM_TYPE,
            ];
            $event->setItems($items);
        }
    }
}
Copied!

Feature: Introduce ModifyJobControllerNewActionViewEvent in JobController::newAction() 

Description 

JobController::newAction() dispatches now the newly introduced PSR-14 event FGTCLBAcademicJobsEventModifyJobControllerNewActionViewEvent providing following methods:

  • function getPluginControllerActionContext(): PluginControllerActionAcontext to extbase controller action plugin context data, which can be used to make decisions using the event.
  • function getView(): FluidViewInterface|CoreViewInterface to retrieve the view instance, which can be used to assign additional data, but disallowing to replace the instance.

Impact 

Implementing a event listener for this event allows attaching additional variables to the view for the JobController::newAction(), for example to provide additional select field options in case fields are changed, from text to a select field for example and avoid the need to implement a custom ViewHelper to retrieve the "select options" within the modified views.

Example event listener 

EXT:my_ext/Classes/EventListener/ModifyJobControllerNewActionViewListener.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExt\EventListener;

use FGTCLB\AcademicJobs\Event\ModifyJobControllerNewActionViewEvent;
use TYPO3\CMS\Fluid\View\FluidViewInterface;

final class ModifyJobControllerNewActionViewListener
{
    public function __invoke(ModifyJobControllerNewActionViewEvent $event): void
    {
        $view = $event->getView();
        if ($view instanceof FluidViewInterface) {
            // Assign additional variable to the view
            $view->assign('myCustomVariable', 'My Custom Value');
        }
    }
}
Copied!

Sitemap