refactor: WriteFailed named constructors, Rollback runner, Errors read-back helpers (H6)

- WriteFailed::rolledBack()/partial() replace the 11-parameter constructor (now
  private); the hint/state of either error are plain $hint/$state.
- Rollback::attempt(...steps) runs every undo step and collects failure messages;
  used by ContentCreate::discard, ContentUpdate::rollBack, MediaUpdate::rollBack and
  DiviSaver::restore.
- Errors::clientMessage/codeOf/fieldsOf replace DiviReplaceTextAbility::reason,
  the JSON digging in MediaUpdateAbility::failure and ContentCreateAbility::fields.
- Errors docblock documents the exception/WP_Error split.
- ContentCreateAbility::discard takes the client reason as a parameter (both callers
  still pass REASON_EXTRAS; changing the Divi text needs a ruling).

Error payloads unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-26 17:40:32 +02:00
co-authored by Claude Opus 5.5
parent fb6eabf80c
commit 8e5ba9eac4
23 changed files with 358 additions and 207 deletions
+33
View File
@@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace LIT\MCP\Abilities;
use Throwable;
/**
* Runs the undo steps of a failed write. Every step runs, even after an earlier one failed;
* a step fails by throwing. The caller turns the collected messages into the log detail and
* picks WriteFailed::rolledBack() (no failures) or WriteFailed::partial().
*/
final class Rollback
{
/**
* @param callable(): mixed ...$steps In the order they must run.
* @return list<string> The messages of the steps that threw, in step order. Never throws.
*/
public static function attempt(callable ...$steps): array
{
$failures = [];
foreach ($steps as $step) {
try {
$step();
} catch (Throwable $e) {
$failures[] = $e->getMessage();
}
}
return $failures;
}
}