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:
co-authored by
Claude Sonnet 5.5
parent
1fdcb2e075
commit
b91c356a28
@@ -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).*
|
||||
Reference in New Issue
Block a user