SiteKit Registry — Anleitung für Integratoren und Extension-Entwickler

Überblick

Die SiteKit Registry ist ein zentraler Mechanismus, der automatisch steuert, welche Content-Elemente (CTypes) in welchen Bereichen des TYPO3-Backends platziert werden dürfen.

Ohne SiteKit Registry müssten erlaubte CTypes an mehreren Stellen manuell gepflegt werden:

  • In den allowed-Listen der BackendLayout-page.tsconfig-Dateien
  • In den TCA-Container-Konfigurationen (PHP-Dateien)

Mit SiteKit Registry reicht es, pro Extension eine YAML-Datei zu pflegen. Alle Platzierungsregeln werden automatisch daraus abgeleitet.


Prinzip

Jede Extension deklariert in einer YAML-Datei, welchen Gruppen ihre CTypes angehören. Die Registry (SiteKitRegistry.php) liest beim ersten Zugriff alle aktiven Packages durch und aggregiert diese Deklarationen. Das Ergebnis wird für einen PHP-Request gecacht.

Es gibt zwei Deklarationswege:

DateiFür
Configuration/SiteKit.yamlKlassische Extensions, dritte Packages, Overrides
ContentBlocks/{Category}/{Name}/SiteKit.yamlContentBlocks (portabel, alles in einem Ordner)
Extension A: Configuration/SiteKit.yaml          ─┐
Extension B: ContentBlocks/*/SiteKit.yaml         ─┤─→ SiteKitRegistry ─→ Erlaubte CTypes
Sitepackage: ContentBlocks/*/SiteKit.yaml         ─┘       (gecacht)        je Bereich
             Configuration/SiteKit.yaml (overrides)

Zwei Verwendungsstellen greifen auf die Registry zu:

  1. BackendLayouts (page.tsconfig): Über den Marker __SITEKIT:gruppe__, der zur Laufzeit durch einen EventListener aufgelöst wird.
  2. b13/container TCA: Direkt per PHP-Aufruf SiteKitRegistry::getCTypesForGroups([...]).

Gruppen-Konventionen

GruppeVerwendung
group_heroHero-Bereich (colPos 3) — typischerweise nur großformatige Elemente
group_content_wideHauptspalte voller Breite — Standard-Inhaltselemente
group_content_smallSchmale Spalten in Mehrspaltern (≤ col-6)
group_cardsNur in Card-Group- und Card-Grid-Containern
group_advancedNur im BackendLayout "Advanced" — Wrapper-Container

Ein CType kann in mehreren Gruppen gleichzeitig registriert sein.


Weg 1: Configuration/SiteKit.yaml (klassische Extensions)

Die Datei liegt unter Configuration/SiteKit.yaml im Root einer Extension.

elements:
    -   ctype: mein_celement
        groups: [ group_content_wide, group_content_small ]
        grid: { minCols: 4, requiresFullWidth: false }

    -   ctype: mein_hero_element
        groups: [ group_hero ]
        grid: { minCols: 12, requiresFullWidth: true }

Felder

FeldPflichtBeschreibung
ctypejaDer CType-Identifier (exakt wie in der Datenbank)
groupsjaListe der Gruppen (YAML-Array)
grid.minColsneinMinimale Bootstrap-Spaltenanzahl (1–12) — nur dokumentarisch
grid.requiresFullWidthneintrue bei voller Containerbreite — nur dokumentarisch

Hinweis:grid-Felder werden aktuell nicht ausgewertet. Sie dienen als Dokumentation und können in zukünftigen Versionen genutzt werden.


Weg 2: ContentBlock-eigene SiteKit.yaml

ContentBlocks können ihre eigene SiteKit.yaml **direkt im ContentBlock-Ordner ** ablegen. Das ist der empfohlene Weg für ContentBlocks, da alles in einem Ordner bleibt und der ContentBlock dadurch zwischen Projekten portierbar wird.

ContentBlocks/
  ContentElements/
    MeinElement/
      config.yaml          ← ContentBlock-Konfiguration (name: vendor/mein-element)
      EditorInterface.yaml
      templates/
      SiteKit.yaml         ← SiteKit-Deklaration (kein ctype nötig!)

Das Format ist vereinfacht — ctype entfällt, da er aus config.yaml abgeleitet wird:

# ContentBlocks/ContentElements/MeinElement/SiteKit.yaml
groups: [ group_content_wide, group_content_small ]
grid: { minCols: 4, requiresFullWidth: false }

CType-Ableitung aus dem ContentBlock-Namen

Der CType wird aus dem name-Feld in config.yaml abgeleitet:

config.yaml nameCType
oliver-thiele/price-cardoliverthiele_pricecard
oliver-thiele/alertoliverthiele_alert
myprojekt/teasermyprojekt_teaser

Regel: Bindestriche entfernen, Schrägstrich durch Unterstrich ersetzen, alles Kleinbuchstaben.

Vorteil: Portabilität

Da die SiteKit.yaml im ContentBlock-Ordner liegt, kann der gesamte Ordner in ein anderes SiteKit-Projekt kopiert werden und die Platzierungsregeln funktionieren sofort — ohne manuelle Konfiguration in einer zentralen Datei.


Overrides — Gruppen-Zuweisungen überschreiben

In der package-level Configuration/SiteKit.yaml (typischerweise im Sitepackage) können Gruppen-Zuweisungen aus beliebigen Extensions überschrieben werden.

Anwendungsfälle:

  • Eine Extension registriert einen CType in group_hero, aber in diesem Projekt soll etwas anderes in den Hero-Bereich.
  • Ein CType soll in diesem Projekt zusätzlich in einem weiteren Container erlaubt sein.
# packages/ot-sitepackage/Configuration/SiteKit.yaml
elements:
    # Dritte Extensions ohne eigene SiteKit.yaml hier eintragen:
    -   ctype: tx_news_pi1
        groups: [ group_content_wide ]
        grid: { minCols: 6, requiresFullWidth: false }

overrides:
    # ot_heroimage aus dem Hero-Bereich entfernen (eigenes Hero-Element wird verwendet):
    -   ctype: ot_heroimage
        removeFromGroups: [ group_hero ]

    # ot_ceheader zusätzlich in Cards erlauben, aus Hero entfernen:
    -   ctype: ot_ceheader
        addToGroups: [ group_cards ]
        removeFromGroups: [ group_hero ]

Override-Felder

FeldBeschreibung
ctypeDer CType, der überschrieben werden soll
removeFromGroupsListe der Gruppen, aus denen der CType entfernt wird
addToGroupsListe der Gruppen, zu denen der CType hinzugefügt wird

Wildcard * bei removeFromGroups

Um einen CType aus allen Gruppen zu entfernen, ohne jede Gruppe einzeln aufzulisten, kann '*' als Wildcard verwendet werden:

overrides:
  - ctype: textmedia
    removeFromGroups: ['*']

Hinweis: Die Anführungszeichen sind zwingend erforderlich, da * in YAML ein reserviertes Zeichen für Anker-Referenzen ist und ohne Quotes einen Parse-Fehler verursacht.

Das ist nützlich, wenn ein CType (z. B. ein Standard-TYPO3-Element) im Projekt komplett deaktiviert werden soll.

Overrides werden nach allen elements- und ContentBlock-Deklarationen verarbeitet (Zwei-Pass-Verfahren), sodass sie immer gewinnen — unabhängig davon, welches Package zuerst geladen wird.


Technischer Ablauf

TYPO3 Bootstrap
│
├─ TCA-Phase (früh)
│    └─ Configuration/TCA/Container/*.php wird eingelesen
│         └─ GeneralUtility::makeInstance(SiteKitRegistry::class)
│              │
│              ├─ Pass 1: Für jedes aktive Package:
│              │    ├─ liest Configuration/SiteKit.yaml (elements + overrides sammeln)
│              │    └─ scannt ContentBlocks/**/SiteKit.yaml (rekursiv)
│              │         └─ liest config.yaml → leitet CType ab
│              │
│              ├─ Pass 2: Alle gesammelten overrides anwenden
│              │
│              └─ setzt static $cache
│
└─ TSconfig-Phase (pro Seiten-Request)
     └─ ModifyLoadedPageTsConfigEvent feuert
          └─ SiteKitPageTsConfigListener::__invoke()
               └─ sucht __SITEKIT:...__-Marker per Regex
               └─ ruft SiteKitRegistry::getCTypesForGroups() auf
                    └─ nutzt static $cache (kein erneutes Einlesen)
               └─ ersetzt Marker durch kommagetrennte CType-Liste

Marker-Syntax in page.tsconfig

In den page.tsconfig-Dateien der BackendLayouts wird die Marker-Syntax verwendet:

allowed {
  CType = __SITEKIT:group_hero__
}

Gruppen und direkte CTypes können kombiniert werden:

allowed {
  CType = __SITEKIT:group_content_wide,my_special_ctype__
}

Wichtig: Der Marker __SITEKIT:...__ (doppelter Unterstrich) wurde bewusst gewählt. Das #-Zeichen gilt in TypoScript als Kommentarzeichen — ###SITEKIT:### würde den Wert als Kommentar interpretieren und alle CTypes blockieren.

BackendLayout-Übersicht

BackendLayoutHero-Bereich (colPos 3)Main-Spalte (colPos 0)
Default__SITEKIT:group_hero____SITEKIT:group_content_wide__
Homepage__SITEKIT:group_hero____SITEKIT:group_content_wide__
SmallContent__SITEKIT:group_hero____SITEKIT:group_content_wide__
Advanced__SITEKIT:group_hero____SITEKIT:group_advanced__

Container-TCA per PHP

Eigene b13/container-Elemente können die Registry direkt per PHP nutzen:

use OliverThiele\OtSitekitbase\SiteKit\SiteKitRegistry;
use TYPO3\CMS\Core\Utility\GeneralUtility;

$registry = GeneralUtility::makeInstance(SiteKitRegistry::class);

$cTypesSmall = $registry->getCTypesForGroups(['group_content_small']);
$cTypesWide  = $registry->getCTypesForGroups(['group_content_wide']);
$cTypesCards = $registry->getCTypesForGroups(['group_cards']);

getCTypesForGroups() gibt eine kommagetrennte, deduplizierte Zeichenkette zurück — direkt verwendbar im allowed['CType']-Feld der Container-Konfiguration.


Debugging

Cache leeren

Nach jeder Änderung an einer SiteKit.yaml den TYPO3-Cache leeren:

vendor/bin/typo3 cache:flush

Registrierte Gruppen prüfen

use OliverThiele\OtSitekitbase\SiteKit\SiteKitRegistry;
use TYPO3\CMS\Core\Utility\GeneralUtility;

$registry = GeneralUtility::makeInstance(SiteKitRegistry::class);
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump(
    $registry->getGroupToCTypeMap()
);

Häufige Fehlerquellen

ProblemUrsacheLösung
CType erscheint nicht im BackendSiteKit.yaml nicht gefundenSymlink prüfen: ls -la vendor/oliverthiele/
CType erscheint nicht nach ÄnderungStatischer Cache noch aktivTYPO3-Cache leeren
Alle CTypes fehlen in einem BereichMarker-Syntax falschMarker muss __SITEKIT:gruppe__ lauten
Lokale Änderungen haben keine Wirkungvendor/ ist kein SymlinkCanonical Path-Repository in composer.json
ContentBlock CType fehltFalsche CType-AbleitungBindestriche werden entfernt, nicht zu _
Override hat keine Wirkungctype im Override falsch geschriebenExakten CType per getGroupToCTypeMap() prüfen

Registrierte Extensions

ExtensionCType(s)Gruppen
ot-sitekit-baseStandard-TYPO3 CTypes, Containerje nach Element
ot-heroimageot_heroimagegroup_hero
ot-sitekit-ce-cardot_sitekitcecardgroup_content_wide,group_content_small, group_cards
ot-sitekit-ce-textmediaot_sitekitcetextmediagroup_content_wide, group_content_small
ot-sitekit-ce-texticonot_sitekitcetexticongroup_content_wide, group_content_small, group_cards
ot-sitekit-ce-imgtextoverlayot_sitekitceimgtextoverlaygroup_content_wide
ot-markdownot_markdowngroup_content_wide
ot-cefluidtemplatesot_cefluidtemplatesgroup_content_wide
ot-faqotfaq_listgroup_content_wide
ot-jobsotjobs_list, otjobs_showgroup_content_wide
ot-ceheaderot_ceheadergroup_content_wide, group_content_small, group_hero
Sitepackage ContentBlocksvia ContentBlock SiteKit.yamlje nach ContentBlock

Quelldateien

DateiBeschreibung
packages/ot-sitekit-base/Classes/SiteKit/SiteKitRegistry.phpRegistry-Klasse
packages/ot-sitekit-base/Classes/SiteKit/EventListener/SiteKitPageTsConfigListener.phpEventListener für TSconfig-Marker
packages/ot-sitekit-base/Configuration/SiteKit.yamlGruppen-Deklarationen für ot-sitekit-base
packages/ot-sitekit-base/Configuration/TCA/Container/Columns.phpMehrspaltige Container
packages/ot-sitekit-base/Configuration/TCA/Container/CardGroup.phpCard-Container
packages/ot-sitepackage/Configuration/SiteKit.yamlOverrides und dritte Extensions
packages/ot-sitepackage/ContentBlocks/{Category}/{Name}/SiteKit.yamlContentBlock-Deklarationen
packages/*/Configuration/SiteKit.yamlGruppen-Deklarationen je Extension