TYPO3 extension for presenting partner institutions and cooperations of
universities with structured data and typified system categories, including
filterable list and map views in the frontend.
Learn about what has changed and which actions are required to
upgrade.
What does it do?
...
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-partners':'^2'
Copied!
Tip
We recommend to pin academic extensions on minor level to mitigate
possible issues in projects in case composer update is used based
on the fact that projects commonly tends to override fluid templates
and changes for otherwise non-breaking changes are possible promoted
to be breaking in case template changes are not adopted why it has
been considered to mark template changes as breaking changes on
minor version updates. That means, we suggest to use for example
following command to ensure that we stay in the minor version range
but have the hightest patchlevel enforced for it and keep possible
bugfix releases for that minor version possible to install:
Get the current version from TER by downloading the ZIP version.
Alternatively, get the ZIP from the GitHub Releases page.
Switch to the module Admin Tools > Extensions.
Enable Upload Extension.
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 four content elements, so it ships four component sets, one
set for the
styles.content
override described below, and one
aggregate set that depends on all of them.
All four content elements are driven by one Extbase plugin, so they share one
TypoScript block,
plugin.tx_academicpartners
. 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-partners-list
The Partners List content element.
fgtclb/academic-partners-map
The Partners Map content element.
fgtclb/academic-partners-partnerships-list
The Partnerships List content element.
fgtclb/academic-partners-partnerships-teaser
The Partnerships Teaser content element.
fgtclb/academic-partners-content-load
The
styles.content.getContent
override only. No content
element, and nothing this extension is otherwise made of — see
The content load override.
fgtclb/academic-partners
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 content element 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 content elements are hidden by default
EXT:academic_partners hides all four 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.
Warning
This changed in version 2.4. Before it, all four elements were selectable on
every page of every installation. Read
Breaking: Site sets and static templates have been restructured before upgrading:
opening an existing record on a page that does not include the page TSconfig
of its component can rewrite the type of that record.
What the sets do not control
The page type Academic partner (doktype 40) and its backend layout
AcademicPartner are not part of any set, and enabling or not
enabling a set never changes them.
That is deliberate, not an oversight. Both are values stored on
pages
records: a page carries doktype = 40 and backend_layout = pagets__AcademicPartner
long before any site configuration is read. Were they delivered by an opt-in
set, every page tree on a site that does not use that set would show
[ MISSING LABEL ] for the layout, the layout could not be picked for
a new page, and the page type would disappear from the page tree wizard.
They are therefore registered installation-wide — the page type in TCA
(Configuration/TCA/Overrides/pages.php), the backend layout in the
always-included Configuration/page.tsconfig — and stay available on every
site of the installation.
What a set does deliver for that page type is its frontend rendering: the
page
object that picks the Fluid template of the page type is part
of the shared TypoScript block, so a site that includes no set of this extension
renders such a page with whatever its own site package defines.
The content load override
Configuration/TypoScript/ContentLoad/setup.typoscript redefines
styles.content.getContent
for the whole site so that it selects
colPos = 0
only. This is an installation-wide rendering change, it
applies to every page of the site and not only to the pages of this extension,
and three academic extensions ship the same override.
It is therefore a set of its own, fgtclb/academic-partners-content-load. The
aggregate set depends on it, so a site on fgtclb/academic-partners keeps what
it had; a site that wants the content elements without the override names the
component sets it needs instead of the aggregate.
Warning
The Fluid template of the page type renders
styles.content.getContent
through
<f:cObject typoscriptObjectPath="styles.content.getContent"/>
, and
that ViewHelper throws when the path is undefined. A site that opts out of
this set and still uses the page type has to define
styles.content.getContent
itself.
Include the site set
Add the set to the config.yaml of the site that should offer the content
elements:
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.
Tip
On TYPO3 v13 and v14 we recommend the site set — and if you use it, do not
press the backend button Create a root TypoScript record on that
site. The
sys_template
record it creates carries the flag
Clear for constants and setup, and that flag discards everything
the site sets contributed. An installation that is already in that state
gets its configuration back by selecting the static templates below in that
very record.
Include static TypoScript
Edit the
sys_template
record of the site root and add the entry to
Include static (from extensions):
Entry
Delivers
Academic Partners: Partners List (academic_partners)
The TypoScript of the Partners List content element.
The
styles.content.getContent
override on its own.
Academic Partners: All components (academic_partners)
Every component this extension ships, in one entry.
Academic Partners: Shared plugin settings and page
rendering (academic_partners)
The shared
plugin.tx_academicpartners
block and the
page
object of the page type, on their 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, and
it no longer carries the content load override.
Include static page TSconfig
Edit the page record of the site root, tab Resources, field
Page TSconfig, and add the entry:
Entry
Delivers
Academic Partners: Partners List (academic_partners)
Makes the Partners List content element selectable, and
configures its entry in the new content element wizard.
Academic Partners: All components (academic_partners)
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
plugin.tx_academicpartners
constants block, the three Fluid
root paths.
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.
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.
ChangeLog v3
Every change to the Academic Partners extension is documented here.
Breaking: The map assets are built and loaded as a module
Description
The stylesheet and the script of the partner map are now compiled from sources
in the repository. Both moved into a frontend/ subdirectory, and the
script became an ES module:
The vendored Leaflet library, its marker cluster plugin and their stylesheets
are unchanged. They are third party files without sources here, they keep
their paths, and they are still loaded as classic scripts — the map module
reads the
LeafletObject
global they define.
Impact
An installation that uses the shipped Map.html template needs to do
nothing.
An installation that references either path keeps pointing at a file that no
longer exists.
Affected installations
Installations that override Templates/Partner/Map.html or reference
map.css or map.js from their own site package.
Migration
In an overridden template, replace the two references:
The three Leaflet lines around them stay exactly as they are.
Breaking: Record and category icons follow the colour scheme
Description
The record icons of this extension were registered with the core provider
\TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider
, which renders
the default markup - the markup a
typeicon_classes
entry reaches - as an
<img>
tag. An image is opaque to CSS, so the icon kept the ink of its
file whatever the backend colour scheme said, and a dark drawing stayed dark on
the dark cards of the record list.
They are now registered with
\FGTCLB\AcademicBase\Imaging\IconProvider\CurrentColorSvgIconProvider
,
which inlines the file in both markups, and the files themselves are drawn in
currentColor with no colour of their own.
That covers the three identifiers of this extension -
academic-partners
,
tx_academicpartners_domain_model_partnership
and
tx_academicpartners_domain_model_role
- and its four category type
icons, which
EXT:category_types
registers as
category_types.partners.*
. The four category types ask for it with
inlineIcon: true in Configuration/CategoryTypes.yaml; without that
flag a category type icon keeps the core provider.
Impact
The four category type icons reach the frontend, through
<core:icon identifier="category_types.partners.{type}" />
in
Pages/AcademicPartner.html, Partials/Partnerships/List/Item.html
and Partials/Partnerships/Teaser/Item.html, and through
category_types.partners.{category}
in Partials/Partner/Item.html.
None of those calls asks for the inline markup, so their rendered markup
changes: an
<img>
of a fixed pixel size becomes an inlined
<svg>
with
width="1em" height="1em"
, which follows the font size
and the colour of the text around it. Every site using the partner or
partnership plugins sees those icons resize and recolour.
Site CSS or JavaScript that sized, coloured or addressed the
<img>
has
to address the
<svg>
instead.
In the backend, the academic partner page type icon, the two record icons and
the four category type icons take the text colour around them, so they stay
legible in a dark backend colour scheme.
academic-partners
is also the
icon of the four content elements of this extension, so those follow with it -
the identifier is one icon, not two.
Affected Installations
Every installation of this extension. Installations that render the partner or
partnership plugins in the frontend are affected visibly.
Migration
Replace an image selector with an element selector in the site CSS, for example
/* before */.partner-attributes.iconimg { width: 32px; }
/* after */.partner-attributes.iconsvg { width: 1.25em; }
Copied!
The icon element keeps the surrounding
<span class="t3js-icon icon" data-identifier="…">
wrapper, so a
selector written against the wrapper needs no change.
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 or v14 -
beforehand or within the same upgrade step.
Breaking: Removed the unused autocomplete library
Description
The file Resources/Public/JavaScript/autocomplete.min.js has been
removed. It was a minified third party library that arrived with the initial
import of the extension and was never referenced — no template, no TypoScript,
no PHP and no other asset loaded it.
It was shipped in every release regardless, and a vendored, minified file
without a source is a maintenance and security liability for as long as it
exists.
Impact
Nothing in the extension changes. No plugin, template or partial loaded the
file, so no rendering, styling or behaviour is affected.
The file is no longer part of the package and a request for it returns 404.
Affected installations
Only installations that referenced the file from their own site package or
template overrides. That is possible, because the file was located below
Resources/Public/, but it was never part of the extension's public
API and no documentation ever mentioned it.
Migration
If a project loads the file from its own template, ship the library in the
project's own site package and reference it from there instead:
GeneralUtility::intExplode() takes a string, so a filter value that is a
list ended in a TypeError:
TypeError: GeneralUtility::intExplode(): Argument #2 ($string) must be of
type string, array given
Copied!
That is exactly what a filter select with multiple submits — the argument the
category filter select gained in the same release. A filterCollection that is
not an array at all did not raise, but emitted a PHP warning
foreach() argument must be of type array|object and silently dropped the
filter.
Both shapes are reachable from a crafted request without any template being
involved, because the controller action takes the demand as a plain
?array $demand = null and validates nothing.
The filter is read through
FGTCLB\CategoryTypes\Filter\CategoryFilterNormalizer now, which accepts a
single value, a list and a comma separated string, and treats anything it cannot
read as no filter.
Impact
A category filter select with multiple works.
A request with an unreadable filter renders the list unfiltered instead of
failing.
An unselected filter no longer contributes uid 0 to the query. The
prepended "all options" entry carries an empty value, and every unselected
category type added one 0 to the uid list. The rendered result is
unchanged — no category has uid 0 — but the list handed to
CategoryRepository::findByGroupAndUidList() is empty now, which it accepts
since the same release.
A uid submitted twice is used once.
Affected Installations
None have to act. Own code calling createDemandObject() with a hand built
demand array keeps working, and gains the list shape.
References
CategoryFilterNormalizer in
EXT:category_types — the class the filter is read with, and where its
behaviour is documented.
Important: The link column of pages is nullable now
Description
The extension adds a
link
column to the shared
pages
table.
It was declared as:
link 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 declaration
is harmless on every core version this release supports. On TYPO3 v12 it
was not: the column ended up
NOT NULL
with no default at all, and
creating a page in the backend failed with
Field 'link' doesn't have a default value
.
The column keeps its type and loses the default instead:
link text DEFAULT NULL,
Copied!
The change is carried here as well so that both maintained branches
declare the column identically.
Impact
Records written without naming the column now store
NULL
where
they previously stored an empty string. Existing rows are not changed, so
the column can hold both. Code that reads it 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 column, so no
data is converted and nothing can be lost.
Important: The page template name of the academic partner page type is set explicitly
Description
This extension registers a page type with a backend layout and ships the page
template for it in Resources/Private/Pages/. Its TypoScript adds that
directory to
page.10.templateRootPaths
, but it did not set
page.10.templateName
— the property that actually selects the
file.
A site package deriving the name from the backend layout therefore did not find
it.
bk2k/bootstrap-package
does exactly that:
templateName.cObject = TEXT
templateName.cObject {
data = pagelayout
case = uppercamelcase
split {
token = pagets__
cObjNum = 1
1.current = 1
}
}
Copied!
case = uppercamelcase
is
GeneralUtility::underscoredToUpperCamelCase()
, which lowercases the whole
string before it camel cases it on underscores. The registered backend layout
pagets__AcademicPartner
therefore resolved to Academicpartner.html, and
the frontend ended in an
InvalidTemplateResourceException
— in a
production context a page whose body reads Oops, an error occurred!.
The extension now sets the name itself, inside the page type condition it
already uses:
The clear is not decoration. Bootstrap package assigns
templateName.cObject
, and a cObject overwrites the plain value in
ContentObjectRenderer::stdWrapValue()
, so assigning without clearing
would change nothing.
Impact
A page of this type renders its template on a site package that derives the
name from the backend layout, where it previously did not render at all.
Nothing changes for a site package that sets the name itself, as long as it does
so after this extension's TypoScript, and nothing changes for a
PAGEVIEW
page object — that content object ignores
templateName
and resolves the file from
paths
, which
is why that integration worked before and is unaffected now.
Affected Installations
All installations of this extension that use a
FLUIDTEMPLATE
page
object. An installation that shipped Academicpartner.html in its own site
package to work around this loses that override: the template of this extension
is used instead. Clearing
page.10.templateName
after this
extension's TypoScript restores it.
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:
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: Partner map draws on a late module load
Description
The partner map did not draw on most page loads. The container stayed empty,
no tiles, no markers, and nothing was reported anywhere - not in the browser
console, not in the TYPO3 log.
Resources/Private/TypeScript/frontend/map.ts bound its whole body to
document.addEventListener('DOMContentLoaded', ...)
without asking whether
that event was still ahead of it.
f:asset.module
renders every module with
async
: the ViewHelper
accepts an identifier and nothing else, and
\TYPO3\CMS\Core\Page\JavaScriptRenderer
writes the attribute
unconditionally. An async module is not ordered against document parsing, so it
regularly runs after
DOMContentLoaded
has already fired. The listener was
then registered on an event that never comes again.
The module now runs its initialisation immediately when the document has
finished parsing, and waits only while it has not:
That is the shape the other frontend modules of this repository already use.
This was the only one missing it.
Impact
The map draws on every load. Nothing about its markup, its configuration or
its data changed, and an installation that saw the map draw before - the load
where the module happened to win the race - sees no difference.
Affected Installations
Every installation rendering the Partners Map plugin, or a template
that includes the map module.
Important: The map leaves out partners without coordinates
Description
Controller\PartnerController::mapAction()
fed the map from
Domain\Repository\PartnerRepository::findByDemand()
, which carries no
geocode constraint. A partner page that was never geocoded - or whose geocoding
failed - therefore reached the map template, and
\Domain\Model\Partner
types both coordinates as non-nullable
float
defaulting to 0:
So a missing coordinate arrived in the template as a perfectly valid one:
<liclass="map-partner"data-lat="0"data-lng="0" …>
Copied!
Resources/Private/TypeScript/frontend/map.ts guarded the values with
Number.isNaN()
, which 0 passes, and the marker was drawn at 0/0 - open
ocean south of Ghana. The guard could not catch an empty attribute either,
because
Number('')
is 0 and not NaN.
The map query now requires both coordinates, and the frontend module refuses to
draw a record whose coordinates it cannot use. A partner without coordinates
stays in the list, which is unchanged: it is still a perfectly good list
entry.
Absence is the criterion, not the value. NULL and the empty string mean "no
coordinate"; a stored 0 is a real one, and only the pair 0/0 is refused.
Longitude 0 runs through the United Kingdom, France, Spain and Ghana and
latitude 0 is the equator, so treating a single zero as missing would hide
partners that are genuinely there.
The two coordinate columns became
allowLanguageSynchronization
. A place
does not move when the page is translated, so a translation follows its default
record instead of carrying a coordinate of its own. A partner translated before
geocoding ran kept an empty coordinate and was therefore drawn at 0/0 in that
language - and, under the rule above, would have been left off that language's
map entirely.
Domain\Repository\PartnerRepository::findGeoLocated()
gained the same
requirement, so a record that claims a successful or manually status without
ever having received coordinates is no longer reported as located.
Impact
A partner that was previously drawn at 0/0 disappears from the map. That marker
never pointed at the partner's location, so nothing that pointed anywhere is
lost.
When no partner has coordinates at all, the plugin no longer renders an empty
map centred on Germany. It renders a message instead:
No partner with a location to show on the map.
Copied!
The label is map.noLocatedPartnersFound in
Resources/Private/Language/locallang.xlf and can be overridden like any
other label. Integrators who replaced
Resources/Private/Templates/Partner/Map.html keep their own copy and get
neither the condition nor the message.
A template that draws the map for one partner is not covered by any of this.
The typical case is a partner detail page that renders the partner's own
location: it has no query to constrain, and the list it hands to the map holds
that single partner whether it has coordinates or not. Such a template draws the
partner at 0/0, or - with the module above - an empty map centred on Germany.
Domain\Model\Partner::isDrawable()
is the same rule for a single object.
Guard the map with it:
Partner/Map stands for the site package's own map partial: this extension
ships the map only as the plugin template, not as a partial.
It is deliberately not called "geo located":
Domain\Repository\PartnerRepository::findGeoLocated()
also requires a
geocode status, and a record can claim to be located without carrying a
coordinate. Like the frontend module it also refuses a coordinate that is not a
finite number.
The model does not see exactly what the query sees, in either direction. An
absent coordinate has already become 0 by the time a template asks, so a pair
with only one coordinate missing reads as drawable at 0 on that axis while the
query excludes it; a hand-entered 0.0 is refused by the model while the query
lets it through. ACE-566 changes the column type and is where the two are
reconciled.
A custom controller that calls
Domain\Repository\PartnerRepository::findByDemand()
itself gets the old
behaviour unless it opts in, because the demand defaults to false:
$demand->setDrawableOnly(true);
Copied!
The server-side rule matches the pair 0/0 as a string, in the spelling
\Command\GeocodeCommand
writes. A hand-entered 0.0 therefore passes the
query and is dropped by the frontend module instead. A numeric comparison cannot
be expressed portably while the column is VARCHAR; ACE-566 changes the column
type and removes that asymmetry.
\Command\GeocodeCommand
writes its result through the DataHandler now
instead of the repository. Only a DataHandler write runs
\DataHandling\Localization\DataMapProcessor
, and geocoding is the one
path that actually writes coordinates - persisting through Extbase would reach
the default record and leave every translation behind, which is the defect one
level down.
Language synchronization takes effect when a record is saved, so it cannot
repair what is already stored. The upgrade wizard
academicPartners_synchronizePartnerCoordinates
copies each partner's
coordinates onto its translations once. Run it after updating; a site with
translated partner pages needs it, and a site without translations does not.
Deleted translations and workspace versions are left alone, and so is a
coordinate an editor detached from its default record on purpose.
A workspace draft created before the update keeps its own stale coordinate:
the wizard does not touch drafts, so publishing such a draft after the update
re-introduces the empty value for that record. Re-saving it in the workspace is
enough to bring it back in line.
Affected Installations
Every installation rendering the Partners Map plugin whose partner
records are not all geocoded, and every installation with translated partner
pages. Installations where every partner has coordinates see no change.
Installations whose own templates draw a map for a single partner - most often
a partner detail page - need to add the
isDrawable()
guard shown above;
this extension's own page template renders no map.
Important: The partner page type renders its categories
Description
A page of the partner page type can carry categories of the category types
this extension registers, and its page template has always contained a block
that lists them, grouped by category type. That block never appeared.
It read the categories as
{partner.categories.allCategoriesByType}
,
and the model behind
{partner}
has no such property — it exposes the
collection as
getAttributes()
. Fluid resolves an unknown path to
null
without raising anything, so the surrounding
<f:if>
was
false on every partner page and the whole list was skipped. The list and
teaser partials of this extension already read the working path.
A partner page with at least one category assigned now shows its category
types and the categories of each, in the markup the template already
contained — for example Region followed by
Rhine-Main Area.
A category type without an assigned category produces no entry, and a partner
page without categories renders exactly as before.
Affected Installations
All installations that render partner pages with the page template shipped by
this extension and assign categories to them.
An installation that overrides
Resources/Private/Pages/AcademicPartner.html is not affected. A copy
that was taken only to repair this defect can be dropped, as long as it
carries no other change.
Important: Partner queries are ordered deterministically
Description
Every query of this extension executed without an ordering, so the order of its
result was whatever the database happened to yield. On PostgreSQL that is not
the same list twice: the partnership teaser rendered a different partner on two
renders of the same data. The queries now order explicitly:
PartnershipRepository::findByPid()
— the source of every partnership
list and teaser — orders by the manual backend
sorting
(TCA ctrl
sortby
), with
uid
settling ties.
PartnerRepository::findAll()
and
findGeoLocated()
order by
the backend
sorting
of the page records, with
uid
settling
ties — partner records are pages, so among siblings this is the order the
editor arranged in the page tree; partners spread over several parent
pages interleave deterministically by that same value.
PartnerRepository::findNextForGeolocation()
processes the geocoding
queue oldest record first (
uid
ascending) instead of letting the
database pick.
PartnerRepository::findByDemand()
appends
uid
as a tiebreaker
to the ordering the plugin demands, so records equal in that ordering — two
partners with the same title, for example — keep a stable relative order.
Impact
Partnership lists and teasers now render in the order the records have in the
backend. An installation whose editors reordered partnership records will see
the frontend follow that order — which is the order the editor expressed, but
was never delivered before. Everything else keeps its practical order: the
backend page sorting and
uid
ascending are what every supported
database returned in practice, they are simply guaranteed now rather than
coincidental.
Affected Installations
Every installation of this extension.
Important: The sorting select shares the option rendering
Description
ViewHelpers\Form\SortingSelectViewHelper::renderOptionTags() was removed. It
was identical to the method it inherits from
FGTCLB\CategoryTypes\ViewHelpers\Form\AbstractSelectViewHelper, down to the
last character - the class only ever needed its own getOptions().
That base class writes every option through a single method now, which escapes
the option value. It used to concatenate the value unchanged while escaping the
label.
Impact
The rendered markup is unchanged. The options of this select carry the values of
Enumeration\SortingOptions - title, asc, desc and their siblings - and
none of them needs escaping.
An own subclass overriding renderOptionTags() keeps working, and one calling
parent::renderOptionTags() reaches the inherited implementation.
References
AbstractSelectViewHelper in
EXT:category_types - the class writing the option markup, and where the
change is documented.
Important: The static template and the backend layout are registered correctly
Description
Two registrations of this extension did not reach an installation.
The static template was registered under the wrong extension key.Configuration/TCA/Overrides/sys_template.php passed
'academic_programs'
to
ExtensionManagementUtility::addStaticFile()
, so the entry offered in a
template record as Academic Partners Page Setup pointed at
EXT:academic_programs/Configuration/TypoScript/ — the TypoScript of a
different extension. The TypoScript of this extension was registered nowhere and
could only be reached through the site set
fgtclb/academic-partners
.
What that costs an installation without site sets: the page template directory
of this extension never enters
page.10.templateRootPaths
, and the
PartnershipProcessor
data processor is never registered, so partnerships
are not resolved on any page. An installation that has this extension without
fgtclb/academic-programs
included nothing at all, silently —
SysTemplateTreeBuilder
skips an include whose extension is not loaded.
The backend layout was imported by the site set only.Configuration/page.tsconfig is auto-included for the whole installation
since TYPO3 v12.0 (Feature: #96614); a site set is opt-in per site. The backend
layout of the page type this extension registers, and the descriptions of its
content elements, were imported only by
Configuration/Sets/AcademicPartners/page.tsconfig. On a site that does
not enable that set the layout
pagets__AcademicPartner
resolved
nowhere: the page properties showed [ MISSING LABEL ] for it and it
could not be selected for a new page at all.
Both imports moved to Configuration/page.tsconfig, where
fgtclb/academic-programs
already had them, and the copy in the site
set was removed rather than left to be applied twice. The empty
Configuration/TsConfig/page.tsconfig, which nothing imports any more,
was removed with it.
The missing label of the layout's content column was added to
Resources/Private/Language/locallang_be.xlf in the same change.
Impact
The static template Academic Partners Page Setup now includes the TypoScript
of this extension. The backend layout and the content element descriptions are
available on every installation, whether or not it uses site sets.
Affected Installations
All installations of this extension.
The static template fix is not self-healing. A template record that selected
the entry before stores
EXT:academic_programs/Configuration/TypoScript/
, which is still a
valid registration of the other extension, so the record keeps working and
keeps including the wrong tree. The now correct entry has to be added to the
record by hand. No upgrade wizard ships for it: the stored value is genuinely
ambiguous — it cannot be told apart from an intentional selection of
Academic Programs Page Setup — and rewriting it would break an installation
that meant the latter.
Nothing has to be done for the backend layout. Pages already carrying
pagets__AcademicPartner
resolve it from now on.
3.x Changes by type
This lists all changes to the Academic Partners extension of minor versions
grouped by their type.
Breaking: Site sets and static templates have been restructured
Description
The TypoScript and the page TSconfig of this extension were shipped twice: the
static template read Configuration/TypoScript/, and the site set
fgtclb/academic-partners
shipped its own constants.typoscript
and setup.typoscript, each of them a single
@import
of
that folder. The page TSconfig existed only as the wizard file
Configuration/TSconfig/Wizards/NewContentElement.tsconfig and was not
selectable on a page at all.
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/ keeps the shared
plugin.tx_academicpartners
block and the
page
object of the page type. All four content elements are driven by the one
plugin, so that block is shipped once and every component folder names it in
a one-line include_static_file.txt.
Configuration/TypoScript/List/,
Configuration/TypoScript/Map/,
Configuration/TypoScript/PartnershipsList/ and
Configuration/TypoScript/PartnershipsTeaser/ are the four component
folders — what the static template registers and what the matching set
points its
typoscript
key at.
Configuration/TSconfig/<Component>/page.tsconfig holds the page
TSconfig of a component and is what the page field Page TSconfig
offers and what the set points its
pagets
key at.
Configuration/TypoScript/Full/ and
Configuration/TSconfig/Full/page.tsconfig are the aggregates for
installations that do not use site sets.
The content elements are now hidden by default. The always-included
Configuration/page.tsconfig removes all four content element types from
the selectable ones, and the page TSconfig of a component adds its own back — so
an element is offered where it is wanted instead of on every page of 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.
The
styles.content.getContent
override that
Configuration/TypoScript/setup.typoscript used to import unconditionally
is a component of its own now,
Configuration/TypoScript/ContentLoad/setup.typoscript. It redefines a
global TypoScript object path for every page of a site, so it must be possible
to take the content elements without it.
The page type Academic partner (doktype 40) and its backend layout
AcademicPartner are unchanged and stay installation-wide. They are
values stored on
pages
records and are not, and must not be, part of any
opt-in set.
Impact
A
sys_template
record that selected the static template of this extension
keeps its stored value and keeps working: the registered folder is unchanged,
only its label is. What it no longer delivers is the
styles.content.getContent
override, which moved into a component
of its own.
A site package that imported one of the moved 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 four content elements are no longer offered in the backend until the page
TSconfig of their component is included, through the site set or through the
page field Page TSconfig.
Warning
Do not open an existing record of one of these content elements in the
backend form on a page that does not include that page TSconfig. An item
removed through
TCEFORM.tt_content.CType.removeItems
is
excluded from the [ invalid value ] fallback TYPO3 otherwise
adds for a stored value it does not know, and the stored value is dropped
from the form data as well. The field Type therefore comes up
with nothing selected, and saving the record writes whatever the browser
preselected into
CType
— the record silently becomes another
content element. The frontend keeps rendering it correctly until that
happens.
Include the page TSconfig of the component on every page tree that holds
such records, and do it before editing them.
Warning
The Fluid template of the page type renders
styles.content.getContent
through
<f:cObject typoscriptObjectPath="styles.content.getContent"/>
, and
that ViewHelper throws when the path is undefined. A site that deliberately
opts out of fgtclb/academic-partners-content-load and still uses the page
type has to define
styles.content.getContent
itself.
The set
fgtclb/academic-partners
keeps its name and keeps delivering
everything, so a site configuration that depends on it needs no change.
Affected Installations
Installations that import one of the shipped files from an own site package,
that use one of the content elements of this extension without including its
page TSconfig, or that relied on the
styles.content.getContent
override arriving with the plugin configuration.
The entry in the
sys_template
record keeps its value and changes its
label:
Old entry
New entry
Academic Partners Page Setup (academic_partners),
stored as EXT:academic_partners/Configuration/TypoScript/
Academic Partners: Shared plugin settings and page
rendering (academic_partners), same stored value — or
Academic Partners: All components (academic_partners),
stored as EXT:academic_partners/Configuration/TypoScript/Full,
which also carries the content load override.
Add the page TSconfig entry, which did not exist before, in the page record of
the site root, tab Resources, field Page TSconfig:
Academic Partners: All components (academic_partners), stored as
EXT:academic_partners/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.
A site configuration may name the new component sets instead of the aggregate:
Set
Delivers
fgtclb/academic-partners
Unchanged in name, now delivers through the component sets below.
fgtclb/academic-partners-list
The Partners List content element only.
fgtclb/academic-partners-map
The Partners Map content element only.
fgtclb/academic-partners-partnerships-list
The Partnerships List content element only.
fgtclb/academic-partners-partnerships-teaser
The Partnerships Teaser content element only.
fgtclb/academic-partners-content-load
The
styles.content.getContent
override only. The
aggregate depends on it; name the component sets above without it to
opt out.
Feature: The partner select is sorted by label
Description
The partner select of a partnership record now offers the partners ordered
by their title, ascending, using the collation of the language the backend
is displayed in.
Until now the select declared no order and offered the partners in the
order the query behind it returned, which on this version line is the page
tree order of the partner pages. In an installation with more than a
handful of partners the entry to pick was found by scanning rather than by
reading.
The order is declared on the field itself, so TYPO3 applies it with the
collator of the backend language: a title starting with a diacritic is
ordered by its base letter, and Öresund Academy is offered between
Oberlin Institute and Potsdam College rather than after
Zeta University.
The empty placeholder entry stays at the top of the list.
Impact
Editors of partnership records see the same partners in a different, and
findable, order. Nothing changes about which partners are offered, about
what a save stores, or about how any list renders in the frontend. No
migration and no manual step is required.
An editor who relied on the page tree order of the partner pages inside
this select no longer gets it. That order was never an intended order of
the select, it was the order of the query behind it.
Affected Installations
All installations using the EXT:academic_partners extension starting with
version 2.4. No action is required for existing installations.
Feature: "Show hidden records" plugin option for the partner lists
Description
A new boolean plugin option Show hidden records
(
settings.showHiddenRecords
, checkbox/toggle, default off)
was added to the following plugins:
List (
academicpartners_list
)
Map (
academicpartners_map
)
Both plugins share the single ListSettings.xml flexform data
structure, which gains the new toggle.
When the option is enabled, the frontend partner 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 plugins.
Impact
Editors can now opt in per plugin instance to display hidden partners in
the frontend, for example to preview 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_partners extension starting
with version 2.4. No action is required for existing installations.
Important: Extended PartnerDemand and demand handling
Description
To support the new "Show hidden records" plugin option, the partner
demand pipeline gained a new transport flag:
\FGTCLB\AcademicPartners\Domain\Model\Dto\PartnerDemand
has a new
bool $showHiddenRecords
property with
setShowHiddenRecords(bool): void
and
getShowHiddenRecords(): bool
accessors (default
false
).
\FGTCLB\AcademicPartners\Factory\DemandFactory::createDemandObject()
now reads
$settings['showHiddenRecords']
and sets the flag on the
demand object.
\FGTCLB\AcademicPartners\Domain\Repository\PartnerRepository::findByDemand()
honours the flag: when it is
true
, the query ignores only the
disabled (hidden) enable field via the Extbase query settings.
The public method signatures of
DemandFactory::createDemandObject()
and
PartnerRepository::findByDemand()
are unchanged.
Impact
The change is non-breaking: the new flag defaults to
false
and no
existing method signature changed. Projects that build a
PartnerDemand
themselves can opt in by calling
setShowHiddenRecords(true)
.
Affected Installations
Only installations that extend or replace the
PartnerDemand
DTO,
the
DemandFactory
or the
PartnerRepository
need to take the
added flag into account. All other installations are unaffected.
Important: The page type is registered from a boot listener
Description
TYPO3 v13 has no
allowedRecordTypes
TCA option and resolves the tables
allowed on a page type through
PageDoktypeRegistry
. This extension
registered its page type 40 there, from
Configuration/TCA/Overrides/pages.php.
That is too early. The first call to
PageDoktypeRegistry->add()
collects
every table declaring
security.ignorePageTypeRestriction
- tt_content,
sys_template and backend_layout - from the
TcaSchemaFactory
and
latches the result for the rest of the request. A TCA override file runs while
the TCA is still being assembled, before
TcaSchemaFactory::load()
, so that
factory is still empty and none of the three ever reaches the allow list of the
default page type.
TYPO3 then refuses content elements on ordinary pages:
Attempt to insert record on pages:1 where table "tt_content" is not allowed
Copied!
This happens while the TCA cache is cold, which is every import run after a cache
flush and the first backend request after one. Once the TCA cache is warm the
override files are not executed at all - and then the page type of this extension
is not registered either, and silently falls back to the allow list of the
default page type instead of allowing every record type.
The registration moved to an event listener on
\TYPO3\CMS\Core\Core\Event\BootCompletedEvent
,
\FGTCLB\AcademicPartners\EventListener\RegisterAcademicPageDoktype
. That event
is dispatched one line after
TcaSchemaFactory::load()
and on every request,
warm cache included, which is what both halves of the defect need. The listener
does nothing on TYPO3 v14, where the TCA option carries the configuration and
PageDoktypeRegistry->add()
is deprecated.
Impact
Content elements can be created on standard pages again while the TCA cache is
cold, and the page type 40 of this extension allows every record type
while it is warm.
Affected Installations
All installations of this extension on TYPO3 v13. TYPO3 v14 is not affected, it
resolves the allowed tables from TCA. Nothing has to be done beyond the usual
cache flush after an update.
Category type based handling has been streamlined and centralized within the EXT:category_types extension
and the known implementation based on deprecated TYPO3 Enumeration has been replaced with a modern PHP API
provided by the EXT:category_type extension.
Extension specific category types are now grouped and are now defined by newly introduced yaml file format,
following a concrete convention to look and auto-register these files.
EXT:academic_partners now ships a default set of partner related category types, which can be found
in ./Configuration/CategoryTypes.yaml
EXT:academic_partners related category types can be extended by any other TYPO3 extension providing a
Configuration/CategoryTypes.yaml file containing category-types using the group-identifier partners.
Configuration/CategoryTypes.yaml format uses following syntax: