feat: lit/divi-preset-get – Preset mit Einstellungen und Fundstellen lesen
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
cc20100cbc
commit
341782a34f
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Integrations\Divi\Design;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use LIT\MCP\Abilities\Ability;
|
||||
use LIT\MCP\Abilities\Annotations;
|
||||
use LIT\MCP\Abilities\Errors;
|
||||
use LIT\MCP\Abilities\JsonMap;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\AttrMap;
|
||||
use LIT\MCP\Integrations\Divi\Library\GlobalUsages;
|
||||
use LIT\MCP\Integrations\Divi\Schema\ShortformMap;
|
||||
use WP_Error;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* lit/divi-preset-get (spec §6.2): one module or option group preset with its settings – short form where the
|
||||
* module's short form reaches them, the full form as attribute path => value like lit/divi-node-get –, its nested
|
||||
* group presets with names, the posts that use it (readable ones by title, the rest as a count) and the design_rev
|
||||
* for a following lit/divi-presets-set.
|
||||
*/
|
||||
final class DiviPresetGetAbility implements Ability
|
||||
{
|
||||
public function __construct(private DesignSystemWriter $writer, private GlobalUsages $usages)
|
||||
{
|
||||
}
|
||||
|
||||
public function name(): string
|
||||
{
|
||||
return 'lit/divi-preset-get';
|
||||
}
|
||||
|
||||
public function label(): string
|
||||
{
|
||||
return 'Divi-Preset lesen';
|
||||
}
|
||||
|
||||
public function description(): string
|
||||
{
|
||||
return 'Liest ein Modul-Preset (module, z. B. "button") oder Gruppen-Preset (group, z. B. "font-body") mit '
|
||||
. 'seinen Einstellungen (set in Kurzform, attrs als Attributpfad → Wert), verschachtelten Gruppen-Presets, '
|
||||
. 'den Seiten, die es verwenden (usage), und der design_rev für lit/divi-presets-set. preset = Name oder '
|
||||
. 'ID aus lit/divi-design-system (direkt: lit-divi-design-system).';
|
||||
}
|
||||
|
||||
public function inputSchema(): array
|
||||
{
|
||||
return [
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'module' => ['type' => 'string', 'description' => 'Modul, z. B. "button" (Modul-Preset).'],
|
||||
'group' => ['type' => 'string', 'description' => 'Gruppe, z. B. "font-body" (Gruppen-Preset).'],
|
||||
'preset' => ['type' => 'string', 'description' => 'Name oder ID des Presets.'],
|
||||
],
|
||||
'required' => ['preset'],
|
||||
'additionalProperties' => false,
|
||||
];
|
||||
}
|
||||
|
||||
public function outputSchema(): ?array
|
||||
{
|
||||
return [
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'id' => ['type' => 'string'],
|
||||
'name' => ['type' => 'string'],
|
||||
'kind' => ['type' => 'string'],
|
||||
'scope' => ['type' => 'string'],
|
||||
'default' => ['type' => 'boolean'],
|
||||
'module_name' => ['type' => 'string'],
|
||||
'group_id' => ['type' => ['string', 'null']],
|
||||
'set' => ['type' => 'object'],
|
||||
'attrs' => ['type' => 'object'],
|
||||
'group_presets' => ['type' => 'array', 'items' => ['type' => 'object']],
|
||||
'usage' => ['type' => 'object'],
|
||||
'design_rev' => ['type' => 'string'],
|
||||
],
|
||||
'required' => ['id', 'name', 'kind', 'scope', 'default', 'module_name', 'group_id', 'set', 'attrs',
|
||||
'group_presets', 'usage', 'design_rev'],
|
||||
];
|
||||
}
|
||||
|
||||
public function annotations(): array
|
||||
{
|
||||
return Annotations::read();
|
||||
}
|
||||
|
||||
public function isDirect(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function permission(array $input): bool|WP_Error
|
||||
{
|
||||
return current_user_can('edit_posts')
|
||||
? true
|
||||
: Errors::forbidden('Presets lesen erfordert das Recht, Beiträge zu bearbeiten.');
|
||||
}
|
||||
|
||||
public function execute(array $input): mixed
|
||||
{
|
||||
try {
|
||||
$scope = PresetScope::fromInput($input, 'input');
|
||||
} catch (InvalidArgumentException $e) {
|
||||
return Errors::invalidInput('Modul oder Gruppe fehlt bzw. ist ungültig.', ['module' => $e->getMessage()]);
|
||||
}
|
||||
|
||||
$book = PresetBook::fromDivi($this->writer->presets());
|
||||
$wanted = is_string($input['preset'] ?? null) ? $input['preset'] : '';
|
||||
try {
|
||||
$item = $book->find($scope, $wanted);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
return Errors::invalidInput('Der Preset-Name ist mehrdeutig.', ['preset' => $e->getMessage()]);
|
||||
}
|
||||
if ($item === null) {
|
||||
return Errors::notFound(
|
||||
sprintf('%s „%s“ gibt es nicht.', $scope->label(), $wanted),
|
||||
'Vorhandene Presets mit lit/divi-design-system (direkt: lit-divi-design-system) und module auflisten.'
|
||||
);
|
||||
}
|
||||
|
||||
$id = (string) $item['id'];
|
||||
$isDefault = $book->defaultId($scope) === $id;
|
||||
$attrs = is_array($item['attrs'] ?? null) ? $item['attrs'] : [];
|
||||
$module = is_string($item['moduleName'] ?? null) ? $item['moduleName'] : $scope->name;
|
||||
$usage = $this->usages->reportFor(
|
||||
new PresetUsageQuery([['scope' => $scope, 'id' => $id, 'default' => $isDefault]]),
|
||||
false
|
||||
);
|
||||
|
||||
return [
|
||||
'id' => $id,
|
||||
'name' => (string) ($item['name'] ?? $id),
|
||||
'kind' => $scope->kind,
|
||||
'scope' => $scope->name,
|
||||
'default' => $isDefault,
|
||||
'module_name' => $module,
|
||||
'group_id' => is_string($item['groupId'] ?? null) ? $item['groupId'] : null,
|
||||
'set' => JsonMap::of(ShortformMap::values(substr($module, (int) strpos($module, '/') + 1), $attrs)),
|
||||
'attrs' => JsonMap::of(AttrMap::flatten($attrs)),
|
||||
'group_presets' => $this->nested($book, $item),
|
||||
'usage' => $usage->listing(),
|
||||
'design_rev' => $book->rev(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $item
|
||||
* @return list<array{group_id: string, group_name: string, presets: list<array{id: string, name: string}>}>
|
||||
*/
|
||||
private function nested(PresetBook $book, array $item): array
|
||||
{
|
||||
$rows = [];
|
||||
foreach (is_array($item['groupPresets'] ?? null) ? $item['groupPresets'] : [] as $groupId => $nested) {
|
||||
$groupName = is_array($nested) && is_string($nested['groupName'] ?? null) ? $nested['groupName'] : '';
|
||||
$presets = [];
|
||||
foreach (is_array($nested) ? (array) ($nested['presetId'] ?? []) : [] as $presetId) {
|
||||
$found = $book->items(new PresetScope(PresetScope::GROUP, $groupName))[(string) $presetId] ?? null;
|
||||
$presets[] = ['id' => (string) $presetId, 'name' => (string) ($found['name'] ?? $presetId)];
|
||||
}
|
||||
$rows[] = ['group_id' => (string) $groupId, 'group_name' => $groupName, 'presets' => $presets];
|
||||
}
|
||||
|
||||
return $rows;
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,9 @@ use Closure;
|
||||
use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\Parser;
|
||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
|
||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemWriter;
|
||||
use LIT\MCP\Integrations\Divi\Design\DiviDesignSystemAbility;
|
||||
use LIT\MCP\Integrations\Divi\Design\DiviPresetGetAbility;
|
||||
use LIT\MCP\Integrations\Divi\Library\DiviLibraryStore;
|
||||
use LIT\MCP\Integrations\Divi\Library\DiviRoles;
|
||||
use LIT\MCP\Integrations\Divi\Library\GlobalEdits;
|
||||
@@ -57,6 +59,7 @@ final class DiviIntegration implements Integration
|
||||
private DesignSystemReader $design;
|
||||
private LibraryAccess $access;
|
||||
private ThemeBuilderAccess $themeBuilderAccess;
|
||||
private DesignSystemWriter $designWriter;
|
||||
|
||||
/**
|
||||
* @param (Closure(): bool)|null $libraryWritable Tools-tab gate for writes to library entries
|
||||
@@ -84,6 +87,7 @@ final class DiviIntegration implements Integration
|
||||
) {
|
||||
$this->modules = new DiviModules();
|
||||
$this->design = new DesignSystemReader();
|
||||
$this->designWriter = new DesignSystemWriter();
|
||||
$roles = new DiviRoles();
|
||||
$this->access = new LibraryAccess(new DiviLibraryStore(), $roles, $libraryWritable, $libraryVisible);
|
||||
$this->themeBuilderAccess = new ThemeBuilderAccess(
|
||||
@@ -150,6 +154,7 @@ final class DiviIntegration implements Integration
|
||||
new DiviReplaceTextAbility($this->schema, $loader, $writer),
|
||||
new DiviNodeCopyAbility($writer, $loader, $this->diviWritable, $this->libraryInsertable),
|
||||
new DiviDynamicSourcesAbility($this->schema, new DynamicContentMap(), $this->access->roles()),
|
||||
new DiviPresetGetAbility($this->designWriter, $this->globalUsages()),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user