Inhaltsquellen ermöglichen es einem aktivierten Plugin, typisierte Domänendaten für bestehende CMS-Blöcke bereitzustellen, ohne das öffentliche Markup zu besitzen. Ein Katalog-, Commerce-, Veranstaltungs- oder Nachrichten-Plugin liefert Datensätze; die CMS-Seiten behalten die Kontrolle über Layout, Blockzusammenstellung, Übersetzung, Vorschau und Darstellung.

Die Abgrenzung ist bewusst gewählt:

  • eine Plugin-Quelle beantwortet, welche Daten verfügbar sind;
  • ein CMS-Block beantwortet, wie diese Daten dargestellt werden;
  • der Seiten- und Slot-Baum beantwortet, wo sie erscheinen.

Plugins dürfen die zentralen Renderer für Header, Rich Text, Card, Grid, Slider oder Slide nicht nur deshalb nachbilden, um Plugin-eigene Datensätze anzuzeigen.

Vertrag für Entitätsquellen

Ein aktiviertes Plugin registriert in seiner Definition eine Entitätsquelle:

PluginDefinition::make('plugin-catalog')
  ->contentSources([
    ContentSourceDefinition::entity('plugin-catalog::plugin')
      ->label('Plugin')
      ->resolver(PluginSource::class)
      ->fields([
        'name' => ['type' => 'text', 'label' => 'Name'],
        'description' => ['type' => 'rich_text', 'label' => 'Description'],
        'download_url' => ['type' => 'url', 'label' => 'Download URL'],
      ]),
  ]);

Der Resolver implementiert ContentSourceResolver. options() stellt dem Block-Editor sichere, menschenlesbare Vorschauoptionen bereit; resolve() gibt einen Datensatz für den angeforderten stabilen Schlüssel sowie den aktuellen Site-, Seiten-, Sprach- (Locale) und Vorschaukontext zurück.

Das Plugin bleibt alleiniger Eigentümer seiner Tabellen und Domänenmodelle. Das CMS speichert nur das Quell-Handle, den stabilen Datensatzschlüssel, das ausgewählte Feld und den regulären redaktionellen Rückfallwert des Blocks.

Zugriff und Caching

Eine Quelle mit eingeschränkten Daten bindet über ContentSourceAccessPolicy eine Klasse ein, die accessPolicy(...) implementiert. Die Richtlinie erhält Site, Seite, Sprache (Locale), Vorschaustatus und authentifizierten Akteur, bevor ein Resolver aufgerufen wird. Eine abgelehnte Quelle verhält sich wie eine nicht verfügbare Quelle, und der öffentliche Block behält seinen redaktionellen Rückfallwert.

Plugins können mit cacheFor($seconds) ein zeitlich begrenztes Ergebnis-Caching aktivieren. Cache-Schlüssel enthalten Quelle, Site, Seite, Sprache (Locale), Datensatz-/Abfrageargumente und Quelleinstellungen. Vorschauanfragen umgehen den Cache, damit Editoren stets aktuelle Daten prüfen. Nach einem Schreibvorgang in der Domäne können Plugins app(ContentSourceRuntime::class)->invalidate('plugin-handle::source') aufrufen, um alle zwischengespeicherten Varianten dieser Quelle sofort als veraltet zu markieren. Eine Dauer von null, der Standardwert, deaktiviert das Caching.

Editorverhalten

Unterstützte bestehende Blöcke zeigen in ihrer Registerkarte Einstellungen ein Steuerelement Inhaltsquelle an. Der Editor kann den in Blockfeldern eingegebenen Literalwert beibehalten oder einen Quelldatensatz und ein typkompatibles Feld auswählen. Bindungsausdrücke werden nicht von Hand eingegeben.

Unterstützte Feldbindungen sind:

  • Header-title aus einem text-Quellfeld;
  • Plain-Text-content aus einem text-Quellfeld;
  • Rich-Text-content aus einem text- oder rich_text-Quellfeld.
  • Bildquelle, Bildunterschrift, Alternativtext und Link aus kompatiblen Feldern.
  • Beschriftungen und URLs für Button und Button Link.
  • Titel, Sekundärtext, Beschreibung und URL für Link List Item.

Bei der öffentlichen Darstellung hat die Bindung Vorrang, wenn sie in einen nicht leeren Wert aufgelöst wird. Fehlende Datensätze, deaktivierte Plugins, nicht verfügbare Quellen und leere Werte behalten sicher den redaktionellen Blockwert. Resolver-Fehler werden gemeldet, ohne die Seite außer Betrieb zu setzen.

Bindungen liegen unter settings.content_bindings, sodass die bestehende Seiten-Duplizierung sowie das Revisions-, Export- und Importverhalten sie ohne domänenspezifische Datenbankspalte bewahren.

Sammlungsquellen

Ein Plugin kann ContentSourceDefinition::collection(...) mit einem Resolver registrieren, der ContentCollectionSourceResolver implementiert. Sammlungsfähige Container können diese Sammlung und ein bestehendes direktes Kindelement als wiederholte Vorlage auswählen. Zur Darstellungszeit klont das CMS diesen Teilbaum für jeden Datensatz, stellt den Datensatz als aktuelles Sammlungselement bereit und löst untergeordnete Feldbindungen dagegen auf.

Sammlungsunterstützung ist eine Fähigkeit des Blockvertrags und keine CMS-Liste spezieller Blocknamen. Die zentralen Typen Section, Container, Stack, Cluster, Grid und Slide akzeptieren jede ansonsten gültige direkte Kindvorlage. Slider akzeptiert Slide; Columns akzeptiert Column Item; Feature Grid akzeptiert Feature Item oder Column Item; Link List akzeptiert Link List Item. Split und semantische Container wie Card bieten diese Fähigkeit nicht an, weil das Wiederholen ihrer strukturellen Kinder gegen ihren Layoutvertrag verstoßen würde.

Plugin-Blocktypen können sich mit ->contentCollectionTemplate() für jeden gültigen Kindtyp anmelden oder eine Liste zulässiger Katalog-Slugs für Kindtypen übergeben. Installierte Manifeste drücken denselben Vertrag als content_collection.enabled und optional content_collection.child_types aus. Die öffentliche Containeransicht des Plugins stellt die aufgelösten Kinder genau wie die zentralen Containeransichten über ContentCollectionRenderer::children($block) dar.

Andere Kinder bleiben regulärer redaktioneller Inhalt und behalten ihre Position. Die ausgewählte Vorlage wird an Ort und Stelle durch ihre aufgelösten Datensätze ersetzt. So kann ein Container manuelle und dynamische Inhalte gezielt mischen, ohne dass das Plugin einen eigenen Carousel-, Grid- oder Card-Renderer benötigt. Editoren können bis zu drei Quelldatensätze als Vorschau anzeigen, Datensätze begrenzen, nach einem Quellfeld und Wert filtern, nach einem Quellfeld in beide Richtungen sortieren und Grid- oder Stack-Ergebnisse paginieren. Die Auflösung ist auf 50 Datensätze begrenzt. Eine fehlende Quelle, ein deaktiviertes Plugin, eine ungültige Vorlage oder ein Resolver-Fehler stellt den regulär gespeicherten Blockbaum sicher wieder her.

Für kleine Quellen genügt ContentCollectionSourceResolver, und das CMS wendet Filterung, Sortierung und Paginierung auf das Iterable an. Große Quellen sollten QueryableContentCollectionSourceResolver implementieren. Das CMS übergibt dem Plugin dann eine typisierte ContentCollectionQuery und verarbeitet ein ContentCollectionResult. Dadurch sind Datenbank-/API-Filterung, Sortierung, Begrenzungen, Gesamtzahlen und Seitenfenster möglich, ohne die vollständige Sammlung zu laden.

Editoren wählen getrennt, ob ein gültiges, aber leeres Ergebnis und ein Resolver-Fehler die wiederholte Vorlage ausblenden oder deren redaktionellen Rückfallwert anzeigen. Abgelehnte oder entfernte Quellen behalten gespeicherte Inhalte. Das Einstellungen-Panel meldet Bindungen, deren Plugin, Quelle oder deklariertes Feld verschwunden ist, damit Plugin-Upgrades und -Entfernungen Inhalte nicht unbemerkt verwaisen lassen.

Bindungen und Sammlungskonfiguration befinden sich in der regulären Block-Nutzlast settings. Seitenrevisionen sowie Site-Export/-Import kopieren diese Nutzlast bereits unverändert; weder eine Plugin-eigene Tabelle noch ausführbare Resolver-Ausgaben gelangen in eine CMS-Revision oder ein Transferpaket.

Interne Inhalts-API

API-Clients finden mit GET /webadmin/api/content-sources nur aktivierte und zugängliche Quellen. Die Übergabe von block_id ergänzt kompatible Bindungsziele und die Angabe, ob der Block die Sammlung aufnehmen kann. Entitätsquellen enthalten ihre sicheren Datensatzauswahlen; Felder stammen stets aus dem deklarierten Vertrag des Plugins.

POST /webadmin/api/content-sources/{source}/preview löst einen Entitätsdatensatz oder bis zu fünf Sammlungsdatensätze auf, ohne Inhalte zu ändern. Vorschauantworten verwerfen jeden Wert, den die Quelle nicht deklariert hat, und verwenden den angeforderten Block, die Sprache (Locale), den authentifizierten Akteur und die Quellenzugriffsrichtlinie als Kontext.

Ein bestehender strukturierter Block akzeptiert content_bindings und content_collection auf der obersten Ebene von PATCH /webadmin/api/blocks/{block}; dieselben Objekte werden auch unter settings akzeptiert. Jedes Objekt ersetzt seine zugehörige Konfiguration, null löscht sie. Vor dem Schreiben validiert die API Blockziele, Feldtypen, Quellenzugriff, Datensatzauswahlen, direkte Kindeigentümerschaft und die vom Blockvertrag erlaubten Vorlagentypen für Sammlungen. Ungültige Konfiguration gibt 422 invalid_content_source_configuration zurück. Stellen Sie nach dem Schreiben die zugehörige Entwurfs- oder Update-Seite dar, um das zusammengesetzte Ergebnis zu prüfen.