fix: SnapshotStore verweigert nicht kodierbare Snapshots

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
Jan-Niclas Loosen
2026-10-16 17:33:03 +02:00
co-authored by Claude Haiku 5.5
parent 5ba52b98b3
commit 6ee8f9258a
2 changed files with 26 additions and 2 deletions
@@ -38,11 +38,16 @@ class SnapshotStore
/** /**
* @param array<array-key, mixed> $data The area's raw inventory. * @param array<array-key, mixed> $data The area's raw inventory.
* @throws SnapshotTooLarge * @throws SnapshotTooLarge
* @throws RuntimeException When the option could not be written. * @throws RuntimeException When the snapshot cannot be encoded or the option could not be written.
*/ */
public function save(string $area, array $data, string $ability): string public function save(string $area, array $data, string $ability): string
{ {
$size = strlen((string) wp_json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); $json = wp_json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
if (! is_string($json)) {
throw new RuntimeException(sprintf('snapshot %s could not be encoded', $area));
}
$size = strlen($json);
if ($size > self::MAX_BYTES) { if ($size > self::MAX_BYTES) {
throw new SnapshotTooLarge($size); throw new SnapshotTooLarge($size);
} }
@@ -87,6 +87,25 @@ final class SnapshotStoreTest extends TestCase
(new SnapshotStore())->save('presets', ['a' => 1], 'lit/divi-presets-set'); (new SnapshotStore())->save('presets', ['a' => 1], 'lit/divi-presets-set');
} }
public function testAnUnencodableSnapshotIsRefusedBeforeAnyWrite(): void
{
Functions\when('wp_json_encode')->justReturn(false);
$written = false;
Functions\when('update_option')->alias(function () use (&$written): bool {
$written = true;
return true;
});
try {
(new SnapshotStore())->save('presets', ['a' => 1], 'lit/divi-presets-set');
self::fail('an unencodable snapshot must be refused');
} catch (RuntimeException $e) {
self::assertSame('snapshot presets could not be encoded', $e->getMessage());
}
self::assertFalse($written, 'nothing may be written when the snapshot cannot be encoded');
}
public function testCorruptOptionReadsAsEmpty(): void public function testCorruptOptionReadsAsEmpty(): void
{ {
$this->options['lit_mcp_snapshots_presets'] = 'kaputt'; $this->options['lit_mcp_snapshots_presets'] = 'kaputt';