Skip to content

Architektur

Renick.Content behandelt Inhalte als strukturierte Daten und Layout als austauschbare Präsentation. Alles im Plugin baut auf drei Schichten auf:

  1. Content (JSON) — ein Dokument ist eine Liste typisierter Blöcke, die als JSON in einem Host-Feld gespeichert wird (eine Tailor-Entry-Spalte, ein einfaches Model-Attribut). Das Format ist ein veröffentlichter Vertrag: JSON Schema v1, validiert bei jedem Schreibvorgang.
  2. Editor — eine TipTap-3-/React-18-Insel, die vom Formular-Widget contenteditor in ein beliebiges Backend-Formular eingebunden wird. Das Bundle ist ein committeter Vite-Build (assets/dist); Konsumenten führen niemals eine JS-Toolchain aus.
  3. RenderingBlockRenderer wandelt das JSON zur Request-Zeit über eine Fallback-sichere Partial-Pipeline in HTML um (Theme-Override → Plugin-Default → Platzhalter) und wendet Sichtbarkeitsregeln serverseitig an.

Komponentenübersicht

Der Editor serialisiert das Dokument in eine versteckte <textarea> innerhalb des Widget-Partials; beim Speichern schickt ContentEditor::getSaveValue() den Wert durch ContentDocument::normalize() (repariert unsaubere Eingaben), DocumentValidator (strikte Schema-Prüfung) und BlockRules (Hierarchie-Einschränkungen), bevor er das Host-Feld erreicht. Nach einem erfolgreichen Speichern des Hosts wird ein Versions-Snapshot erfasst und der Media-Usage-Index aktualisiert.

Das Dokument selbst lebt im Host — die pluginspezifischen Tabellen sind Sidecars:

TabelleZweck
renick_content_versionsvollständige Dokument-Snapshots pro Speichervorgang; dient zugleich als Audit-Log
renick_content_templateswiederverwendbare Dokument-/Teilbaum-Vorlagen
renick_content_media_usagewelche Medienpfade von welchem Host + Block referenziert werden
renick_content_ai_usageAI-Token-Abrechnung pro Request für das Monatsbudget

Aufbau des Plugins

plugins/renick/content/
├── Plugin.php          # registrations: widgets, content fields, component,
│                       # twig markup, permissions, settings, schedule
├── routes.php          # optional REST API (/api/renick/content/v1, off by default)
├── blocks/             # 11 shipped block definitions (YAML) + default partials
├── classes/
│   ├── BlockManager, BlockDefinition, BlockRenderer, BlockRules
│   ├── ContentDocument, DocumentValidator, VisibilityRules
│   ├── Content, ContentApi          # PHP facades
│   ├── MediaUsageIndex, MediaDeleteGuard, HostResolver
│   └── ai/             # ProviderManager, drivers, Translator, Drafter, FirecrawlClient
├── components/         # renickContent CMS component
├── contentfields/      # Tailor content field wrapper
├── formwidgets/        # the ContentEditor widget + mount partial
├── console/            # prune-versions, reindex-media commands
├── models/             # Version, Template, AiSetting, AiUsage
├── schema/document-v1.json
├── assets/src/         # editor source (TypeScript + React + TipTap 3)
├── assets/dist/        # committed editor bundle (ESM + CSS) — what ships
└── tests/              # PHPUnit; Playwright e2e lives in /tests-e2e at repo root

Zentrale Einstiegspunkte für Integratoren: