From 85f4138b36d4c1a01fbfd1cec1846d5fd93a3bbb Mon Sep 17 00:00:00 2001 From: Jan-Niclas Loosen Date: Fri, 6 Nov 2026 13:15:59 +0100 Subject: [PATCH] =?UTF-8?q?feat(admin):=20Pr=C3=BCfroute=20je=20Profil=20u?= =?UTF-8?q?nd=20Reiter=20=E2=80=9ECompatibility=E2=80=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Die generische CheckRoute (POST lit-mcp/v1/-check, für Divi weiter /divi-check) ersetzt DiviCheckRoute: Lock je Profil mit Besitzer-Token, Bericht je Profil, Rücksprung auf den neuen Reiter und Hook lit_mcp_compat_changed (Divi lädt darauf seinen Freigabe-Status neu). Der Reiter „Compatibility“ zeigt je Plugin Zustand (Wort und Icon), Hinweis zur Stufe, Fähigkeiten, getestete und freigegebene Versionen und den letzten Bericht, mit Prüfen, Freigeben und Zurückziehen (Recht manage_options, Allowlist der Profil-ID, Nonce je Profil). Freigeben serverseitig nur mit frischem grünem Bericht. Der Load-Hook lit_mcp_compat_profile_load bereitet den Abbau des DiviTab vor, der bis dahin parallel läuft. Co-Authored-By: Claude Opus 5.5 --- src/Admin/AdminPostAction.php | 10 +- src/Admin/CheckRoute.php | 184 +++++ src/Admin/CompatibilityTab.php | 474 +++++++++++ src/Admin/SettingsPage.php | 62 +- src/Compatibility/Profile.php | 3 + src/Integrations/Divi/Admin/DiviTab.php | 6 +- src/Integrations/Divi/Design/DesignLock.php | 2 +- src/Integrations/Divi/DiviIntegration.php | 18 +- .../Divi/Release/DiviCheckRoute.php | 128 --- src/Integrations/Divi/Release/DiviProfile.php | 1 + src/Plugin.php | 18 +- src/Uninstaller.php | 2 +- tests/Unit/Admin/CheckRouteTest.php | 310 ++++++++ tests/Unit/Admin/CompatibilityTabTest.php | 742 ++++++++++++++++++ tests/Unit/Admin/SettingsPageTest.php | 95 ++- tests/Unit/Compatibility/ProfileTest.php | 7 +- .../Integrations/Divi/DiviIntegrationTest.php | 14 +- .../Divi/Release/DiviCheckRouteTest.php | 161 ---- .../Divi/Release/DiviProfileTest.php | 6 + tests/Unit/PluginTest.php | 25 +- tests/Unit/UninstallTest.php | 3 +- tests/Unit/UninstallerTest.php | 3 +- 22 files changed, 1940 insertions(+), 334 deletions(-) create mode 100644 src/Admin/CheckRoute.php create mode 100644 src/Admin/CompatibilityTab.php delete mode 100644 src/Integrations/Divi/Release/DiviCheckRoute.php create mode 100644 tests/Unit/Admin/CheckRouteTest.php create mode 100644 tests/Unit/Admin/CompatibilityTabTest.php delete mode 100644 tests/Unit/Integrations/Divi/Release/DiviCheckRouteTest.php diff --git a/src/Admin/AdminPostAction.php b/src/Admin/AdminPostAction.php index 6d3358e..ae4fe1b 100644 --- a/src/Admin/AdminPostAction.php +++ b/src/Admin/AdminPostAction.php @@ -32,10 +32,14 @@ final class AdminPostAction } } - /** Redirects to settings tab $slug with "lit_mcp_notice" = $notice and ends the request. */ - public function redirect(string $slug, string $notice): void + /** + * Redirects to settings tab $slug with "lit_mcp_notice" = $notice (and further query $args) and ends the request. + * + * @param array $args + */ + public function redirect(string $slug, string $notice, array $args = []): void { - wp_safe_redirect(SettingsPage::url($slug, ['lit_mcp_notice' => $notice])); + wp_safe_redirect(SettingsPage::url($slug, ['lit_mcp_notice' => $notice] + $args)); ($this->terminate)(); } } diff --git a/src/Admin/CheckRoute.php b/src/Admin/CheckRoute.php new file mode 100644 index 0000000..efc6e60 --- /dev/null +++ b/src/Admin/CheckRoute.php @@ -0,0 +1,184 @@ +-check, one route per + * profile. A REST request on purpose – not admin-post – so the check runs in the same context as MCP calls (Divi + * renders its blocks in REST requests, lit-page-render-summary). The form sends the wp_rest nonce as _wpnonce + * (cookie authentication); only manage_options. The profile comes from the route, which exists only for the + * profiles of Compatibility; handle() looks the ID up again, so an ID never reaches an option name unchecked. + * One check per profile at a time: an atomic "INSERT IGNORE" on the options table (lit_mcp__check_lock) is the + * lock – add_option() reads then writes (wp-includes/option.php) and is not atomic, so two simultaneous requests + * could both "acquire" it. The value is "