chore: Version 0.7.0 (Etappe 4); Spec und Notizen nachgeführt

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Jan-Niclas Loosen
2026-10-20 00:31:24 +02:00
co-authored by Claude Sonnet 5.5
parent 1fdcb2e075
commit b91c356a28
7 changed files with 132 additions and 15 deletions
@@ -215,6 +215,18 @@ In-Request-Caches: `GlobalData::$_cached_data` (Reset bei `set_*`), `GlobalPrese
| ePanel | `edit_theme_options` + Rollen-Recht `theme_options` |
| `remove_static_resources` | `edit_posts` (oder Cron), sonst wirkungslos |
## Nachtrag Divi 5.15.1 – Schleifen (Etappe 4e, 2026-10-20)
Ausführlich: `2026-10-19-etappe-4e-recherche-schleifen.md` (rekonstruiert, siehe dort); Pfade relativ zu `includes/builder-5/server/Packages/Module/Options/Loop/`.
1. **Speicherort:** Block-Attribut `module.advanced.loop`; Schalter `desktop.value.enable`, Art `desktop.value.queryType`. Divi liest beide mit `sanitize_key()`, fehlender `queryType` → `post_types` (`LoopUtils.php:725-732`).
2. **`queryType`-Werte:** `post_types`, `current_page` (Beiträge), `post_taxonomies` (Terme; intern `terms`), `user_roles` (Benutzer), `menus`; Divi kennt außerdem die Aliase `terms` und `users` (`LoopUtils.php:881-898`) und `repeater_<ACF-Feld>`.
3. **Kontextregel:** nächster Vorfahre-oder-selbst mit `desktop.value.enable === "on"`; Tablet/Phone/Hover und `true` zählen nicht; die innerste Schleife gilt.
4. **`loop_*`-Optionen und Arten:** 34 Optionen in der Registry; Art nach Gruppe („Loop Terms“, „Loop Users“, übrige = Beiträge), die drei Meta-Schlüssel-Optionen nach Namen (Gruppennamen sind übersetzt); gespeichert wird der Array-Schlüssel.
5. **Gefahr des Fehlabgleichs:** `loop_<post|user|term>_meta_key_*` liest Meta der Art aus dem Namen mit der **ID der Schleife** (`DynamicContentLoopOptions.php:145-158`): Post-Meta des Beitrags mit der Term-/Benutzer-ID. Bei verschachtelten Schleifen gibt eine leere innere Schleife den Block unverändert an die äußere (`LoopUtils.php:4449-4457`, `4572-4598`); darum prüft das Plugin Meta-Optionen gegen jede Schleife der Kette.
6. **Rendern außerhalb einer Schleife:** `loop_*` hat keine Quelle und bleibt leer; das Plugin lehnt es beim Schreiben ab.
7. **Grenzen:** Presets starten oder ändern Schleifen auf der Website nicht (Divi parst das rohe Dokument, `LoopUtils.php:4219-4229`); globale Module werden vor der Schleifen-Phase expandiert (`BlockParser.php:917-924`), das Plugin sieht ihren Inhalt nicht.
## 7. Abweichungen und Ergänzungen zu Spec §7
1. **„Variablen … über `GlobalData::set_global_variables`“** – stimmt, aber die Funktion ersetzt die ganze Option, liefert keinen Fehler bei fehlenden Rechten und kennt keinen Typ `colors`. Das Tool muss vorher lesen, `stdClass` → Array wandeln, `allowedActions` und die zwei Customizer-Schriften entfernen und nach dem Schreiben per Lesen prüfen.
@@ -120,3 +120,44 @@ Belege: `2026-10-19-etappe-4d-divi-recherche.md`; Formate-Nachtrag „Etappe 4d
- Smoke-Skripte: fehlende `file_exists`-Prüfung in Schritt 7, Format-Grep im Probelauf vakuos (stattdessen `sha256`/`bytes` prüfen), Namenskonflikt prüft nicht auf `conflict`, `'none'` nicht isoliert, kein Zurücklesen von `body_font`, EXIT-Trap stellt ganz `et_divi` wieder her (Admin-Änderungen während des Laufs gehen verloren) und räumt Snapshots sowie Dateien fälschlich akzeptierter Schriften nicht auf, Sentinel-Prüfung vakuos, `restore()` verbirgt stderr.
- Protokoll: `src/Admin/LogObjects.php` kennt den Objekttyp `divi_font` nicht (Anzeige als Code).
- Kleinkram: Reihenfolge der `use`-Blöcke; `DiviLocked`-Rethrow setzt voraus, dass die Sperre vor jedem Schreiben greift.
## Etappe 4e (Plan 2026-10-19-etappe-4e-schleifen-guides-audit.md)
Belege: `2026-10-19-etappe-4e-recherche-schleifen.md` (rekonstruiert, siehe dort), Audit `2026-10-19-etappe-4e-security-audit.md` (Status nach der Fix-Welle). Die Rulings amendieren Spec §9.
- **X1:** Der Schleifen-Kontext ist der des nächsten Vorfahren-oder-selbst mit `loop.desktop.value.enable === "on"`; `queryType` fehlt → `post_types`; die innerste Schleife gilt.
- **X2:** Arten `post`, `term`, `user`, `menu`; die Art einer Option folgt der Divi-Gruppe, die Meta-Schlüssel-Optionen dem Namen; gespeichert wird der Array-Schlüssel.
- **X3:** `VariableRef` und `DynamicContentRules` bekommen einen `LoopScope`; Insert, Update und Move prüfen im Kontext des Ziels, Move warnt statt abzulehnen (A11); `lit-content-create` hat nie einen Kontext.
- **X4:** Kurzform `{{loop:<option>}}` über die Tabelle `LOOP` in `Placeholders`.
- **X5:** Neue Meldungen („braucht eine Divi-Schleife“, „passt nicht zur Schleife … (Typ: …)“); Ruling S36 abgelöst.
- **X6:** `lit/divi-dynamic-sources` mit `post_id` + `node` nennt die zur Schleife des Knotens passenden Quellen.
- **X7:** Grenzen statt Lösung: Schleifen über `attrs` schaltbar, globale Module ohne Kontext, Kopieren mit `unfiltered_html`, Preset-Schleifen unerkannt, ACF-Wiederholungsfelder nicht unterstützt.
- **X8:** Guides ohne Prompts: Ablauf „Corporate Design übernehmen“ in `workflows.md`, Design-Tools und Fehlercodes in `divi-design-system.md`/`overview.md`, Loop-Regeln in `divi-placeholders.md`/`divi-shortform.md`.
- **X9:** Unabhängiger Security-Audit (0 kritisch, 0 hoch, 1 mittel, 9 niedrig, 10 Info); Fix-Welle für M1, L1 (Option B), L2, L4–L8 und DNS-Rebinding.
- **X10:** Version 0.6.1 → 0.7.0, kein Tag, kein Release.
- **Zusätze aus dem Audit:** Kettenregel für `_meta_key_`-Optionen (M1), `queryType` wie `sanitize_key` mit Aliasen `terms`/`users` (L2), Rechteprüfung für Schleifen-Einstellungen (L1 B: `list_users`, `read_private_posts`), Restore berechnet Fundstellen (L4), ein Lock für Farben und Theme-Optionen, atomarer `DesignLock` (L5, L6), `CURLOPT_RESOLVE` gegen DNS-Rebinding und Abruf nur mit cURL (L8).
### Folgearbeit nach Etappe 4
Aus dem Audit (nicht behoben):
- **L3:** Globale Instanzen und Kopien (`unfiltered_html`: `lit/library-insert` im Kopiermodus, `lit/divi-node-copy`) tragen `loop_*`-Inhalt über Schleifen-Arten ohne Prüfung oder Warnung; braucht einen eigenen Plan.
- **L9:** Der Seiten-Umschreiber parst jeden Kandidaten bei jedem Probelauf und Confirm, ohne Cap für Entwürfe (Administrator-Niveau, Wirkung endet mit dem Request).
- **L8-Rest:** Bei https mit einem cURL ohne SSL kann Requests auf fsockopen ausweichen (selten, bewusst belassen).
- **I1–I10:** I1 Preset-Detach ohne Marker-Prüfung der Affixe; I2 abgelöster Variablenwert ohne Bereinigung für den Feldtyp; I3 `from_node` mit `unfiltered_html` kopiert `loop_*` ungeprüft in Presets; I4 Lese-Tools prüfen Rechte nur in `permission()`; I5 Shortcodes und Bedingungen in Term-/Benutzer-/Menü-Schleifen laufen gegen den Beitrag mit der Term-/Benutzer-ID; I6 Font-Probelauf verrät private DNS-Auflösung; I7 Font-Confirm ist nicht an die Probelauf-SHA-256 gebunden; I8 Font-Download bis ca. 120 s je Aufruf, Temp-Reste bei Abbruch; I9 Lost Update auf `et_uploaded_fonts`; I10 `numbers`-Variablen akzeptieren `url(https://…)`.
- **Z1:** Schleifen und `loop_*`-Verweise aus Presets erkennt die Baumprüfung nicht (fail closed; auf der Website ohne Wirkung, weil Divi die Schleife aus dem rohen Dokument liest).
Übernommen aus 4d und früher:
- Schema-Fehler-Form projektweit (Adapter-Eingabeschema statt `validation_failed`-Feldpfade).
- Schriftnamen in Preset- und Modul-Attributen prüfen; `lit/divi-fonts-list`/Schriftsuche; Entfernen hochgeladener Schriften; Format `eot`.
- Rev-Helfer der Book-Klassen vereinheitlichen.
- `dryRun()`/`installed()` aus `DiviFontsUploadAbility::upload()` herauslösen.
- sha256-Pin beim Upload-`confirm` (`expected_sha256`).
- Weitere Minor-Punkte aus den Abschnitten „Offene Kleinpunkte“ (4a, 4d) und unten (4e).
### Offene Kleinpunkte aus 4e (Ledger, nicht behoben)
- `LoopScope`/`LoopContext`: `LOOP`-Tabelle mit 31 Identitätszuordnungen (Stil); Lücken bei Tests (int/bool `queryType`, Groß-/Kleinschreibung, Wurzelknoten opak, kein Test für den Standard-Konstruktor von `Placeholders`).
- `DynamicContentMapTest` prüft nur „Schleifen“ statt „braucht eine Divi-Schleife“; die Fehlanpassungsmatrix hat nicht alle Zeilen (Benutzer-Meta in Term-/Menü-Schleife, `loop_product_*` in Nicht-Beitrags-Schleifen); ein nicht unterstützter `queryType` erscheint roh im Fehlertext; `VariableRefTest` akzeptiert zwei Meldungen.
- Insert: Meldung „braucht eine Divi-Schleife“, wenn derselbe Aufruf die Schleife am Knoten setzt, dessen Elternteil keine hat; doppelter Warntext, wenn Vorfahr und Nachfahr zugleich geändert werden; Wechsel von keiner zu nicht unterstützter Schleife ohne Warnung; Cache-Schlüssel `''` für „keine“ und „nicht unterstützt“ geteilt; Wortlaut der Move-Warnung „Divi zeigt sie dort leer“ für nicht unterstützte Ziele.
- Tests: `testInLoopChecksLoopContentAgainstItsScope` und `testLoopContentBelowANewLoopContainerIsRefused` zu schwach; Obfuskations-Datenprovider prüft nur `problems !== ''`; kein Test „keine Schleifen-Warnung bei einfachem Update in der Schleife“; Testzeilen über 120 Zeichen (Tests außerhalb des Lints).
- `lit/divi-dynamic-sources`: Bibliothekseinträge und Theme-Builder-Layouts nicht erreichbar (Docblock verspricht mehr); `page()` lädt zweimal; tote Fixture-Einträge in `withLoopPage`.
- Audit-Spur: Innerhalb einer Schleife reicht Divi `loop_id`/`loop_query_type`/`loop_object` an jede Inhaltsvariable; Resolver von Nicht-Loop-Optionen, die `loop_id` nutzen, sind nicht einzeln nachverfolgt (I5 deckt Shortcodes ab).
@@ -0,0 +1,51 @@
# Etappe 4e – Divi-Schleifen: Recherche (Divi 5.15.1)
Stand 2026-10-20. **Hinweis zur Herkunft:** Die ursprüngliche Recherche (`research-4e-loop-divi.md` im Scratchpad der Planung) war nicht mehr auffindbar. Diese Notiz ist deshalb aus den Belegen rekonstruiert, die im Repo stehen: Security-Audit (`2026-10-19-etappe-4e-security-audit.md`), Task-Berichte der SDD-Läufe und der Divi-Quelltext 5.15.1 selbst. Sie enthält nur Fakten, die dort belegt sind; Zeilenangaben beziehen sich auf `includes/builder-5/server/Packages/Module/Options/Loop/` (Divi 5.15.1) und sind dort geprüft oder aus dem Audit übernommen.
## 1. Speicherort und Schalter
- Die Schleife steht im Block-Attribut `module.advanced.loop`, je Gerät und Zustand: `desktop.value.enable` (`"on"`) und `desktop.value.queryType`.
- Divi liest beide Werte mit `sanitize_key()`; fehlt `queryType`, gilt `post_types` (`LoopUtils.php:725-732`). Nur `desktop` zählt; Tablet-, Phone- und Hover-Varianten schalten keine Schleife (Ruling X1).
- Die Schleife wird beim Rendern aus dem **rohen** Dokument gelesen (`WP_Block_Parser`, `LoopUtils.php:4219-4229`). Presets (`LoopPresetAttrsMap`) starten, stoppen oder ändern eine Schleife auf der Website nicht.
## 2. `queryType`-Werte
| `queryType` | Art im Plugin | Bemerkung |
|---|---|---|
| `post_types`, `current_page` | Beiträge (post) | Standard bei fehlendem Wert |
| `post_taxonomies` | Terme (term) | Divi bildet ihn intern auf `terms` ab (`LoopUtils.php:735-738`) |
| `user_roles` | Benutzer (user) | |
| `menus` | Menü (menu) | |
| `terms`, `users` | Terme, Benutzer | Aliase, die Divi kennt (`LoopUtils.php:881-898`); das Plugin normalisiert wie `sanitize_key` (Audit L2) |
| `repeater_<ACF-Feld>` | nicht unterstützt | verlangt die Einstellung `acf_type`; `loop_*` darin wird abgelehnt (X7e) |
## 3. Kontext eines Moduls
- Maßgeblich ist die **innerste** eingeschaltete Schleife auf dem Weg Wurzel → Knoten, den Knoten selbst eingeschlossen (X1).
- Verschachtelte Schleifen: Hat die innere Schleife keine Treffer, gibt Divi den Block unverändert zurück (`__loop_no_results`, `LoopUtils.php:4449-4457`); die äußere Schleife löst danach die `$variable(…)$`-Verweise mit **ihrem** Objekt auf (`LoopUtils.php:4572-4598`). Deshalb gilt für `_meta_key_`-Optionen die Kettenregel (Audit M1).
- Innerhalb einer Schleife reicht Divi `loop_id`, `loop_query_type` und `loop_object` an jede Inhaltsvariable weiter.
## 4. `loop_*`-Optionen
- Divi registriert 34 Loop-Optionen. Die Art bestimmt die Gruppe der Option („Loop Terms“, „Loop Users“, übrige = Beiträge, Menü nach Name); die drei Meta-Schlüssel-Optionen `loop_post_meta_key_manual_custom_field`, `loop_user_…`, `loop_term_…` ordnet der Name zu, weil ihre Gruppennamen übersetzt sind.
- Gespeichert wird der Array-Schlüssel der Option (`loop_term_name`), nicht die interne `id`.
## 5. Gefahr des Fehlabgleichs (Sicherheitsgrenze)
- `loop_<post|user|term>_meta_key_*` entnimmt die Meta-Art dem **Namen** und liest die Metadaten des Objekts mit der **ID der Schleife** (`DynamicContentLoopOptions.php:145-158`). Eine Post-Meta-Option in einer Term- oder Benutzer-Schleife liest also die Metadaten des Beitrags mit derselben ID, auch von Entwürfen und privaten Beiträgen (umgekehrt Benutzer-/Term-Meta in einer Beitrags-Schleife).
- Die übrigen `loop_*`-Resolver prüfen `instanceof WP_Post`/`WP_Term`/`WP_User` und liefern für ein fremdes Objekt `''` (`LoopUtils.php:3162+`, `3553+`, `3599+`).
- Benutzer-Meta in Benutzer-Schleifen verlangt vom **Betrachter** `manage_users` (nicht ACF) bzw. `list_users` (ACF) (`DynamicContentACFUtils.php`); kein Leck an Besucher.
- Folge im Plugin: Ein `loop_*`-Wert ist nur erlaubt, wenn die Art des Schleifen-Kontexts zur Art der Option passt; ohne Schleife ist jede `loop_*`-Option abgelehnt.
## 6. Rendern außerhalb einer Schleife
Ohne Schleife in der Vorfahrenkette bleiben `loop_*`-Verweise ohne Quelle und rendern leer; das Plugin lehnt sie deshalb schon beim Schreiben ab, mit der Meldung „braucht eine Divi-Schleife“.
## 7. Grenzen (dokumentiert, nicht gelöst)
- **Presets:** Ein Preset kann `loop_*`-Verweise und Schleifen-Einstellungen tragen; die Baumprüfung erkennt Schleifen aus Presets nicht (fail closed). Auf der Website bleibt das ohne Wirkung (siehe 1).
- **Globale Module:** Der Inhalt eines globalen Eintrags hat keinen Schleifen-Kontext (`loop_*` im Eintrag wird abgelehnt). Eine globale Instanz in einer Schleife expandiert Divi vor der Schleifen-Phase (`BlockParser.php:917-924`); das Plugin sieht nur die lokalen Attribute der Instanz (Audit L3, offen).
- **Shortcodes und Bedingungen** in Term-/Benutzer-/Menü-Schleifen laufen gegen den Beitrag mit der Term-/Benutzer-ID (`LoopUtils.php:4507-4510`, Audit I5).
- **Rechte:** Schleifen über `attrs` können private Beiträge und Benutzerdaten ausgeben, wie im Divi-Builder; das Plugin verlangt dafür `list_users` (Benutzer) bzw. `read_private_posts` (`any`, `attachment`, leere `subTypes`; Audit L1, Option B).
*Fußnote: Alle Angaben gegen Divi 5.15.1 (Formate zuvor aus 5.2.1 und 5.14.0 geprüft; 5.15.1 maßgeblich).*
@@ -1,7 +1,7 @@
# Etappe 4 – Designsystem schreiben – Design-Spezifikation
- **Datum:** 2026-10-16
- **Status:** Entwurf zur Freigabe
- **Status:** umgesetzt (Etappe 4a–4e, Version 0.7.0)
- **Autor:** Jan-Niclas Loosen (Loosen-IT), erarbeitet mit Claude
- **Einordnung:** Etappe 4 der Gesamt-Spec (`2026-09-25-wp-lit-mcp-design.md` §7, §13); baut auf der Divi-Absicherung (`2026-09-29-divi-absicherung-design.md`) auf. Entscheidungen G1–G12: `docs/superpowers/notes/2026-09-28-etappe-4-entscheidungen-entwurf.md`. Datenformate: `docs/superpowers/notes/2026-09-28-etappe-4-divi-formate.md` (Divi 5.2.1).
- **Annahmen** sind mit **(A…)** markiert: Punkte, die im Brainstorming nicht einzeln gefragt wurden; bei der Freigabe der Spec bestätigen oder ändern.
@@ -15,7 +15,7 @@ Das Plugin liest das Designsystem (`lit/divi-design-system`: Farben, Variablen,
- Einstellungen eines Presets lesen; Presets anlegen, ändern, löschen; Gruppen-Presets und Preset-Stapel zuweisen; Presets auf viele Seiten auf einmal ausrollen oder überall entfernen.
- Globale Farben, Variablen, Design-Theme-Optionen und Schriften schreiben.
- Eine Wiederherstellung: Divi 5 führt für Farben, Variablen und Presets keine serverseitige Historie (Formate §7.6).
- Schleifen-Inhalte (`loop_*`, z. B. Datum oder Kategorien in Karten einer Loop-Spalte) werden immer abgelehnt (Ruling S36), mit irreführender Meldung „nur innerhalb von Divi-Schleifen“ (G12).
- Schleifen-Inhalte (`loop_*`, z. B. Datum oder Kategorien in Karten einer Loop-Spalte) wurden bis 4d immer abgelehnt (Ruling S36), mit irreführender Meldung „nur innerhalb von Divi-Schleifen“ (G12); seit 4e gelten die Regeln aus §9.
### 1.2 Ziele
@@ -65,7 +65,7 @@ lit/divi-design-detach ─┘
- Neue Divi-Aufrufe liegen nur im **Designsystem-Adapter** (Schreiben: `GlobalData::set_global_colors`, `set_global_variables`, `GlobalPreset::prepare_data`, `validate_preset_count`, `save_data`, `et_update_option`, `FontsUtility`/Divis Upload-Filter) und im **Katalog-Adapter** (`GlobalPreset::get_group_preset_default_attr`, `get_default_group_name`, `Conversion::get_preset_attrs_mapping`, `get_preset_attrs`, `et_builder_get_google_fonts`, Loop-Optionen). Jeder Eintrag steht im Manifest; nachgebaute Logik bekommt einen Fingerabdruck. Divi-Funktionen werden aufgerufen, wo möglich, statt nachgebaut.
- Domänenklassen (Bestände berechnen, Diff, Prüfregeln, Überdeckungen) sind reines PHP und unit-testbar; sie arbeiten auf den Rohdaten des Adapters.
- Seitenänderungen laufen über die vorhandenen Bausteine: `Parser`/`TreeEditor`/`Composer`/`Serializer` und `DiviSaver` (Revision je Seite, Cache), Rechte und Grenzen wie `GlobalUsages`/`VisibleEdits`.
- Formate stammen aus Divi 5.2.1; freigegeben ist inzwischen 5.14.0. **Erster Umsetzungsschritt:** Formate und Funktionssignaturen gegen 5.14.0 prüfen und die Formate-Notiz nachführen (Spec §14 Gesamt-Spec: „nur aus Code abgeleitet“).
- Formate stammen aus Divi 5.2.1 (Formate aus 5.2.1/5.14.0 geprüft, 5.15.1 maßgeblich); freigegeben sind 5.2.1, 5.14.0 und 5.15.1. **Erster Umsetzungsschritt:** Formate und Funktionssignaturen gegen 5.15.1 prüfen und die Formate-Notiz nachführen (Spec §14 Gesamt-Spec: „nur aus Code abgeleitet“).
## 4. Änderungs-Pipeline (freigegeben)
@@ -190,15 +190,20 @@ Jedes Tool nimmt **mehrere Einträge** eines Bereichs je Aufruf (ein Snapshot, e
- Keine Snapshots für Schriften: ein Upload legt nur neu an, überschreibt nie (A2). Probelauf + `confirm` gelten trotzdem.
- DSGVO: lokales Laden der Google-Fonts bleibt Theme-Einstellung; Tool-Beschreibung weist auf hochgeladene Schriften als datensparsame Variante hin.
## 9. Schleifen-Inhalte (G12)
## 9. Schleifen-Inhalte (G12, umgesetzt in 4e; aus Divi 5.15.1 abgeleitet)
- **Kontext:** Für den Zielknoten wird der nächste Knoten auf dem Weg Wurzel → Knoten (einschließlich des Knotens selbst) gesucht, dessen `module.advanced.loop.desktop.value.enable` an ist; daraus `queryType` (`post_types`, `post_taxonomies`/`terms`, `user_roles`/Benutzer, Menü …). Genaue Regeln (Selbst vs. Vorfahre, verschachtelte Schleifen, Werte von `queryType`) werden im ersten Umsetzungsschritt aus Divi 5.14.0 abgeleitet (`LoopUtils`, `LoopContext`, `DynamicContentLoopOptions`, Visual-Builder-Logik) und in der Formate-Notiz festgehalten.
- **Erlaubte Optionen:** `DynamicContentMap` liefert `loop_*`-Optionen nicht mehr verworfen, sondern getrennt je Query-Typ (Optionen aus Divis Registry, Zuordnung zum Query-Typ aus Divis Code). `DynamicContentRules::fieldsFor()` bekommt den Schleifen-Kontext; `loop_*` nur, wenn eine Schleife vorhanden ist und die Option zum Query-Typ passt. Einstellungen werden wie alle Dynamic-Content-Einstellungen je Feldtyp bereinigt, Meta-Schlüssel-Regeln S29/S30 inklusive `loop_*_meta_key_`.
- **Meldungen:** ohne Schleife: „Schleifen-Inhalt "%s" braucht eine Divi-Schleife in diesem Modul oder einem übergeordneten Element (Abschnitt, Zeile, Spalte, Gruppe).“; falscher Typ: „… passt nicht zur Schleife dieses Elements (Typ: Terme).“
- **Kurzform:** Platzhalter `{{loop:<option>}}` (z. B. `{{loop:post_date}}` → `loop_post_date`) mit Einstellungen wie `{{post:…}}` (A10).
- **`lit/divi-dynamic-sources`:** optional `post_id` + `node` (Pfad-ID) → zusätzlich die `loop_*`-Optionen des Schleifen-Kontexts dieses Knotens.
- Knoten, die per Insert/Move in eine Schleife gelangen oder sie verlassen: Prüfung am Zielort; ein Move, der vorhandene `loop_*`-Inhalte aus der Schleife herausführt, erzeugt eine Warnung (nicht abgelehnt – Divi lässt das zu) (A11).
- Ruling S36 wird abgelöst; Sicherheitsblick im Audit (§12).
Belege: `docs/superpowers/notes/2026-10-19-etappe-4e-recherche-schleifen.md`; Audit: `…-etappe-4e-security-audit.md`.
- **Kontext (X1):** Der Schleifen-Kontext eines Knotens ist der des nächsten Vorfahren-oder-selbst, dessen `module.advanced.loop.desktop.value.enable` genau `"on"` ist (Tablet-, Phone- und Hover-Varianten zählen nicht, wie bei Divi). `queryType` wird wie bei Divi mit `sanitize_key` gelesen; fehlt er (auch `null`), gilt `post_types`; `terms` und `users` sind Aliase für Term- und Benutzer-Schleifen (L2). Verschachtelte Schleifen: die innerste gilt für alles darunter; für `loop_<art>_meta_key_*`-Optionen muss die Art jeder eingeschalteten Schleife der Vorfahrenkette passen, weil eine leere innere Schleife ihren Block unverändert an die äußere gibt (Kettenregel, Audit M1).
- **Arten und Optionen (X2):** `post` (`post_types`, `current_page`), `term` (`post_taxonomies`, `terms`), `user` (`user_roles`, `users`), `menu` (`menus`). Die Art einer Option folgt der Gruppe der Divi-Option, die drei Meta-Schlüssel-Optionen dem Namen; gespeichert wird der Array-Schlüssel (`loop_term_name`). `repeater_<ACF>`-Schleifen sind nicht unterstützt: `loop_*` darin wird abgelehnt (X7e). `DynamicContentMap::loopFields($art)` liefert die Optionen je Art, `DynamicContentRules`/`VariableRef` nehmen einen `LoopScope`.
- **Typabgleich als Sicherheitsgrenze:** Ein `loop_*`-Wert ist nur erlaubt, wenn die Art des Kontexts zur Art der Option passt; ohne Schleife ist jede `loop_*`-Option abgelehnt. Grund: Divi liest `loop_post_meta_key_*` in einer Term-/Benutzer-Schleife als Post-Meta des Objekts mit der Schleifen-ID (und umgekehrt). Die Meta-Schlüssel-Regeln S29/S30 gelten auch für `loop_*_meta_key_`.
- **Meldungen (X5):** ohne Schleife: „Schleifen-Inhalt "%s" braucht eine Divi-Schleife in diesem Modul oder einem übergeordneten Element (Abschnitt, Zeile, Spalte, Gruppe).“; falsche Art: „… passt nicht zur Schleife dieses Elements (Typ: Terme).“ (Typ: Beiträge, Terme, Benutzer, Menü).
- **Kurzform (X4):** `{{loop:<option>}}` (z. B. `{{loop:post_date}}` → `loop_post_date`) mit Einstellungen wie `{{post:…}}` (A10); die Tabelle `LOOP` in `Placeholders` ordnet Kurznamen den Optionen zu.
- **`lit/divi-dynamic-sources` (X6):** optional `post_id` + `node` (Pfad-ID): zusätzlich die zur Schleife dieses Knotens passenden `loop_*`-Optionen; ohne Schleife im Kontext ein Hinweis statt einer Liste; Leserecht auf die Seite wie `lit-divi-node-get`.
- **Insert, Update, Move (X3):** Insert prüft im Kontext der Zielposition; schaltet ein Aufruf eine neue Schleife und `loop_*`-Inhalt zugleich ein, wird fail closed auf den komponierten Blöcken entschieden. Update prüft im Kontext des Knotens (ein Composer je Kontext, neue `loop`-Attribute desselben Aufrufs zählen) und warnt, wenn der Wechsel der Schleifen-Art unveränderte Kinder mit `loop_*` betrifft. Move prüft am Ziel und **warnt** (lehnt nicht ab; A11), wenn `loop_*`-Inhalte ihre Schleife verlassen oder in eine andere Art kommen. Die Warnung gilt nur für Inhalte, die vorher zur Schleifen-Kette passten (M1). `lit-content-create` und Theme-Builder-Anlage haben nie einen Schleifen-Kontext.
- **Rechte (Audit L1, Option B):** Eine Schleife in `module.advanced.loop`, die Benutzer (`user_roles`) ausgibt, verlangt `list_users`; eine Beitrags-Schleife mit leeren, `any`- oder `attachment`-`subTypes` verlangt `read_private_posts`; das gilt auch beim Kopieren.
- **Grenzen (X7, dokumentiert):** Schleifen schalten über `attrs` bleibt möglich (A3 verbietet nur ein eigenes Werkzeug); globale Module werden nicht betreten, `loop_*` in Bibliothekseinträgen wird abgelehnt (die Einfügung globaler Instanzen und das Kopieren mit `unfiltered_html` prüfen die Art nicht, Audit L3, offen); Schleifen aus Presets erkennt die Baumprüfung nicht (fail closed).
- Ruling S36 ist abgelöst (X5).
## 10. Rechte
@@ -236,7 +241,7 @@ Alle Schreib-Tools sind Divi-Schreib-Tools im Sinne der Divi-Absicherung (gesper
## 14. Umsetzungsreihenfolge
1. Formate und Signaturen gegen Divi 5.14.0 prüfen (Presets, Farben, Variablen, Theme-Optionen, Fonts, Loop-Kontext); Formate-Notiz nachführen; Manifest-Einträge.
1. Formate und Signaturen gegen Divi 5.15.1 prüfen (Presets, Farben, Variablen, Theme-Optionen, Fonts, Loop-Kontext); Formate-Notiz nachführen; Manifest-Einträge.
2. Pipeline, `design_rev`, SnapshotStore, `design-snapshots`/`design-restore` (zuerst mit Bereich `presets`).
3. Presets: `preset-get`, `presets-set` (inkl. `from_node`, Gruppen, Standard), `presets-delete`.
4. Zuweisen an Module: Stapel, `group_presets`, Überdeckungen/`clear_overrides`, Outline mit Gruppen-Presets.
+9 -1
View File
@@ -4,7 +4,7 @@ Tags: mcp, ai, divi, pods, oauth
Requires at least: 6.9
Tested up to: 7.1
Requires PHP: 8.1
Stable tag: 0.6.1
Stable tag: 0.7.0
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
@@ -196,6 +196,14 @@ LIT MCP schreibt nur mit Divi-Versionen, die für diese Plugin-Version geprüft
== Changelog ==
= 0.7.0 =
* Designsystem schreiben (Etappe 4): Presets lesen, anlegen, ändern, löschen, einzelnen Modulen und ganzen Seiten zuweisen und Verweise überall entfernen (Probelauf, Bestätigung, Snapshot, Wiederherstellen).
* Globale Farben und Variablen anlegen und ändern; Variablen werden archiviert, nicht gelöscht; Verweise auf Variablen durch ihren Wert ersetzen.
* Divi-Theme-Optionen (Schriften, Größen, Layout) lesen und ändern; eigene Schriften von einer URL hochladen; Schriftnamen mit Vorschlägen prüfen.
* Schleifen-Inhalte (`loop_*`, `{{loop:…}}`) in Modulen innerhalb einer Divi-Schleife; `lit/divi-dynamic-sources` zeigt sie je Knoten.
* Divi-Freigabe je Fähigkeit statt pauschaler Sperre; neue Guides.
* Sicherheit (Audit der Etappe): Schleifen-Optionen werden gegen die Art jeder Schleife der Vorfahrenkette geprüft; Schleifen über Benutzer oder private Beiträge brauchen list_users bzw. read_private_posts; Wiederherstellen prüft betroffene Seiten; gemeinsame, atomare Sperre für Farben und Theme-Optionen; Schriften-Abruf nur mit cURL und auf die geprüfte Adresse gepinnt (DNS-Rebinding); Bild-Variablen können die :root-Regel nicht mehr verlassen.
= 0.6.1 =
* Divi 5.14.0 geprüft und freigegeben (Referenz von SyncToServerController::update() nachgezogen; die Builder-Kennzeichen werden unverändert gesetzt).
* Admin: Gruppenschalter im Reiter „Tools“ wirken sofort sichtbar; Protokollfilter auch auf Telefonen; „Protokoll leeren“ nur bei Einträgen und mit Anzahl; Hinweis zur Divi-Prüfung; Rückfrage vor dem Aussperren im Reiter „Zugriff“.
+1 -1
View File
@@ -45,7 +45,7 @@ defined('ABSPATH') || exit;
*/
final class Plugin
{
public const VERSION = '0.6.1';
public const VERSION = '0.7.0';
private static string $pluginFile = '';
private static ?SettingsPage $settingsPage = null;
+1 -1
View File
@@ -3,7 +3,7 @@
/**
* Plugin Name: WP-LIT-MCP
* Description: MCP-Server für WordPress, Divi 5 und Pods – mit OAuth für KI-Assistenten.
* Version: 0.6.1
* Version: 0.7.0
* Requires at least: 6.9
* Requires PHP: 8.1
* Tested up to: 7.1