---
title: "Configuration"
manual: "Academic Partners"
version: "2.4"
permalink: "https://docs.typo3.org/permalink/fgtclb/academic-partners:configuration@2.4"
source: "Configuration/Index.rst"
rendered: "2026-10-26T16:44:11+00:00"
---

# Configuration {#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](https://docs.typo3.org/permalink/fgtclb/academic-partners:one-mechanism-per-site@2.4) for what happens otherwise.

## What the sets contain {#configuration-components}

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](https://docs.typo3.org/permalink/fgtclb/academic-partners:content-load-override@2.4). |
| `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 {#configuration-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](https://docs.typo3.org/permalink/fgtclb/academic-partners:breaking-site-sets-and-static-templates-restructured@2.4) before upgrading. An
> existing content element on a page that does not enable its component keeps
> its type: the backend shows the stored type followed by
> **(not enabled on this page)**, and saving keeps it. Content
> elements whose type an earlier save already replaced are not repaired, the
> record history shows their former type.

## What the sets do not control {#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`](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ExtensionArchitecture/FileStructure/Configuration/TCA/Index.html#file-extension-configuration-tca-overridessomefile-php)), the backend layout in the
always-included [`Configuration/page.tsconfig`](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ExtensionArchitecture/FileStructure/Configuration/PageTsconfig.html#file-extension-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 {#content-load-override}

[`Configuration/TypoScript/ContentLoad/setup.typoscript`](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ExtensionArchitecture/FileStructure/Configuration/TypoScript/Index.html#file-extension-configuration-typoscriptsetup-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 {#site-set}

> [!IMPORTANT]
> Site sets arrived in TYPO3 v13.1. On **TYPO3 v12 they do nothing at all** —
> the core has no set API, the folder `Configuration/Sets/` is never
> read, and a `dependencies` key in a site configuration is stored and
> ignored. On v12, use the static templates and the page TSconfig files
> described below; they deliver exactly the same files.

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

**config/sites/my-site/config.yaml (diff)**

```diff
 base: 'https://example.com/'
 rootPageId: 1
+dependencies:
+  - fgtclb/academic-partners
```

See also [TYPO3 Explained, Using a site set as dependency in a site](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ApiOverview/SiteHandling/SiteSets/Index.html#site-sets-usage).

## Include static templates {#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.

> [!TIP]
> On TYPO3 v13 we recommend the site set; on TYPO3 v12 this is the only
> mechanism there is. If you use the site set, 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 {#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. |
| **Academic Partners: Partners Map (academic_partners)** | The same for **Partners Map**. |
| **Academic Partners: Partnerships List (academic_partners)** | The same for **Partnerships List**. |
| **Academic Partners: Partnerships Teaser (academic_partners)** | The same for **Partnerships Teaser**. |
| **Academic Partners: Content load override (academic_partners)** | 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 {#static-pagetsconfig}

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: Partners Map (academic_partners)** | The same for **Partners Map**. |
| **Academic Partners: Partnerships List (academic_partners)** | The same for **Partnerships List**. |
| **Academic Partners: Partnerships Teaser (academic_partners)** | The same for **Partnerships Teaser**. |
| **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.

## The category filters {#configuration-list-filter}

The filter form of the **Partners List** and the **Partners
Map** offers one select per category type of the group `partners`. Three settings
change which of them it offers and how, for the whole site:

| Site setting and constant | Default | Meaning |
| --- | --- | --- |
| `plugin.tx_academicpartners.filter.categoryTypes` | empty | The category types to offer, in this order, as a comma separated list of type identifiers, for example `sdg,region`. Empty offers every type that has a category, in the order of the category types of the group. |
| `plugin.tx_academicpartners.filter.visibleCount` | 0 | How many filters the form shows right away. The others follow in a **More filters** section the visitor opens, which is open already while one of its filters has a value. 0 shows every filter. |
| `plugin.tx_academicpartners.filter.hideDisabledOptions` | 0 | Leaves out a category no listed partner carries, instead of offering it as a disabled option. A selected category is always offered. A filter whose categories are all left out still renders, with its "All" option only. |

**config/sites/my-site/settings.yaml**

```yaml
plugin:
  tx_academicpartners:
    filter:
      categoryTypes: 'sdg,region'
      visibleCount: 1
      hideDisabledOptions: true
```

The settings are site settings of the aggregate set `fgtclb/academic-partners`
and constants of the same names for a site on static templates. A site that
depends on `fgtclb/academic-partners-list` or `fgtclb/academic-partners-map`
alone gets the defaults, but the site settings editor does not offer the
settings there — both content elements read them, and a set declares settings
only for itself.

Site settings exist from TYPO3 v13 on. On TYPO3 v12, set the constants.

A type is offered only when at least one category of that type exists, and an
identifier that is no type of the group is ignored. The settings decide what
the form offers, not what the list accepts: a link that filters by a category
of a type the form does not offer still filters the list.

### The "All" option of a filter {#the-all-option-of-a-filter}

The first option of each filter, the one that selects no category, reads the
label `sys_category.partners.allOptions.<type>` of this extension, and
falls back to `sys_category.partners.allOptions` ("All options") where a
type has none. The extension ships no label per type; a site adds them in
TypoScript, for every content element of the extension or for one plugin:

**EXT:my_sitepackage/Configuration/TypoScript/setup.typoscript**

```typoscript
plugin.tx_academicpartners._LOCAL_LANG {
  default.sys_category.partners.allOptions.region = All regions
  de.sys_category.partners.allOptions.region = Alle Regionen
}

# Only in the partner map:
plugin.tx_academicpartners_map._LOCAL_LANG.default.sys_category.partners.allOptions.region = All regions
```

A language file override works as well, as for any label of this extension:
`$GLOBALS['TYPO3_CONF_VARS']['SYS']['locallangXMLOverride']`, pointing
from [`EXT:academic_partners/Resources/Private/Language/locallang.xlf`](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ExtensionArchitecture/FileStructure/Resources/Private/Language.html#file-extension-resources-private-language-locallang-xlf)
to a file of the site package.

### Templates {#templates}

The partial `Partner/DemandCategories.html` renders the selects from the
variable `{filterTypes}`: `{filterTypes.visible}` and
`{filterTypes.more}` hold the identifiers of the offered types, in their
order, before and behind **More filters**. Where that variable does not
reach the partial — a project controller that overrides `listAction()` or
`mapAction()`, or a template that renders the partial with arguments of its
own instead of `{_all}` — it offers every type with a category, as before,
and the filter types and the visible count have no effect there. To use them,
let the overriding action call the parent action, and pass `filterTypes`
on in a template that renders the partial.

<!-- TODO: no Markdown rendering for "versionadded" -->

Up to 2.3 the form offered every type with a category, all of them right
away and with one "All" label, and anything else needed an override of the
partial.

## Which partners the map draws {#configuration-map-show-on-map}

The **Partners Map** content element draws the partners its filter
matches that have coordinates and whose page has **Show on map**
switched on, the switch next to the coordinates of the partner page. The switch
is on for a new partner. It is about the map only: the partner list lists a
partner hidden from the map.

The map reads the switch of the partner page in the language it is rendered in.
The switch of a translation follows its default record, as the coordinates do,
so switching a partner off in the default language takes it off the map in every
language. An editor who detaches the switch of a translation sets it for that
language on its own.

A template that renders a map for one partner, such as a partner page showing
its own location, checks `\Domain\Model\Partner::isShownOnMap()`, which is
`{partner.shownOnMap}` in Fluid: the partner has coordinates to draw and
the switch is on.

## Content Security Policy {#configuration-content-security-policy}

The selects of the form of the **Partners List** and the
**Partners Map** submit it when the visitor changes one of them,
through the inline event handler `onchange="this.form.submit()"`. A nonce
does not cover an event handler attribute, so the frontend policy of TYPO3
blocks it once a site enforces that policy. The extension therefore allows
exactly this handler text in its
[`Configuration/ContentSecurityPolicies.php`](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ExtensionArchitecture/FileStructure/Configuration/ContentSecurityPolicies.html#file-extension-configuration-contentsecuritypolicies-php), which TYPO3 loads on its
own: the directive `script-src-attr` of the frontend policy gets
`'unsafe-hashes'` and `'sha256-osjxnKEPL/pQJbFk1dKsF7PYFmTyMWGmVSiL9inhxJY='`.
`script-src` is not changed. Every site that inherits the default frontend
policy gets both sources. A site whose `csp.yaml` sets
`inheritDefault: false`, and a site package whose copy of
`Partner/DemandSorting.html` or `Partner/DemandCategories.html`
uses another handler text, add the hash of that text in the `csp.yaml` of
the site:

**config/sites/\<site>/csp.yaml**

```yaml
mutations:
  - mode: extend
    directive: 'script-src-attr'
    sources:
      - "'unsafe-hashes'"
      - "'sha256-osjxnKEPL/pQJbFk1dKsF7PYFmTyMWGmVSiL9inhxJY='"
```

The hash is the base64 encoded SHA-256 of the handler text, without the quotes
of the attribute. A policy the web server or a proxy sends is not covered and
needs the same sources itself. This works the same on TYPO3 v12 and v13.

A site whose policy allows inline scripts already, with `'unsafe-inline'` in
`script-src`, or in `default-src` where it has no `script-src`, gets no
`script-src-attr` from the extension: a listener of **academic_base**
takes it out again, unless the site declares the directive itself. The browser
then reads `script-src` for the handlers of the form, as for the site's own
handlers. On a page whose `script-src` keeps a nonce, a browser ignores
`'unsafe-inline'` and blocks both. TYPO3 v12 never drops a nonce: a page that
uses one, and every page with uncached content such as the plugins of this
form, sends it.

For a visitor without JavaScript the form renders a submit button inside
`<noscript>`, labelled `filter.submit`. A visitor with JavaScript
does not see it.

<!-- TODO: no Markdown rendering for "versionchanged" -->

The policy allows the handler, and the form renders the button. See
Important: The filter form works under a security policy.

### The tiles of the map {#configuration-map-tiles-content-security-policy}

The **Partners Map** loads its tiles as images from OpenStreetMap,
`https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png`, a URL the map script
holds as a fixed value. The frontend policy of TYPO3 does not allow that host
in `img-src`, so a browser would block every tile once a site enforces the
policy, and the markers would stay on an empty map. The element therefore
extends `img-src` of the policy of its page by
`https://*.tile.openstreetmap.org`, and only a page with the map gets it. The
label `{s}` of the host becomes the wildcard, because a policy cannot name a
placeholder.

The source is added while TYPO3 renders the page and is kept with the page in
its cache, so it applies to a cached page as well. It applies on top of the
policy of the site, also on a site whose `csp.yaml` sets
`inheritDefault: false`. On TYPO3 v13 the content element registers it
through a data processor of its rendering definition, which extends the one of
`lib.contentElement`. A site there that renders the element without
the data processors of `lib.contentElement` gets the source only on
pages that come from the page cache, and adds it to its `csp.yaml` as
shown below. On TYPO3 v12 the map adds it on every request.

Not covered:

-   A page template that draws a map with the map script of the extension
    itself, outside the content element, adds the host of the tiles to the
    `csp.yaml` of the site:

    **config/sites/\<site>/csp.yaml**

    ```yaml
    mutations:
      - mode: extend
        directive: 'img-src'
        sources:
          - 'https://*.tile.openstreetmap.org'
    ```
-   A policy that the web server or a proxy sends needs the source itself.

The stylesheets, the scripts and the marker images of the map are files of the
extension. Leaflet positions its tiles and markers with styles it sets from
its script, which a policy does not restrict, so the map needs no other source.

<!-- TODO: no Markdown rendering for "versionchanged" -->

The map allows the host of its tiles in img-src. See
Important: The partner map allows its tiles under a security policy.

## Do not combine both {#one-mechanism-per-site}

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 and the settings of [the category filters](https://docs.typo3.org/permalink/fgtclb/academic-partners:configuration-list-filter@2.4).

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.

-   [Labels](https://docs.typo3.org/permalink/fgtclb/academic-partners:labels@2.4)
