diff --git a/docs/guides/theme-builder.md b/docs/guides/theme-builder.md index f6475bf..1e7e5f4 100644 --- a/docs/guides/theme-builder.md +++ b/docs/guides/theme-builder.md @@ -13,7 +13,8 @@ Kopf- und Fußzeile heißen „global“, weil andere Vorlagen sie mitbenutzen. Nutzer fragen → dieselbe Anfrage mit `confirm: true`. - Auch alles andere, was Besucher sofort sähen, ist zuerst ein Probelauf (`confirm_required`) und braucht `confirm: true`: Bedingungen einer aktiven Vorlage ändern (`lit/tb-assign`) und ein Layout ändern, das eine - aktive Vorlage zeigt (die `lit-divi-…`-Werkzeuge; die Antwort nennt die Vorlagen unter `templates`). Vor dem + aktive Vorlage zeigt (die `lit-divi-…`-Werkzeuge; die Antwort nennt die Vorlagen unter `templates`, solche + ohne Berechtigung nur als Anzahl `hidden_templates`). Vor dem Speichern eines sichtbaren Layouts entsteht eine Revision; sind Revisionen abgeschaltet, eine Sicherungskopie im Papierkorb (`backup_id`). - `lit/divi-replace-text` ändert sichtbare Layouts nicht; solche Änderungen mit `lit-divi-update` und @@ -85,7 +86,8 @@ bleiben die Felder ungeprüft (die Antwort sagt das). Kopf- und Fußzeile werden - Divi → Rollen-Editor: „Theme Builder“ – standardmäßig nur für Administratoren. - Fehlt eines davon, gibt es für dieses Konto keine Vorlagen und Layouts (`not_found` wie bei einer unbekannten ID bzw. `forbidden`). Vorlagen, die das Konto nicht bearbeiten darf, erscheinen nirgends; aktive davon nur als - Anzahl (`hidden_live` in `lit/tb-list`, `hidden_overlaps` im Probelauf). + Anzahl (`hidden_live` in `lit/tb-list`, `hidden_overlaps` im Probelauf, `hidden_templates` beim Ändern eines + Layouts). - Einstellungen → LIT MCP → Tools: Gruppe „Divi Theme Builder“ auf „nur lesen“ sperrt jedes Schreiben, auch über die `lit-divi-…`-Werkzeuge; deaktiviert gibt es keine Vorlagen und Layouts. diff --git a/docs/superpowers/notes/2026-09-27-etappe-3-entscheidungen-entwurf.md b/docs/superpowers/notes/2026-09-27-etappe-3-entscheidungen-entwurf.md index 11feafb..e1ac5c6 100644 --- a/docs/superpowers/notes/2026-09-27-etappe-3-entscheidungen-entwurf.md +++ b/docs/superpowers/notes/2026-09-27-etappe-3-entscheidungen-entwurf.md @@ -242,8 +242,8 @@ Rulings Q1–Q25: `.superpowers/sdd/2026-09-27-etappe-3b-theme-builder/progress. - E3 für den Theme Builder: `edit_others_posts`, `edit_theme_options` (Q15) und Divis Rollen-Recht „Theme Builder“, je Vorlage/Layout `edit_post`, zum Anlegen die Veröffentlichen-Rechte. Nicht bearbeitbare Vorlagen antworten wie fehlende (Q18); aktive davon nur als Anzahl in Liste und Probeläufen - von `lit/tb-assign`/`lit/tb-activate` (Q21; für die Probeläufe der Layout-Änderungen folgt Q22 in der - Schlussrunde). + von `lit/tb-assign`/`lit/tb-activate` (Q21) und der Layout-Änderungen (`hidden_templates`; die Rückfrage + gilt trotzdem für alle aktiven Vorlagen, Q22). - Bedingungen nur aus Divis Katalog; Objekte lesbar (Begriffe: `assign_term`); strenger als Divi: Autoren-Bedingungen (`archive:user:id:`) nur mit `list_users` (Q10). - E9: eigene Gruppe „Divi Theme Builder“ (`divi-theme-builder`); alle neuen Tools indirekt, 22 direkte Tools. diff --git a/src/Integrations/Divi/Pages/DiviReplaceTextAbility.php b/src/Integrations/Divi/Pages/DiviReplaceTextAbility.php index 7edb026..4d69fab 100644 --- a/src/Integrations/Divi/Pages/DiviReplaceTextAbility.php +++ b/src/Integrations/Divi/Pages/DiviReplaceTextAbility.php @@ -406,7 +406,7 @@ final class DiviReplaceTextAbility implements Ability 'error' => Errors::clientMessage($error) . ' Sichtbare Theme-Builder-Layouts nicht mit ' . 'lit/divi-replace-text, sondern nach Rückfrage mit lit-divi-update (confirm: true) ändern.', 'templates' => $data['templates'], - ]; + ] + (isset($data['hidden_templates']) ? ['hidden_templates' => $data['hidden_templates']] : []); } return [ diff --git a/src/Integrations/Divi/Pages/DiviWriteAbility.php b/src/Integrations/Divi/Pages/DiviWriteAbility.php index db031ca..22f331f 100644 --- a/src/Integrations/Divi/Pages/DiviWriteAbility.php +++ b/src/Integrations/Divi/Pages/DiviWriteAbility.php @@ -41,8 +41,10 @@ abstract class DiviWriteAbility implements Ability 'affected_count' => ['type' => 'integer'], 'hidden_count' => ['type' => 'integer'], 'backup_id' => ['type' => 'integer'], - // Theme Builder layouts: the enabled templates that show the layout. + // Theme Builder layouts: the enabled templates that show the layout – those the user may edit; the + // others only as a count (ruling Q22). 'templates' => ['type' => 'array', 'items' => ['type' => 'object']], + 'hidden_templates' => ['type' => 'integer'], ], ['tree_rev']); } diff --git a/src/Integrations/Divi/Pages/DiviWriter.php b/src/Integrations/Divi/Pages/DiviWriter.php index c3ca304..09850db 100644 --- a/src/Integrations/Divi/Pages/DiviWriter.php +++ b/src/Integrations/Divi/Pages/DiviWriter.php @@ -218,22 +218,45 @@ final class DiviWriter return $this->save($ability, $page, $change, $input, SaveScope::ThemeBuilderLayout); } - // E12: fields in a body checked against the templates' post types – warnings only, also in the dry run. - $fieldWarnings = $this->themeBuilder->fieldWarnings($page, $change); + // E12: fields in a body checked against the templates' post types – warnings only, also in the dry run + // and in any refusal (review M-12 a). The live templates are read once for both checks. + $live = $this->themeBuilder->live(); + $fieldWarnings = $this->themeBuilder->fieldWarnings($page, $change, $live); foreach ($fieldWarnings as $warning) { $change->warning($warning); } - $prepared = $this->themeBuilder->prepare($page, $input); + $prepared = $this->themeBuilder->prepare($page, $input, $live); if ($prepared instanceof WP_Error) { - return $fieldWarnings !== [] && Errors::codeOf($prepared) === 'confirm_required' - ? VisibleEdits::merged($prepared, 'Hinweise zu Feldern siehe warnings.', ['warnings' => $fieldWarnings]) - : $prepared; + return $fieldWarnings === [] ? $prepared : self::withWarnings($prepared, $fieldWarnings); } return $this->savePrepared($ability, $page, $change, $input, $prepared, 'des Theme-Builder-Layouts'); } + /** + * $error with the field warnings of the change (key warnings): a confirm_required also says so in its message. + * + * @param list $warnings + */ + private static function withWarnings(WP_Error $error, array $warnings): WP_Error + { + if (Errors::codeOf($error) === 'confirm_required') { + return VisibleEdits::merged($error, 'Hinweise zu Feldern siehe warnings.', ['warnings' => $warnings]); + } + + $data = $error->get_error_data(); + $data = is_array($data) ? $data : []; + + return Errors::make( + Errors::codeOf($error), + Errors::clientMessage($error), + (string) ($data['hint'] ?? ''), + (int) ($data['status'] ?? 400), + array_merge(array_diff_key($data, ['status' => true, 'hint' => true]), ['warnings' => $warnings]) + ); + } + /** * save() with the scope GlobalEdits/ThemeBuilderEdits prepared; their details join the result, and a * failure after their backup names it (ruling P14, VisibleEdits). $entry names the entry in that error. diff --git a/src/Integrations/Divi/ThemeBuilder/ThemeBuilderEdits.php b/src/Integrations/Divi/ThemeBuilder/ThemeBuilderEdits.php index f6d967d..3eb0d14 100644 --- a/src/Integrations/Divi/ThemeBuilder/ThemeBuilderEdits.php +++ b/src/Integrations/Divi/ThemeBuilder/ThemeBuilderEdits.php @@ -21,8 +21,10 @@ defined('ABSPATH') || exit; * ausdrücklicher Freigabe"): Divi reads TB layouts live (F22), so a layout that a live template (attached to the * live Theme Builder and enabled, whatever its post status – ruling Q8) shows changes the website at once – * without confirm: true nothing is saved and the answer lists those templates (dry run of the fully validated - * change, like global modules, answer F2; ruling Q9). A confirmed edit gets the restore point of every visible - * change (VisibleEdits, ruling Q2): a backup when revisions are off, refused when it could not be faithful (P9). + * change, like global modules, answer F2; ruling Q9) – by name only those the user may edit, the others as the + * count hidden_templates; confirm is decided on all of them (ruling Q22). A confirmed edit gets the restore point + * of every visible change (VisibleEdits, ruling Q2): a backup when revisions are off, refused when it could not be + * faithful (P9). * Layouts of disabled or detached templates save at once. The save scope sets the Divi flags and clears every * page's CSS and the Theme Builder cache. * @@ -39,28 +41,49 @@ final class ThemeBuilderEdits ) { } - /** @return list