feat: Divi save pipeline – tree_rev lock, kses-safe save, revision, flags, cache, ToolResult

DiviSaver/DiviWriter/DiviComposition/DiviChange, WpValueSanitizer (S4),
WpMediaResolver, DiviFlags (S11), DynamicContentMap from Divi's live
registry (S22), S31 wiring, S35 control strip at apply() entry.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-26 14:56:47 +02:00
co-authored by Claude Opus 5.5
parent ea1fd607b2
commit 7762b76305
20 changed files with 1716 additions and 2 deletions
@@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace LIT\MCP\Integrations\Divi\Pages;
use LIT\MCP\Integrations\Divi\Compose\ValueSanitizer;
/**
* WordPress sanitizing of Divi values (spec §5.6/§10). Because DiviSaver bypasses kses for the
* page as a whole (kses would re-serialize every untouched block, D7), every value this plugin
* writes goes through here instead – always via AttrWriter::cleanValue(), which also checks
* $variable(…)$ references before and after these sanitizers.
*
* Rich text and code depend on unfiltered_html like in core (ruling S4): administrators keep
* their embeds, forms and scripts; everybody else gets wp_kses_post.
*/
final class WpValueSanitizer implements ValueSanitizer
{
public function text(string $value): string
{
return sanitize_text_field($value);
}
public function html(string $value): string
{
return $this->allowsUnfilteredHtml() ? $value : wp_kses_post($value);
}
public function code(string $value): string
{
return $this->allowsUnfilteredHtml() ? $value : wp_kses_post($value);
}
public function url(string $value): string
{
return esc_url_raw(trim($value));
}
public function allowsUnfilteredHtml(): bool
{
return current_user_can('unfiltered_html');
}
}