feat(cache): Tool lit/cache-clear zum gezielten Leeren des Caches

lit/cache-clear leert den Seiten-Cache von WP Super Cache für die ganze Website (scope all, Recht manage_options) oder einen Beitrag (scope post, Recht edit_post); Probelauf ohne confirm, Ausführen mit confirm: true. Das CapabilityGate sperrt das Tool, wenn WP Super Cache bricht; eine Sperre zur Laufzeit wird als Fehler gemeldet. Listener und Tool teilen die 30-s-Drosselung mit Nachlauf (SuperCachePurger); der Listener ignoriert die Einträge des Tools. Behoben vor dem Commit: die Verdrahtung des Purgers erfasste die Registry zu früh (immer gesperrt), jetzt per Referenz und mit Test über Plugin::integrations().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jan-Niclas Loosen
2026-11-06 19:05:21 +01:00
co-authored by Claude Opus 5.5
parent d3e5d4fac0
commit 1ac347e76f
12 changed files with 883 additions and 86 deletions
@@ -11,30 +11,37 @@ use LIT\MCP\Integrations\Bootable;
use LIT\MCP\Integrations\Integration;
use LIT\MCP\Integrations\SuperCache\SuperCacheCompatibility;
use LIT\MCP\Integrations\SuperCache\SuperCacheIntegration;
use LIT\MCP\Integrations\SuperCache\SuperCachePurger;
use LIT\MCP\Tests\Support\FakeChangeLog;
use LIT\MCP\Tests\Unit\TestCase;
final class SuperCacheIntegrationTest extends TestCase
{
public function testIsAnIntegrationWithoutAbilitiesThatProvidesItsProfile(): void
private static function purger(): SuperCachePurger
{
$integration = new SuperCacheIntegration();
return new SuperCachePurger(static fn (): bool => true);
}
public function testIsAnIntegrationThatProvidesItsProfileAndTheCacheClearTool(): void
{
$integration = new SuperCacheIntegration(null, self::purger(), FakeChangeLog::forbidden());
self::assertInstanceOf(Integration::class, $integration);
self::assertInstanceOf(ProvidesCompatibility::class, $integration);
self::assertSame('wpsc', $integration->id());
self::assertSame('WP Super Cache', $integration->label());
self::assertSame([], $integration->abilities());
self::assertEquals(['lit/cache-clear'], array_map(static fn ($a): string => $a->name(), $integration->abilities()));
self::assertEquals([SuperCacheCompatibility::profile()], $integration->compatibilities());
}
public function testIsAvailableOnlyWithSuperCache(): void
{
self::assertSame(defined('WPCACHEHOME'), (new SuperCacheIntegration())->isAvailable());
self::assertSame(defined('WPCACHEHOME'), (new SuperCacheIntegration(null, self::purger(), FakeChangeLog::forbidden()))->isAvailable());
}
public function testBootHooksTheOrphanCleanupIntoTheProfileLoad(): void
{
$integration = new SuperCacheIntegration();
$integration = new SuperCacheIntegration(null, self::purger(), FakeChangeLog::forbidden());
$integration->boot();
self::assertInstanceOf(Bootable::class, $integration);
@@ -45,11 +52,11 @@ final class SuperCacheIntegrationTest extends TestCase
{
Functions\expect('get_posts')->never();
Functions\when('current_user_can')->justReturn(true);
(new SuperCacheIntegration(static fn (): bool => true))->removeOrphans('pods');
(new SuperCacheIntegration(static fn (): bool => false))->removeOrphans('wpsc');
(new SuperCacheIntegration(static fn (): bool => true, self::purger(), FakeChangeLog::forbidden()))->removeOrphans('pods');
(new SuperCacheIntegration(static fn (): bool => false, self::purger(), FakeChangeLog::forbidden()))->removeOrphans('wpsc');
Functions\when('current_user_can')->justReturn(false);
(new SuperCacheIntegration(static fn (): bool => true))->removeOrphans('wpsc');
(new SuperCacheIntegration(static fn (): bool => true, self::purger(), FakeChangeLog::forbidden()))->removeOrphans('wpsc');
$this->addToAssertionCount(1);
}
@@ -63,6 +70,6 @@ final class SuperCacheIntegrationTest extends TestCase
return [];
});
(new SuperCacheIntegration(static fn (): bool => true))->removeOrphans('wpsc');
(new SuperCacheIntegration(static fn (): bool => true, self::purger(), FakeChangeLog::forbidden()))->removeOrphans('wpsc');
}
}