Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
74 lines
2.1 KiB
PHP
74 lines
2.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace LIT\MCP\Integrations\Divi\BlockTree;
|
|
|
|
/**
|
|
* Turns a Document back into block markup. Unchanged blocks reuse their original
|
|
* delimiters; changed or new blocks get delimiters generated exactly like WordPress'
|
|
* get_comment_delimited_block_content() / serialize_block_attributes() do, which also
|
|
* yields the escaping Divi expects inside $variable(…)$ payloads (" → ").
|
|
*/
|
|
final class Serializer
|
|
{
|
|
/** serialize_block_attributes() replacements (WordPress 7.0). */
|
|
private const ESCAPES = [
|
|
'\\\\' => '\\u005c',
|
|
'--' => '\\u002d\\u002d',
|
|
'<' => '\\u003c',
|
|
'>' => '\\u003e',
|
|
'&' => '\\u0026',
|
|
'\\"' => '\\u0022',
|
|
];
|
|
|
|
public static function document(Document $document): string
|
|
{
|
|
return self::parts($document->parts());
|
|
}
|
|
|
|
public static function block(Block $block): string
|
|
{
|
|
$open = $block->rawOpen() ?? self::opener($block);
|
|
if ($block->isVoid()) {
|
|
return $open;
|
|
}
|
|
|
|
return $open . self::parts($block->parts()) . ($block->rawClose() ?? self::closer($block));
|
|
}
|
|
|
|
/** @param array<string, mixed> $attrs */
|
|
public static function attributes(array $attrs): string
|
|
{
|
|
return strtr(Json::encode($attrs), self::ESCAPES);
|
|
}
|
|
|
|
private static function opener(Block $block): string
|
|
{
|
|
$attrs = $block->attrs() === [] ? '' : self::attributes($block->attrs()) . ' ';
|
|
|
|
return '<!-- wp:' . self::serializedName($block->name()) . ' ' . $attrs . ($block->isVoid() ? '/-->' : '-->');
|
|
}
|
|
|
|
private static function closer(Block $block): string
|
|
{
|
|
return '<!-- /wp:' . self::serializedName($block->name()) . ' -->';
|
|
}
|
|
|
|
private static function serializedName(string $name): string
|
|
{
|
|
return str_starts_with($name, 'core/') ? substr($name, 5) : $name;
|
|
}
|
|
|
|
/** @param list<string|Block> $parts */
|
|
private static function parts(array $parts): string
|
|
{
|
|
$out = '';
|
|
foreach ($parts as $part) {
|
|
$out .= $part instanceof Block ? self::block($part) : $part;
|
|
}
|
|
|
|
return $out;
|
|
}
|
|
}
|