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

118 lines
4.1 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\ToolResult;
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
use LIT\MCP\Integrations\Divi\Release\FeatureSets;
use LIT\MCP\Integrations\Divi\Release\RequiresDiviFeatures;
use WP_Error;
defined('ABSPATH') || exit;
/**
* The frame of the Divi write tools (spec §5.6): permission and execute both load the page
* through DiviWriter::page() (rights, Divi layout, tree_rev lock – execute never trusts state
* from permission), the tool changes the tree in change() – only when its whole input
* validated, all or nothing (ruling S39) – and DiviWriter::commit() stores it (library entries:
* GlobalEdits) and builds the result. The composition is bound to the page (DiviWriter::composition(), ruling S22).
*/
abstract class DiviWriteAbility implements Ability, RequiresDiviFeatures
{
public function __construct(protected DiviWriter $writer)
{
}
/**
* Changes the tree of $page, or returns why nothing is written. Client values enter the
* tree only through $composition (Composer / TreeEditor).
*
* @param array<string, mixed> $input
*/
abstract protected function change(DiviPage $page, array $input, DiviComposition $composition): DiviChange|WP_Error;
/**
* What the tool needs whatever entry it changes; diviFeatures() adds what the entry post_id names (a library
* entry or Theme Builder layout is saved with its own capability, D5).
*
* @return list<DiviFeature>
*/
abstract protected function baseFeatures(): array;
public function diviFeatures(array $input): array
{
return FeatureSets::merge($this->baseFeatures(), FeatureSets::ofEntry($input['post_id'] ?? null, true));
}
public function outputSchema(): ?array
{
return ToolResult::schema([
'tree_rev' => ['type' => 'string'],
// Global library entries (answer F2): the pages that show the entry, and the backup
// made when revisions are off (also for live Theme Builder layouts, ruling Q2).
'affected' => ['type' => 'array', 'items' => ['type' => 'object']],
'affected_count' => ['type' => 'integer'],
'hidden_count' => ['type' => 'integer'],
'backup_id' => ['type' => 'integer'],
// Library entries and Theme Builder layouts: their revision in WordPress' revision screen (audit L3 –
// lit/revision-restore takes only content types).
'restore_url' => ['type' => 'string'],
// Theme Builder layouts: the enabled templates that show the layout – those the user may edit; the
// others only as a count (ruling Q22).
'templates' => ['type' => 'array', 'items' => ['type' => 'object']],
'hidden_templates' => ['type' => 'integer'],
], ['tree_rev']);
}
public function isDirect(): bool
{
return true;
}
final public function permission(array $input): bool|WP_Error
{
$refusal = $this->precheck($input);
if ($refusal !== null) {
return $refusal;
}
$page = $this->writer->page($input);
return $page instanceof WP_Error ? $page : true;
}
final public function execute(array $input): mixed
{
$refusal = $this->precheck($input);
if ($refusal !== null) {
return $refusal;
}
$page = $this->writer->page($input);
if ($page instanceof WP_Error) {
return $page;
}
$change = $this->change($page, $input, $this->writer->composition($page));
if ($change instanceof WP_Error) {
return $this->writer->notice($page, $change);
}
return $this->writer->commit($this->name(), $page, $change, $input);
}
/**
* Checks of a tool beyond the page (rights and Tools-tab gates of another group) – run in
* permission() and again in execute(). Null = none.
*
* @param array<string, mixed> $input
*/
protected function precheck(array $input): ?WP_Error
{
return null;
}
}