fix: media usage check fails closed on database errors; refused deletes checked for partial state
MediaUsageFinder treats a failed query (null result or last_error) as a possible usage and an incomplete scan, so media-delete refuses without force. A refused wp_delete_attachment() is write_failed only when the attachment is intact, otherwise partial_write. media-update: re-read hint on write_failed, normalized ids in failures, documented lock resolution and kses on restore. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
This commit is contained in:
@@ -10,6 +10,7 @@ use LIT\MCP\Abilities\FollowUp;
|
||||
use LIT\MCP\Abilities\ToolResult;
|
||||
use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use WP_Error;
|
||||
use WP_Post;
|
||||
|
||||
/**
|
||||
* lit/media-delete: deletes one attachment after confirmation. WordPress has no media trash by
|
||||
@@ -123,8 +124,9 @@ final class MediaDeleteAbility implements Ability
|
||||
);
|
||||
}
|
||||
|
||||
$file = (string) get_post_meta($id, '_wp_attached_file', true);
|
||||
if (! wp_delete_attachment($id, false)) {
|
||||
return Errors::writeFailed(sprintf('WordPress hat das Löschen von Medium %d abgelehnt.', $id));
|
||||
return $this->refused($id, $title, $file);
|
||||
}
|
||||
|
||||
$warnings = [];
|
||||
@@ -145,6 +147,40 @@ final class MediaDeleteAbility implements Ability
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* wp_delete_attachment() returned false/null. It deletes meta, terms and the row before the
|
||||
* files, so a failure can leave half a deletion: only an attachment that is still there with
|
||||
* its file reference intact counts as "nothing deleted".
|
||||
*/
|
||||
private function refused(int $id, string $title, string $file): WP_Error
|
||||
{
|
||||
$reason = sprintf('WordPress hat das Löschen von Medium %d abgelehnt.', $id);
|
||||
$current = get_post($id);
|
||||
$intact = $current instanceof WP_Post
|
||||
&& $current->post_type === 'attachment'
|
||||
&& (string) get_post_meta($id, '_wp_attached_file', true) === $file;
|
||||
if ($intact) {
|
||||
return Errors::writeFailed($reason);
|
||||
}
|
||||
|
||||
$this->log->recordPartial(
|
||||
$this->name(),
|
||||
'attachment',
|
||||
(string) $id,
|
||||
sprintf('Medium "%s": Löschen nur teilweise ausgeführt', $title)
|
||||
);
|
||||
|
||||
return Errors::partialWrite(
|
||||
$reason,
|
||||
null,
|
||||
null,
|
||||
sprintf('Medium %d ist möglicherweise teilweise gelöscht (Daten oder Dateien fehlen).', $id),
|
||||
'Den Aufruf nicht einfach wiederholen. Das Medium mit lit/media-get bzw. in der WordPress-Mediathek '
|
||||
. 'prüfen und dem Nutzer Bescheid geben.',
|
||||
['attachment_id' => $id]
|
||||
);
|
||||
}
|
||||
|
||||
/** @param list<array<string, mixed>> $usages */
|
||||
private function question(int $id, string $title, bool $trash, array $usages): string
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user