Files
WP-LIT-MCP/docs/superpowers/specs/2026-09-29-divi-absicherung-design.md

17 KiB
Raw Permalink Blame History

Divi-Absicherung – Design-Spezifikation

  • Datum: 2026-09-29
  • Status: Entwurf zur Freigabe
  • Autor: Jan-Niclas Loosen (Loosen-IT), erarbeitet mit Claude
  • Einordnung: eigene Etappe vor Etappe 4 (Designsystem schreiben); Etappe 4 baut darauf auf.

1. Ziel und Kontext

1.1 Problem

Die Divi-Integration hängt an Divi-Interna, nicht an einer zugesicherten Schnittstelle (Divi 5 bietet zum Schreiben keine an). Stand 0.5.0:

  • 19 Dateien rufen Divi direkt auf (et_*-Funktionen, ET\…-Klassen, _et_*-Meta, Option et_divi), auch außerhalb von Integrations/Divi/ (MediaUsageFinder, PostPresenter, ContentSchema).
  • Einige Stellen bilden Divi-Speicherlogik nach (Theme-Builder-Templateliste/Bedingungen/_et_enabled nach et_theme_builder_api_save(), Bibliothekseinträge nach et_pb_submit_layout(), Builder-Kennzeichen nach SyncToServerController). Ändert Divi diese Logik, schreibt das Plugin still falsche Daten.
  • Welche Divi-Teile genutzt werden, steht an drei Orten (DiviCompatibility, DiviThemeBuilder::FUNCTIONS, Docblocks mit Zeilennummern aus Divi 5.2.1). DiviCompatibility prüft nur Existenz, nicht Verhalten.
  • Eine Divi-Version wird nicht geprüft.

1.2 Ziele (Vorgabe Auftraggeber)

  1. Weniger Aufwand pro Divi-Update.
  2. Ungetestete Divi-Version → nichts schreiben, klare Antwort. Lesende Divi-Tools laufen weiter mit Hinweis „Achtung, ungetestet“; schreibende Divi-Tools sind gesperrt und sagen warum.
  3. Freigabe ohne Plugin-Update möglich: getestete Versionen stehen fest im Code; zusätzlich kann ein Administrator auf einer Website im WP-Admin eine Prüfung laufen lassen und die Version danach freigeben (Eintrag in der Datenbank). Freigeben geht nur nach bestandener Prüfung.
  4. Wartbarkeit: Divi-Zugriffe an einer Stelle bündeln (bestehender Code wird umgebaut, nicht nur neuer Code).

1.3 Erfolgskriterien

  1. Außerhalb der fünf Divi-Adapter (§3) gibt es keinen direkten Divi-Zugriff; ein Unit-Test erzwingt das.
  2. Jede genutzte Divi-Funktion/-Klasse/-Methode, jeder Post-Typ, jede Taxonomie, jeder Meta-Schlüssel und jede Option steht im Manifest ihres Adapters; nachgebaute Divi-Funktionen haben einen Fingerabdruck.
  3. Mit einer nicht freigegebenen Divi-Version schreibt kein Divi-Tool; die Antwort trägt divi_untested bzw. divi_incompatible und einen deutschen Hinweis. Lesende Divi-Tools liefern ihr Ergebnis mit Hinweis in warnings.
  4. Die Admin-Prüfung läuft auf einer Live-Website ohne sichtbare Spuren: die Wegwerfseite ist danach in jedem Fall gelöscht.
  5. Alle bestehenden Unit-Tests und Smoke-Skripte sind nach dem Umbau unverändert grün (Umbau ohne Verhaltensänderung).
  6. Eine neue Divi-Version lokal prüfen ist ein Befehl (wp lit-mcp divi-check); bei Rot zeigt --diff die geänderten Divi-Funktionen.

1.4 Nicht Teil dieser Etappe

  • Sperren für Pods (nutzt nur die öffentliche Pods-API) oder den MCP-Adapter.
  • Automatisierter Browsertest des Visual Builders.
  • Schreiben ins Designsystem (Etappe 4 – dort gleich mit Manifest).

2. Begriffe

  • Adapter: Klasse, die als einzige Divi direkt anspricht (§3).
  • Manifest: Beschreibung der Divi-Abhängigkeiten eines Adapters (§4).
  • Nachbau (Mirror): Plugin-Code, der Speicherlogik einer Divi-Funktion wiederholt, statt sie aufzurufen.
  • Fingerabdruck: SHA-256 des normalisierten Quelltexts einer Divi-Funktion/-Methode (§4.2).
  • Live-Prüfung: Abgleich aller Manifeste mit dem installierten Divi (Existenz + Fingerabdrücke), zur Laufzeit, zwischengespeichert (§5.4).
  • Admin-Prüfung: vollständige Prüfung aus dem WP-Admin inkl. Schreibtest (§6).

3. Divi-Grenze

Nur fünf Adapter greifen auf Divi zu. Vorhandene Klassen werden wo möglich zu Adaptern bzw. in sie hineingezogen, damit der Umbau klein bleibt.

Adapter Übernimmt (Stand 0.5.0)
Seiten DiviSaver (Divi-Teil), DiviFlags, CSS-Cache ET_Core_PageResource, WpLinkTargets (Divi-Teil)
Bibliothek DiviLibraryStore, LibraryItemSpec, NewLibraryEntry, DiviRoles, LibraryAccess (Divi-Teil), GlobalLayout
Theme Builder DiviThemeBuilder, Template, TemplateConditions (Divi-Teile)
Designsystem DesignSystemReader, DesignSystem (Divi-Teil), Option et_divi inkl. divi_logo für MediaUsageFinder
Katalog DiviModules, DynamicContentMap, Divi-Post-Typen/Flags für PostPresenter und ContentSchema

Die genaue Klassenaufteilung legt der Plan fest; Regel: jede Divi-Berührung liegt in genau einem Adapter, der Rest des Plugins nutzt nur dessen Methoden.

Parser, Serializer und Compose/ bleiben, wo sie sind: sie kennen das Divi-Format (Blockmarkup, Attributpfade), rufen aber keine Divi-Funktionen auf. Ihr Schutz ist die Katalog- und Formatprüfung (§6.2 Schritte 2–3).

Architekturtest (Unit): durchsucht src/; außerhalb der Adapter-Dateien sind et_*(-Aufrufe, ET\…- und ET_…-Klassen sowie '_et_…'/'et_divi'-Schlüssel ein Fehler. Innerhalb der Adapter ist jede solche Fundstelle ein Fehler, die nicht im Manifest des Adapters steht. Während des Umbaus gibt es eine Ausnahmeliste für Altbestand; am Ende der Etappe ist sie leer und wird entfernt.

4. Manifest

4.1 Inhalt

Jeder Adapter liefert ein Manifest (festes PHP-Wertobjekt, keine Konfigurationsdatei) mit:

  • functions: Divi-Funktionen, die aufgerufen werden;
  • methods: Klasse + Methode (+ erwartete Mindest-Parameterzahl), z. B. ET\Builder\Packages\GlobalData\GlobalData::get_global_colors;
  • classes: Klassen, deren Existenz genügt;
  • post_types, taxonomies, block_types;
  • meta_keys, options: Divi-Schlüssel, die gelesen oder geschrieben werden (dokumentarisch; Architekturtest nutzt sie);
  • mirrors: nachgebaute Divi-Funktionen/-Methoden mit Fingerabdruck und Kurzbeschreibung, was nachgebaut wird;
  • sources: Quellenangaben (Divi-Datei, Funktion) – ersetzt die Zeilennummern in Docblocks. Zeilennummern entfallen.

4.2 Fingerabdruck

sha256 über den Quelltext der Funktion bzw. Methode (per ReflectionFunction/ReflectionMethod: Datei, Start- und Endzeile), normalisiert mit token_get_all(): T_COMMENT, T_DOC_COMMENT, T_WHITESPACE entfernt, übrige Tokens aneinandergehängt. Kommentar- und Formatänderungen ändern den Fingerabdruck nicht; Codeänderungen schon.

Die Soll-Fingerabdrücke werden mit dem Plugin ausgeliefert (erzeugte Datei im Plugin, z. B. JSON neben den Manifesten). Die normalisierten Soll-Quelltexte liegen nur für die Entwicklung unter tests/Fixtures/divi/reference/ (per .gitattributes nicht im Plugin-Paket) und dienen --diff (§7).

4.3 DiviCompatibility

Verliert ihre handgepflegte Liste und prüft alle Manifeste: Existenz von Funktionen/Klassen/Methoden (inkl. Parameterzahl), Post-Typen, Taxonomien, Block-Typen; Fingerabdrücke der Mirrors. Ergebnis: Liste roter Punkte mit Adapter, Divi-Symbol, Fundort in der installierten Version. Die bisherigen Sonderprüfungen (z. B. divi/global-layout registriert oder in den Core-Metadaten) werden Manifest-Einträge mit eigener Prüfregel.

5. Freigabe und Sperre zur Laufzeit

5.1 Divi-Version

Aus dem aktiven Theme wie bisher (EnvironmentProbe: Template Divi, bei Child-Theme Version des Eltern-Themes).

5.2 Zustände

Zustand Bedingung Schreibende Divi-Tools Lesende Divi-Tools
released Version freigegeben (§5.3) und Live-Prüfung grün laufen laufen
untested Live-Prüfung grün, Version nicht freigegeben gesperrt, divi_untested laufen, Hinweis
incompatible Live-Prüfung rot gesperrt, divi_incompatible laufen, Hinweis

Die Live-Prüfung zählt immer, auch für Versionen aus der Code-Liste (erkennt z. B. Hotfixes mit gleicher Versionsnummer). Ist Divi nicht aktiv, gibt es wie bisher keine Divi-Tools; der Zustand ist dann ohne Bedeutung.

5.3 Quellen der Freigabe

Eine Divi-Version ist freigegeben, wenn sie

  1. im Code steht: feste Liste getesteter Versionen (PHP-Konstante), vom Entwickler gepflegt; oder
  2. in der Datenbank der Website steht: Option lit_mcp_divi_releases, Liste von Einträgen {divi_version, plugin_version, user_id, released_at, report_id}. Ein Eintrag entsteht nur über die Admin-Prüfung nach grünem Bericht (§6.3) und gilt nur für die Plugin-Version, mit der geprüft wurde. Nach einem Plugin-Update muss eine nur per Datenbank freigegebene Divi-Version neu geprüft werden, außer sie steht inzwischen in der Code-Liste. Ein Administrator kann Einträge zurückziehen.

Multisite: pro Website (Optionen der jeweiligen Website).

5.4 Live-Prüfung und Zwischenspeicher

Die Live-Prüfung (Manifeste, §4.3) wird im Transient lit_mcp_divi_state zwischengespeichert, Schlüssel aus Divi-Version, Plugin-Version und filemtime der Dateien aller Mirrors und Methoden. Weicht der Schlüssel ab oder lief ein Theme-Update (upgrader_process_complete für das Divi-Theme), wird neu berechnet. Kosten ohne Cache: Reflection + Tokenisieren von rund zehn Funktionen.

5.5 Sperre

Zentral (AbilityRegistrar): Für jedes Tool der Divi-Integration wird vor execute der Zustand ermittelt.

  • Schreibendes Tool (Annotation nicht readonly) und Zustand ≠ released: sofort WP_Error mit Code divi_untested bzw. divi_incompatible, keine Ausführung, Protokolleintrag als abgelehnter Aufruf.
  • Lesendes Tool und Zustand ≠ released: normale Ausführung, Hinweis in warnings des Ergebnisses.

Welche Tools „Divi-Tools“ sind, ergibt sich aus der Integrations-Zugehörigkeit (IntegrationRegistry::groupMap()); Divi-lastige Tools anderer Integrationen deklarieren sich zusätzlich (Ability-Eigenschaft „nutzt Divi“), ein Unit-Test prüft die Zuordnung.

In den Adaptern: Jede schreibende Adapter-Methode prüft den Zustand selbst und wirft bei ≠ released eine eigene Ausnahme, die auf dieselben Fehlercodes abgebildet wird; bestehendes Rollback greift. Das deckt Wege ab, die Divi-Interna indirekt nutzen (z. B. Content-Update einer Divi-Seite über DiviSaver). Generisches Kopieren/Wiederherstellen von Posts (PostCloner, Revisionen) berührt keine Divi-Interna und bleibt ungesperrt.

Prüfmodus: Der Schreibtest der Admin-Prüfung (§6.2 Schritt 4) muss trotz untested schreiben. Er setzt dafür eine request-lokale Ausnahme, die ausschließlich für die ID der Wegwerfseite gilt; sie ist nicht von außen setzbar (kein Parameter, keine Option).

5.6 Hinweistexte

  • divi_untested: „Achtung: Divi {version} ist auf dieser Website noch nicht für LIT MCP freigegeben. Schreibende Divi-Werkzeuge sind gesperrt, bis ein Administrator unter Einstellungen → LIT MCP → Divi die Prüfung ausführt und die Version freigibt. Es wurde nichts geändert.“
  • divi_incompatible: „Divi {version} hat Stellen geändert, die LIT MCP nutzt. Schreibende Divi-Werkzeuge sind gesperrt, bis LIT MCP aktualisiert wurde. Es wurde nichts geändert.“
  • Lesehinweis (warnings): „Achtung: Divi {version} ist für LIT MCP ungetestet (bzw. inkompatibel); Lesen funktioniert, Schreiben ist gesperrt.“

5.7 lit-site-status

Zeigt für Divi zusätzlich: Zustand, Quelle der Freigabe (code/database mit Datum und Benutzer), rote Punkte der Live-Prüfung.

6. Admin-Prüfung

6.1 Oberfläche und Rechte

Neuer Reiter „Divi“ unter Einstellungen → LIT MCP: Zustand, Divi-Version, Quelle der Freigabe, letzter Prüfbericht, Knöpfe „Prüfung starten“, „Divi {version} freigeben“, „Freigabe zurückziehen“. Alle Aktionen: manage_options, Nonce, admin-post-Aktionen wie die übrigen Reiter (AdminPostAction). Eine Sperre (Transient) verhindert zwei gleichzeitige Prüfungen.

6.2 Prüfschritte

  1. Manifeste: Live-Prüfung (§4.3), ohne Cache.
  2. Modulkatalog: Alle Attributpfade aus ShortformMap existieren im Live-Katalog von Divi. Die Logik von tests/Integration/divi-shortform-check.php wandert dafür ins Plugin; das Skript nutzt danach die Plugin-Klasse.
  3. Format im Speicher: Ein mit dem Plugin ausgelieferter Referenzinhalt (Divi-5-Blockmarkup, deckt die Alltagsmodule ab) wird mit dem Plugin-Parser gelesen und serialisiert und muss byte-identisch herauskommen; parse_blocks() muss dieselbe Blockstruktur (Namen, Verschachtelung) liefern.
  4. Schreibtest auf Wegwerfseite: privater Entwurf „[LIT MCP Prüfung] {Datum}“ (Post-Typ page); über den normalen Schreibweg (Composer → Serializer → Seiten-Adapter) je ein Exemplar der Alltagsmodule schreiben; prüfen: Inhalt gespeichert wie serialisiert, Builder-Kennzeichen gesetzt, Rendern über Divi ohne PHP-Fehler/Warnung und mit den erwarteten Texten in der Ausgabe. Kein Eintrag im Änderungsprotokoll. Im finally immer wp_delete_post($id, true) (endgültig, mit Revisionen und Meta); schlägt das fehl, nennt der Bericht die ID zum Löschen von Hand und der Bericht ist rot.

Jeder Schritt meldet grün/rot mit Einzelpunkten. Ein Fehler in einem Schritt bricht die übrigen nicht ab (außer Schritt 4 bei rotem Schritt 1: dann kein Schreibtest).

6.3 Bericht und Freigabe

Der Bericht wird in der Option lit_mcp_divi_check_report gespeichert (letzter Bericht; ID, Zeit, Benutzer, Divi-Version, Plugin-Version, Cache-Schlüssel aus §5.4, Ergebnisse). „Freigeben“ ist nur aktiv – und wird serverseitig nur ausgeführt –, wenn der letzte Bericht vollständig grün ist und Divi-Version, Plugin-Version und Cache-Schlüssel zum aktuellen Stand passen. Freigabe und Zurückziehen werden im Änderungsprotokoll vermerkt.

Hinweis im Bericht (blockiert nichts): „Optional: eine Divi-Seite im Visual Builder öffnen und speichern.“

7. WP-CLI für die Entwicklung

wp lit-mcp divi-check (nur registriert, wenn WP_CLI definiert ist) führt die Prüfschritte aus §6.2 aus und gibt den Bericht aus; Rückgabecode ≠ 0 bei Rot. Freigaben schreibt der Befehl nicht.

  • --diff: zeigt für jeden roten Mirror den Unterschied zwischen Soll-Quelltext (tests/Fixtures/divi/reference/) und installiertem Quelltext, mit Datei und Zeilen in der installierten Version.
  • --update-reference: schreibt Soll-Fingerabdrücke und Referenz-Quelltexte neu – nur, wenn alle übrigen Prüfschritte grün sind. Gedacht nach dem Anpassen eines Nachbaus.

Ablauf bei neuer Divi-Version: lokal einspielen → wp lit-mcp divi-check → bei Grün Version in die Code-Liste eintragen; bei Rot --diff, Nachbau anpassen, --update-reference, Smoke-Skripte, Version eintragen → Plugin-Release.

8. Daten und Deinstallation

Neu: Optionen lit_mcp_divi_releases, lit_mcp_divi_check_report; Transients lit_mcp_divi_state, Prüfsperre. Uninstaller und uninstall.php-Doku werden ergänzt.

9. Fehlerbehandlung

  • Reflection/Tokenisieren scheitert (Funktion fehlt, Datei nicht lesbar): Punkt rot → incompatible, nie Ausnahme nach außen.
  • Zustand nicht ermittelbar (unerwartete Ausnahme): wie incompatible behandeln (Schreiben gesperrt), Protokoll-Fehlereintrag.
  • Admin-Prüfung bricht ab (Timeout, Fatal im Rendern): Wegwerfseite im finally gelöscht; bei Fatal zusätzlich beim nächsten Aufruf des Reiters nach verwaisten „[LIT MCP Prüfung]“-Entwürfen des Plugins suchen (Marker-Meta) und löschen.

10. Tests

Unit:

  • Zustandsberechnung: alle Kombinationen aus Code-Liste, DB-Eintrag (passende/andere Plugin-Version), Live-Prüfung grün/rot.
  • Sperre in AbilityRegistrar: lesend/schreibend × drei Zustände; Fehlercodes und Texte; warnings bei lesenden Tools.
  • Sperre in Adaptern inkl. Prüfmodus nur für die Wegwerfseiten-ID.
  • Fingerabdruck: Kommentar/Leerraum ändert nichts, Codeänderung schon.
  • Architekturtest (§3) und Test „jedes Divi-Tool ist als solches erkannt“.
  • Freigabe nur bei frischem grünem Bericht (Version, Plugin-Version, Cache-Schlüssel); Rechte und Nonce.
  • Uninstaller entfernt die neuen Optionen/Transients.

Integration gegen echtes Divi (Smoke-Skript):

  • Admin-Prüfung komplett grün; Wegwerfseite danach nicht mehr vorhanden (auch keine Revisionen).
  • Künstlich veränderter Soll-Fingerabdruck → incompatible, schreibendes Tool liefert divi_incompatible, lesendes Tool liefert Ergebnis + Hinweis.
  • Version aus Code-Liste entfernt → untested; nach Admin-Prüfung + Freigabe → released.
  • wp lit-mcp divi-check grün; --diff bei verändertem Soll zeigt den Unterschied.

Regression: alle bestehenden Unit-Tests und Smoke-Skripte unverändert grün.

11. Umsetzungsreihenfolge

  1. Manifest-Format, Fingerabdruck, Architekturtest mit Ausnahmeliste für Altbestand.
  2. Adapter nacheinander umbauen, bis die Ausnahmeliste leer ist; DiviCompatibility auf Manifeste umstellen; Docblock-Zeilennummern entfernen.
  3. Zustand, Freigabe (Code-Liste, Datenbank), zentrale und Adapter-Sperre, lit-site-status.
  4. Admin-Reiter „Divi“, Prüfschritte, Wegwerfseite, Bericht, Freigabe.
  5. WP-CLI-Befehl mit --diff und --update-reference.
  6. Security-Audit; danach Etappe 4.