feat: Divi tools write library entries; global ones with dry run, confirm and backup (E2, F2)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-27 01:15:58 +02:00
co-authored by Claude Opus 5.5
parent 681bb755ff
commit d66ad36c2e
23 changed files with 1066 additions and 44 deletions
+28 -13
View File
@@ -50,6 +50,9 @@ defined('ABSPATH') || exit;
* pages the bytes change for every user – reported as CHANGED_ON_SAVE. Finding R2 / rulings
* S5, S7: docs/superpowers/notes/2026-09-26-etappe-2-entscheidungen.md.
*
* SaveScope: Bibliothekseinträge bekommen keine Divi-Flags; ein globaler Eintrag leert zusätzlich den CSS-Cache
* aller Seiten und den Theme-Builder-Cache.
*
* If saving throws, the previous content is written back (WriteFailed: rolled back or not).
* Not final so abilities can be tested with a mock.
*/
@@ -64,7 +67,7 @@ class DiviSaver
* @return array{revision_id: ?int, warnings: list<string>}
* @throws WriteFailed
*/
public function save(WP_Post $post, string $content): array
public function save(WP_Post $post, string $content, SaveScope $scope = SaveScope::Page): array
{
$postId = (int) $post->ID;
$revisionId = null;
@@ -90,17 +93,27 @@ class DiviSaver
}
$warnings = [];
if ($scope->setsFlags()) {
FollowUp::run(
static fn () => DiviFlags::set($postId),
'divi builder flags',
'Die Divi-Kennzeichen der Seite konnten nicht gesetzt werden; der Inhalt ist gespeichert – die Seite '
. 'einmal im Divi-Builder öffnen und speichern.',
$warnings
);
}
FollowUp::run(
static fn () => DiviFlags::set($postId),
'divi builder flags',
'Die Divi-Kennzeichen der Seite konnten nicht gesetzt werden; der Inhalt ist gespeichert – die Seite '
. 'einmal im Divi-Builder öffnen und speichern.',
$warnings
);
FollowUp::run(
static function () use ($postId): void {
if (class_exists('ET_Core_PageResource')) {
\ET_Core_PageResource::remove_static_resources($postId, 'all', true);
static function () use ($postId, $scope): void {
if (! class_exists('ET_Core_PageResource')) {
return;
}
\ET_Core_PageResource::remove_static_resources($postId, 'all', true);
// A global library entry is part of every page that shows it (spec §5.6 step 5).
if ($scope->clearsSiteCss()) {
\ET_Core_PageResource::remove_static_resources('all', 'all', true);
if (function_exists('et_theme_builder_clear_wp_cache')) {
et_theme_builder_clear_wp_cache('all');
}
}
},
'divi static css',
@@ -128,14 +141,16 @@ class DiviSaver
* @return list<string> Warnings (CHANGED_ON_SAVE).
* @throws RuntimeException
*/
public function saveNew(int $postId, string $content): array
public function saveNew(int $postId, string $content, SaveScope $scope = SaveScope::Page): array
{
$refusal = self::refusal($this->writeContent($postId, $content));
if ($refusal !== null) {
throw new RuntimeException(sprintf('wp_update_post(%d) refused the Divi layout: %s', $postId, $refusal));
}
DiviFlags::set($postId);
if ($scope->setsFlags()) {
DiviFlags::set($postId);
}
$stored = get_post($postId);