Files
WP-LIT-MCP/src/Integrations/Divi/Pages/DiviNodeGetAbility.php
T

165 lines
5.9 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace LIT\MCP\Integrations\Divi\Pages;
use LIT\MCP\Abilities\Ability;
use LIT\MCP\Abilities\Annotations;
use LIT\MCP\Abilities\Errors;
use LIT\MCP\Abilities\JsonMap;
use LIT\MCP\Abilities\Rev;
use LIT\MCP\Integrations\Divi\BlockTree\AttrMap;
use LIT\MCP\Integrations\Divi\BlockTree\NodeIndex;
use LIT\MCP\Integrations\Divi\BlockTree\NodeSummary;
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
use LIT\MCP\Integrations\Divi\Schema\ShortformMap;
use WP_Error;
defined('ABSPATH') || exit;
/**
* lit/divi-node-get: all attributes of one node in the full form (spec §5.4, §5.7) –
* attribute path => breakpoint map – plus the current short-form values.
*/
final class DiviNodeGetAbility implements Ability
{
public function __construct(private DiviPageLoader $loader, private DesignSystemReader $design)
{
}
public function name(): string
{
return 'lit/divi-node-get';
}
public function label(): string
{
return 'Divi-Knoten lesen';
}
public function description(): string
{
return 'Liest einen Knoten der Divi-Seite vollständig: attrs als Attributpfad → Werte je Breakpoint '
. '(Vollform, z. B. "title.decoration.font.font": {"desktop": {"value": {…}}}), die Kurzform-Werte, '
. 'Presets und die IDs der Kinder. Pfad-IDs aus lit-divi-outline. Werte wie $variable(…)$ (globale '
. 'Farben, Variablen, dynamische Inhalte) werden unverändert angezeigt, beim Schreiben aber erneut '
. 'geprüft, nie ungeprüft übernommen.';
}
public function inputSchema(): array
{
return [
'type' => 'object',
'properties' => [
'post_id' => ['type' => 'integer', 'minimum' => 1],
'id' => ['type' => 'string', 'description' => 'Pfad-ID aus lit-divi-outline, z. B. "s0.r0.c1.m2".'],
],
'required' => ['post_id', 'id'],
'additionalProperties' => false,
];
}
public function outputSchema(): ?array
{
return [
'type' => 'object',
'properties' => [
'post_id' => ['type' => 'integer'],
'tree_rev' => ['type' => 'string'],
'rev' => ['type' => 'string'],
'id' => ['type' => 'string'],
'parent' => ['type' => ['string', 'null']],
'type' => ['type' => 'string'],
'label' => ['type' => 'string'],
'editable' => ['type' => 'boolean'],
'attrs' => ['type' => 'object'],
'shortform' => ['type' => 'object'],
'presets' => [
'type' => 'array',
'items' => [
'type' => 'object',
'properties' => ['id' => ['type' => 'string'], 'name' => ['type' => 'string']],
'required' => ['id', 'name'],
],
],
'builder_version' => ['type' => ['string', 'null']],
'children' => ['type' => 'array', 'items' => ['type' => 'string']],
'global' => ['type' => ['object', 'null']],
],
'required' => ['post_id', 'tree_rev', 'rev', 'id', 'type', 'editable', 'attrs', 'shortform', 'children'],
];
}
public function annotations(): array
{
return Annotations::read();
}
public function isDirect(): bool
{
return true;
}
public function permission(array $input): bool|WP_Error
{
$page = $this->loader->load($input['post_id'] ?? null, false);
return $page instanceof WP_Error ? $page : true;
}
public function execute(array $input): mixed
{
$page = $this->loader->load($input['post_id'] ?? null, false);
if ($page instanceof WP_Error) {
return $page;
}
$id = is_string($input['id'] ?? null) ? $input['id'] : '';
if (preg_match(NodeIndex::ID_PATTERN, $id) !== 1) {
return Errors::invalidInput('id ist keine Pfad-ID.', ['id' => 'z. B. "s0.r1.c0.m2"']);
}
$block = $page->index->find($id);
if ($block === null) {
return DiviErrors::unknownNode($id, $page->post);
}
$names = $this->design->read()->presetNames();
$editable = $block->isDivi() && ! $block->isOpaque();
$version = $block->attrs()['builderVersion'] ?? null;
$global = NodeSummary::globalRef($block);
if ($global !== null) {
$global['hint'] = sprintf(
'Globales Modul: Inhalt im Bibliothekseintrag %s bearbeiten (lit-divi-outline mit post_id %s); '
. 'jede Änderung dort wirkt auf alle Seiten mit diesem Modul.',
$global['id'],
$global['id']
);
}
return [
'post_id' => (int) $page->post->ID,
'tree_rev' => $page->treeRev(),
'rev' => Rev::ofPost($page->post),
'id' => $id,
'parent' => $page->index->parentId($block),
'type' => $block->isDivi() ? $block->shortName() : $block->name(),
'label' => NodeSummary::label($block),
'editable' => $editable,
'attrs' => JsonMap::of(AttrMap::flatten($block->attrs())),
'shortform' => JsonMap::of(ShortformMap::values($block->shortName(), $block->attrs())),
'presets' => array_map(
static fn (string $presetId): array => ['id' => $presetId, 'name' => $names[$presetId] ?? ''],
NodeSummary::presetIds($block)
),
'builder_version' => is_string($version) ? $version : null,
'children' => $editable
? array_values(array_filter(array_map([$page->index, 'idOf'], $block->children())))
: [],
'global' => $global,
];
}
}