refactor: small Divi tree helpers out of DiviWriter (M3)
Block::isPlaceholder replaces the divi/placeholder literals (ledger T4); NodeIndex::parentBlock/sectionLabel replace the two parentBlock copies and DiviWriter::sectionLabel; DiviChange::idOf and Outline::summary replace the duplicated id resolution and outline text; DiviSchema holds the shared input properties. Behaviour unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
This commit is contained in:
@@ -9,9 +9,7 @@ use LIT\MCP\Abilities\Rev;
|
||||
use LIT\MCP\Abilities\ToolResult;
|
||||
use LIT\MCP\Abilities\WriteFailed;
|
||||
use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\Block;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\NodeIndex;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\NodeSummary;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\Outline;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\Serializer;
|
||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
|
||||
@@ -40,33 +38,6 @@ class DiviWriter
|
||||
) {
|
||||
}
|
||||
|
||||
/** @return array<string, array<string, mixed>> post_id and tree_rev of every Divi write. */
|
||||
public static function inputProperties(): array
|
||||
{
|
||||
return [
|
||||
'post_id' => ['type' => 'integer', 'minimum' => 1],
|
||||
'tree_rev' => [
|
||||
'type' => 'string',
|
||||
'description' => 'tree_rev aus lit-divi-outline bzw. der letzten Divi-Änderung (Pflicht).',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array<string, array<string, mixed>> Target position of insert and move. */
|
||||
public static function positionProperties(): array
|
||||
{
|
||||
return [
|
||||
'parent' => [
|
||||
'type' => 'string',
|
||||
'description' => 'Pfad-ID des Elternknotens (z. B. Spalte "s0.r0.c1"); ohne parent/before/after: '
|
||||
. 'Ende der Seite.',
|
||||
],
|
||||
'before' => ['type' => 'string', 'description' => 'Pfad-ID: vor diesem Knoten einfügen.'],
|
||||
'after' => ['type' => 'string', 'description' => 'Pfad-ID: nach diesem Knoten einfügen.'],
|
||||
'index' => ['type' => 'integer', 'minimum' => 0, 'description' => 'Position unter parent (0 = zuerst).'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The page to change, after rights, type, layout and the tree_rev lock were checked.
|
||||
*
|
||||
@@ -104,18 +75,6 @@ class DiviWriter
|
||||
return $this->composition->forPost((int) $page->post->ID);
|
||||
}
|
||||
|
||||
/** Section label around $block, for automatic admin labels ("" when none). */
|
||||
public static function sectionLabel(NodeIndex $index, ?Block $block): string
|
||||
{
|
||||
for ($node = $block; $node !== null; $node = self::parentBlock($index, $node)) {
|
||||
if ($node->name() === 'divi/section') {
|
||||
return NodeSummary::label($node);
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the changed tree of $page and returns the ToolResult array. Call it only when the
|
||||
* whole input validated – every error before means nothing is written.
|
||||
@@ -178,15 +137,16 @@ class DiviWriter
|
||||
->with('tree_rev', Rev::of((string) $updated->post_content))
|
||||
->urls((string) get_preview_post_link($updated), $page->editUrl());
|
||||
foreach ($change->entries() as $entry) {
|
||||
$id = $entry['id'] ?? ($entry['block'] !== null ? $index->idOf($entry['block']) : null);
|
||||
$tool->changed($id ?? '?', $entry['type'], $entry['action'], $entry['label']);
|
||||
$tool->changed(DiviChange::idOf($entry, $index) ?? '?', $entry['type'], $entry['action'], $entry['label']);
|
||||
}
|
||||
|
||||
return $tool->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Outline of the sections that contain changed nodes (breadth limit of ruling S18).
|
||||
* Outline of the sections that contain changed nodes (breadth limit of ruling S18). A removed
|
||||
* node has no block any more, but its ID from before the removal still names the (surviving)
|
||||
* section.
|
||||
*
|
||||
* @return array{text: ?string, truncated: bool}
|
||||
*/
|
||||
@@ -194,9 +154,7 @@ class DiviWriter
|
||||
{
|
||||
$sections = [];
|
||||
foreach ($change->entries() as $entry) {
|
||||
// Same id resolution as the "changed" entries below: a removed node has no block
|
||||
// any more, but its id from before the removal still names the (surviving) section.
|
||||
$id = $entry['id'] ?? ($entry['block'] !== null ? $index->idOf($entry['block']) : null);
|
||||
$id = DiviChange::idOf($entry, $index);
|
||||
if ($id !== null) {
|
||||
$sections[explode('.', $id)[0]] = true;
|
||||
}
|
||||
@@ -207,20 +165,7 @@ class DiviWriter
|
||||
}
|
||||
|
||||
$outline = new Outline($this->design->read()->presetNames());
|
||||
$texts = [];
|
||||
$truncated = false;
|
||||
foreach (array_keys($sections) as $sectionId) {
|
||||
$texts[] = $outline->text($outline->rows($index, (string) $sectionId));
|
||||
$truncated = $truncated || $outline->wasTruncated();
|
||||
}
|
||||
|
||||
return ['text' => implode("\n", $texts), 'truncated' => $truncated];
|
||||
}
|
||||
|
||||
private static function parentBlock(NodeIndex $index, Block $block): ?Block
|
||||
{
|
||||
$parent = $index->parentOf($block);
|
||||
|
||||
return $parent instanceof Block && $parent->name() !== 'divi/placeholder' ? $parent : null;
|
||||
return $outline->summary($index, array_map('strval', array_keys($sections)));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user