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:
2026-09-26 02:54:37 +02:00
co-authored by Claude Opus 5.5
parent 931ddeb137
commit 7f136f6f4c
10 changed files with 238 additions and 20 deletions
@@ -102,17 +102,19 @@ final class MediaUpdateAbilityTest extends TestCase
$failures = $result->get_error_data()['failures'];
self::assertSame([1, 2, 3], array_column($failures, 'index'));
self::assertSame(['not_found', 'not_found', 'validation_failed'], array_column($failures, 'code'));
self::assertSame([99, 5, 35], array_column($failures, 'id'));
self::assertStringContainsString('nicht gefunden', $failures[0]['error']);
self::assertStringContainsString('Papierkorb', $failures[2]['error']);
self::assertSame([], $this->postUpdates);
self::assertSame([], $this->altUpdates);
}
public function testFailuresOfOneKindKeepTheirCode(): void
public function testFailuresOfOneKindKeepTheirCodeAndReportTheNormalizedId(): void
{
$result = (new MediaUpdateAbility($this->log()))->execute(['items' => [['id' => 99, 'alt' => 'x']]]);
$result = (new MediaUpdateAbility($this->log()))->execute(['items' => [['id' => '99', 'alt' => 'x']]]);
self::assertSame('lit_not_found', $result->get_error_code());
self::assertSame(99, $result->get_error_data()['failures'][0]['id']);
}
public function testRejectsEmptyDuplicateAndOverlongItems(): void
@@ -165,6 +167,7 @@ final class MediaUpdateAbilityTest extends TestCase
} catch (WriteFailed $e) {
self::assertTrue($e->rolledBack);
self::assertSame('lit_write_failed', $e->toError()->get_error_code());
self::assertStringContainsString('neu lesen', $e->toError()->get_error_data()['hint']);
self::assertStringContainsString('Datenbankfehler', $e->getMessage());
}