Files
WP-LIT-MCP/src/Integrations/WordPress/PostSaveFollowUp.php
T
janniclas.loosenandClaude Opus 5.5 b24eb6c3e9 fix(security): no direct HTTP access to plugin PHP files (audit L2, cheap part)
Every file under src/ exits outside WordPress (defined('ABSPATH') ||
exit; after the use block, so a direct request no longer prints a fatal
error with the server path); divi-convert-fixture.php gets the WP_CLI
guard the other integration scripts have. A unit test keeps both true;
PSR1 side-effects warning excluded for the guard.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 19:32:12 +02:00

92 lines
2.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\WordPress;
use LIT\MCP\Abilities\FollowUp;
use LIT\MCP\Abilities\Rev;
use LIT\MCP\Abilities\ToolResult;
use LIT\MCP\ChangeLog\ChangeLog;
use WP_Post;
defined('ABSPATH') || exit;
/**
* What every post tool does once its write is saved: fire lit_mcp_after_save, re-read the
* post, write the change log and build the ToolResult with the new rev. From here on a
* failure must not turn the saved change into an error – listener and log failures are
* logged and reported as warnings ("… ist gespeichert").
*/
final class PostSaveFollowUp
{
/** @var list<string> */
private array $warnings;
private ?int $logId = null;
/**
* @param string $saved What is saved, for the warnings, e.g. "die Änderung", "der Entwurf".
* @param list<string> $warnings Warnings collected before the write.
*/
public function __construct(
private string $ability,
private ChangeLog $log,
private int $postId,
private string $saved = 'die Änderung',
array $warnings = []
) {
$this->warnings = $warnings;
}
/**
* @param array<string, mixed> $input
* @param string $after The step just done, e.g. "Speichern", "Veröffentlichen".
*/
public function afterSave(array $input, string $after = 'Speichern'): self
{
FollowUp::run(
fn () => do_action('lit_mcp_after_save', $this->postId, $this->ability, $input),
$this->ability . ' lit_mcp_after_save',
sprintf(
'Eine Erweiterung ist nach dem %s auf einen Fehler gestoßen; %s ist gespeichert.',
$after,
$this->saved
),
$this->warnings
);
return $this;
}
/** The saved post as stored now; $fallback when it cannot be read. */
public function reread(?WP_Post $fallback = null): ?WP_Post
{
$post = get_post($this->postId);
return $post instanceof WP_Post ? $post : $fallback;
}
public function log(string $objectType, string $summary, ?int $revisionId = null): self
{
$logId = FollowUp::run(
fn () => $this->log->record($this->ability, $objectType, (string) $this->postId, $summary, $revisionId),
$this->ability . ' change log',
sprintf('Änderungsprotokoll konnte nicht geschrieben werden; %s ist gespeichert.', $this->saved),
$this->warnings
);
$this->logId = is_int($logId) ? $logId : null;
return $this;
}
/** Result with the rev of $post, the log id and all warnings; callers add changed, urls, … */
public function result(string $summary, ?WP_Post $post): ToolResult
{
return ToolResult::ok($summary)
->rev($post instanceof WP_Post ? Rev::ofPost($post) : null)
->logId($this->logId)
->warnings($this->warnings);
}
}