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 && $this->loader->libraryIdsVisible()) { $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'] ); } elseif ($global !== null) { // Ruling P13: which entry is shown stays unknown without library access (AttrMap::flatten // already leaves globalModule/globalParent out of attrs). $global = [ 'id' => null, 'block_name' => $global['block_name'], 'hint' => 'Globales Modul aus der Divi-Bibliothek – nur lesbar; dieses Konto hat keinen Zugang zur ' . 'Divi-Bibliothek.', ]; } 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, ]; } }