From 50f0f98c8e7ce5e4646438428a32b68dce6e0cee Mon Sep 17 00:00:00 2001 From: Jan-Niclas Loosen Date: Sat, 26 Sep 2026 05:07:35 +0200 Subject: [PATCH] chore: uuid string guard in revoke, docblock placement, stricter schedule warning test --- src/Abilities/Rev.php | 3 ++- src/Admin/AccessTab.php | 4 +++- src/Integrations/Media/MediaUsageFinder.php | 6 +++--- tests/Unit/Admin/AccessTabTest.php | 13 +++++++++++++ .../WordPress/Status/PostScheduleAbilityTest.php | 2 +- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/Abilities/Rev.php b/src/Abilities/Rev.php index f412fbc..3a6521b 100644 --- a/src/Abilities/Rev.php +++ b/src/Abilities/Rev.php @@ -39,7 +39,8 @@ final class Rev * title, url and linked object. Other item data (classes, target, …) is never rewritten * by the tool and therefore not part of the lock. * - * @param list $items wp_get_nav_menu_items() result. + * @param array $items wp_get_nav_menu_items() result – may have gaps in + * its keys (core filters it), only the order counts. */ public static function ofMenu(array $items): string { diff --git a/src/Admin/AccessTab.php b/src/Admin/AccessTab.php index 6c7e172..c183f59 100644 --- a/src/Admin/AccessTab.php +++ b/src/Admin/AccessTab.php @@ -121,7 +121,9 @@ final class AccessTab implements AdminTab } // phpcs:disable WordPress.Security.NonceVerification.Missing -- verified right below. - $uuid = isset($_POST['uuid']) ? sanitize_text_field(wp_unslash((string) $_POST['uuid'])) : ''; + $uuid = isset($_POST['uuid']) && is_string($_POST['uuid']) + ? sanitize_text_field(wp_unslash($_POST['uuid'])) + : ''; $userId = isset($_POST['user_id']) ? absint($_POST['user_id']) : 0; // phpcs:enable WordPress.Security.NonceVerification.Missing check_admin_referer(self::REVOKE_ACTION . '_' . $uuid); diff --git a/src/Integrations/Media/MediaUsageFinder.php b/src/Integrations/Media/MediaUsageFinder.php index 0f6d3f2..ec10818 100644 --- a/src/Integrations/Media/MediaUsageFinder.php +++ b/src/Integrations/Media/MediaUsageFinder.php @@ -60,12 +60,12 @@ class MediaUsageFinder private const EXCLUDED_STATUSES = "'auto-draft', 'trash', 'inherit'"; - /** - * @param Closure(): list $mediaMetaKeys Keys of file/image fields (ContentSchema::mediaFieldKeys()). - */ /** Set by results() when a query of the current collect() run failed. */ private bool $queryFailed = false; + /** + * @param Closure(): list $mediaMetaKeys Keys of file/image fields (ContentSchema::mediaFieldKeys()). + */ public function __construct(private Closure $mediaMetaKeys, private ?\wpdb $db = null) { } diff --git a/tests/Unit/Admin/AccessTabTest.php b/tests/Unit/Admin/AccessTabTest.php index 131d931..e2e3abc 100644 --- a/tests/Unit/Admin/AccessTabTest.php +++ b/tests/Unit/Admin/AccessTabTest.php @@ -145,6 +145,19 @@ final class AccessTabTest extends TestCase }))->handleRevoke(); } + public function testRevokeTreatsANonStringUuidAsMissing(): void + { + $_POST = ['user_id' => '3', 'uuid' => ['uuid-1']]; + Functions\when('current_user_can')->justReturn(true); + Functions\expect('check_admin_referer')->once()->with('lit_mcp_revoke_'); + $connections = Mockery::mock(ConnectionRepository::class); + $connections->expects('revoke')->with(3, '')->andReturn(false); + Functions\when('wp_safe_redirect')->justReturn(true); + + (new AccessTab(new Access(), $connections, static function (): void { + }))->handleRevoke(); + } + public function testRevokeRequiresManageOptions(): void { $_POST = ['user_id' => '3', 'uuid' => 'uuid-1']; diff --git a/tests/Unit/Integrations/WordPress/Status/PostScheduleAbilityTest.php b/tests/Unit/Integrations/WordPress/Status/PostScheduleAbilityTest.php index 0e38ffc..628d71e 100644 --- a/tests/Unit/Integrations/WordPress/Status/PostScheduleAbilityTest.php +++ b/tests/Unit/Integrations/WordPress/Status/PostScheduleAbilityTest.php @@ -65,7 +65,7 @@ final class PostScheduleAbilityTest extends TestCase $result = $this->ability($log)->execute(['post_id' => 5, 'date' => '2099-06-01 09:30']); self::assertCount(1, $result['warnings']); - self::assertStringContainsString('öffentlich', $result['warnings'][0]); + self::assertStringContainsString('ÖFFENTLICH', $result['warnings'][0]); self::assertStringContainsString('2099-06-01 09:30', $result['warnings'][0]); }