feat: Divi tab with REST check, release and withdrawal
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,296 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Admin;
|
||||
|
||||
use Closure;
|
||||
use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use LIT\MCP\Integrations\Divi\Release\CheckReport;
|
||||
use LIT\MCP\Integrations\Divi\Release\CheckReportStore;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviCheckRoute;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviEnvironment;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseResolver;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStore;
|
||||
use LIT\MCP\Integrations\Divi\Release\WriteProbe;
|
||||
use LIT\MCP\Plugin;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Tab "Divi" (spec §6): release status of the installed Divi, the latest check report, "Prüfung starten" (REST,
|
||||
* DiviCheckRoute), "Divi <Version> freigeben" (only after a fresh green report) and "Freigabe zurückziehen" (only
|
||||
* for a database release). Opening the tab removes check pages a dead check left behind.
|
||||
*/
|
||||
final class DiviTab implements AdminTab
|
||||
{
|
||||
public const SLUG = 'divi';
|
||||
public const RELEASE_ACTION = 'lit_mcp_divi_release';
|
||||
public const WITHDRAW_ACTION = 'lit_mcp_divi_withdraw';
|
||||
|
||||
private const STATES = [
|
||||
'released' => 'freigegeben',
|
||||
'untested' => 'ungetestet',
|
||||
'incompatible' => 'inkompatibel',
|
||||
];
|
||||
|
||||
/**
|
||||
* @param (Closure(): string)|null $version Installed Divi version ('' = none); null = DiviEnvironment.
|
||||
* @param (Closure(string): string)|null $stateKey null = ReleaseResolver::stateKey().
|
||||
*/
|
||||
public function __construct(
|
||||
private ?CheckReportStore $reports = null,
|
||||
private ?ReleaseStore $releases = null,
|
||||
private ?ChangeLog $log = null,
|
||||
private ?AdminPostAction $action = null,
|
||||
private ?Closure $version = null,
|
||||
private ?Closure $stateKey = null
|
||||
) {
|
||||
}
|
||||
|
||||
public function slug(): string
|
||||
{
|
||||
return self::SLUG;
|
||||
}
|
||||
|
||||
public function label(): string
|
||||
{
|
||||
return __('Divi', 'wp-lit-mcp');
|
||||
}
|
||||
|
||||
public function registerSettings(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function registerActions(): void
|
||||
{
|
||||
add_action('admin_post_' . self::RELEASE_ACTION, [$this, 'release']);
|
||||
add_action('admin_post_' . self::WITHDRAW_ACTION, [$this, 'withdraw']);
|
||||
}
|
||||
|
||||
public function release(): void
|
||||
{
|
||||
$action = $this->action ?? new AdminPostAction();
|
||||
$action->guard();
|
||||
check_admin_referer(self::RELEASE_ACTION);
|
||||
|
||||
$version = $this->version();
|
||||
$report = $this->reports()->latest();
|
||||
$fresh = $report !== null
|
||||
&& $report->freshFor($version, Plugin::VERSION, $this->stateKey($version));
|
||||
if ($version === '' || ! $fresh) {
|
||||
$action->redirect(self::SLUG, 'divi_release_refused');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
($this->releases ?? new ReleaseStore())->add($version, Plugin::VERSION, get_current_user_id(), $report->id);
|
||||
ReleaseGate::forget();
|
||||
$this->log?->record(
|
||||
'lit/divi-release',
|
||||
'divi',
|
||||
$version,
|
||||
sprintf('Divi %s für LIT MCP %s freigegeben (Prüfbericht %s).', $version, Plugin::VERSION, $report->id)
|
||||
);
|
||||
$action->redirect(self::SLUG, 'divi_released');
|
||||
}
|
||||
|
||||
public function withdraw(): void
|
||||
{
|
||||
$action = $this->action ?? new AdminPostAction();
|
||||
$action->guard();
|
||||
check_admin_referer(self::WITHDRAW_ACTION);
|
||||
|
||||
$version = $this->version();
|
||||
if (! ($this->releases ?? new ReleaseStore())->withdraw($version, Plugin::VERSION)) {
|
||||
$action->redirect(self::SLUG, 'divi_withdraw_failed');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ReleaseGate::forget();
|
||||
$this->log?->record(
|
||||
'lit/divi-release',
|
||||
'divi',
|
||||
$version,
|
||||
sprintf('Freigabe von Divi %s zurückgezogen.', $version)
|
||||
);
|
||||
$action->redirect(self::SLUG, 'divi_withdrawn');
|
||||
}
|
||||
|
||||
public function render(): void
|
||||
{
|
||||
$removed = WriteProbe::removeOrphans();
|
||||
$status = ReleaseGate::status();
|
||||
$report = $this->reports()->latest();
|
||||
|
||||
echo '<h2>' . esc_html__('Divi-Freigabe', 'wp-lit-mcp') . '</h2>';
|
||||
echo '<p>' . esc_html__(
|
||||
// phpcs:ignore Generic.Files.LineLength.TooLong -- WordPress.WP.I18n forbids splitting the text argument.
|
||||
'LIT MCP schreibt nur mit Divi-Versionen, die geprüft sind. Nach einem Divi-Update hier die Prüfung starten und die Version freigeben; bis dahin lesen die Divi-Werkzeuge nur.',
|
||||
'wp-lit-mcp'
|
||||
) . '</p>';
|
||||
if ($removed !== []) {
|
||||
printf(
|
||||
'<div class="notice notice-warning inline"><p>%s</p></div>',
|
||||
esc_html(sprintf(
|
||||
/* translators: %s: comma separated page IDs */
|
||||
__('Liegengebliebene Prüfseiten gelöscht: %s', 'wp-lit-mcp'),
|
||||
implode(', ', $removed)
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
$this->renderStatus($status);
|
||||
$this->renderForms($status, $report);
|
||||
if ($report !== null) {
|
||||
$this->renderReport($report);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderStatus(ReleaseStatus $status): void
|
||||
{
|
||||
echo '<table class="form-table" role="presentation"><tbody>';
|
||||
printf(
|
||||
'<tr><th scope="row">%s</th><td>%s</td></tr>',
|
||||
esc_html__('Divi-Version', 'wp-lit-mcp'),
|
||||
esc_html($status->version === '' ? __('nicht erkannt', 'wp-lit-mcp') : $status->version)
|
||||
);
|
||||
printf(
|
||||
'<tr><th scope="row">%s</th><td><strong>%s</strong> – %s</td></tr>',
|
||||
esc_html__('Zustand', 'wp-lit-mcp'),
|
||||
esc_html(self::STATES[$status->state->value]),
|
||||
esc_html($this->explanation($status))
|
||||
);
|
||||
if ($status->problems !== []) {
|
||||
echo '<tr><th scope="row">' . esc_html__('Geändert in Divi', 'wp-lit-mcp') . '</th><td><ul>';
|
||||
foreach ($status->problems as $problem) {
|
||||
echo '<li>' . esc_html($problem) . '</li>';
|
||||
}
|
||||
echo '</ul></td></tr>';
|
||||
}
|
||||
echo '</tbody></table>';
|
||||
}
|
||||
|
||||
private function explanation(ReleaseStatus $status): string
|
||||
{
|
||||
if ($status->state === ReleaseState::Incompatible) {
|
||||
return __(
|
||||
// phpcs:ignore Generic.Files.LineLength.TooLong -- WordPress.WP.I18n forbids splitting the text argument.
|
||||
'Divi hat Stellen geändert, die LIT MCP nutzt. Schreiben bleibt gesperrt, bis ein Plugin-Update von LIT MCP eingespielt ist.',
|
||||
'wp-lit-mcp'
|
||||
);
|
||||
}
|
||||
if ($status->state === ReleaseState::Untested) {
|
||||
return __(
|
||||
'Diese Version ist nicht geprüft. Die Divi-Werkzeuge lesen nur, bis sie freigegeben ist.',
|
||||
'wp-lit-mcp'
|
||||
);
|
||||
}
|
||||
if ($status->source === ReleaseStatus::SOURCE_CODE) {
|
||||
return __('Diese Version ist im Plugin als getestet hinterlegt.', 'wp-lit-mcp');
|
||||
}
|
||||
|
||||
$user = get_userdata((int) ($status->release['user_id'] ?? 0));
|
||||
$releasedAt = (int) strtotime((string) ($status->release['released_at'] ?? ''));
|
||||
|
||||
return sprintf(
|
||||
/* translators: 1: date, 2: user name */
|
||||
__('Auf dieser Website freigegeben am %1$s von %2$s.', 'wp-lit-mcp'),
|
||||
date_i18n((string) get_option('date_format'), $releasedAt),
|
||||
is_object($user) && isset($user->display_name) ? (string) $user->display_name : '?'
|
||||
);
|
||||
}
|
||||
|
||||
private function renderForms(ReleaseStatus $status, ?CheckReport $report): void
|
||||
{
|
||||
printf('<form method="post" action="%s">', esc_url(DiviCheckRoute::url()));
|
||||
printf('<input type="hidden" name="_wpnonce" value="%s">', esc_attr(wp_create_nonce('wp_rest')));
|
||||
submit_button(__('Prüfung starten', 'wp-lit-mcp'), 'secondary', 'lit-mcp-divi-check', false);
|
||||
echo '</form>';
|
||||
|
||||
if ($status->state === ReleaseState::Untested && $status->version !== '') {
|
||||
$fresh = $report !== null
|
||||
&& $report->freshFor($status->version, Plugin::VERSION, $this->stateKey($status->version));
|
||||
if ($fresh) {
|
||||
$this->actionForm(
|
||||
self::RELEASE_ACTION,
|
||||
/* translators: %s: Divi version */
|
||||
sprintf(__('Divi %s freigeben', 'wp-lit-mcp'), $status->version),
|
||||
'primary'
|
||||
);
|
||||
} else {
|
||||
echo '<p>' . esc_html__(
|
||||
// phpcs:ignore Generic.Files.LineLength.TooLong -- WordPress.WP.I18n forbids splitting the text argument.
|
||||
'Freigeben geht erst nach einer vollständig grünen Prüfung dieser Divi-Version – Prüfung erneut ausführen.',
|
||||
'wp-lit-mcp'
|
||||
) . '</p>';
|
||||
}
|
||||
}
|
||||
|
||||
if ($status->state === ReleaseState::Released && $status->source === ReleaseStatus::SOURCE_DATABASE) {
|
||||
$this->actionForm(self::WITHDRAW_ACTION, __('Freigabe zurückziehen', 'wp-lit-mcp'), 'secondary');
|
||||
}
|
||||
}
|
||||
|
||||
private function actionForm(string $action, string $label, string $type): void
|
||||
{
|
||||
printf('<form method="post" action="%s">', esc_url(admin_url('admin-post.php')));
|
||||
printf('<input type="hidden" name="action" value="%s">', esc_attr($action));
|
||||
wp_nonce_field($action);
|
||||
submit_button($label, $type, 'submit', false);
|
||||
echo '</form>';
|
||||
}
|
||||
|
||||
private function renderReport(CheckReport $report): void
|
||||
{
|
||||
printf(
|
||||
'<h3>%s</h3><p>%s</p><ul class="lit-mcp-divi-report">',
|
||||
esc_html__('Letzte Prüfung', 'wp-lit-mcp'),
|
||||
esc_html(sprintf(
|
||||
/* translators: 1: Divi version, 2: plugin version, 3: date */
|
||||
__('Divi %1$s mit LIT MCP %2$s, %3$s', 'wp-lit-mcp'),
|
||||
$report->diviVersion,
|
||||
$report->pluginVersion,
|
||||
date_i18n((string) get_option('date_format'), (int) strtotime($report->createdAt))
|
||||
))
|
||||
);
|
||||
foreach ($report->steps as $step) {
|
||||
$mark = $step->skipped ? '–' : ($step->green() ? '✓' : '✗');
|
||||
printf('<li>%s %s', esc_html($mark), esc_html($step->label()));
|
||||
if ($step->skipped) {
|
||||
echo ' (' . esc_html__('nicht ausgeführt', 'wp-lit-mcp') . ')';
|
||||
}
|
||||
if ($step->problems !== []) {
|
||||
echo '<ul>';
|
||||
foreach ($step->problems as $problem) {
|
||||
echo '<li>' . esc_html($problem) . '</li>';
|
||||
}
|
||||
echo '</ul>';
|
||||
}
|
||||
echo '</li>';
|
||||
}
|
||||
echo '</ul><p class="description">' . esc_html__(
|
||||
'Optional: eine Divi-Seite im Visual Builder öffnen und speichern.',
|
||||
'wp-lit-mcp'
|
||||
) . '</p>';
|
||||
}
|
||||
|
||||
private function version(): string
|
||||
{
|
||||
return ($this->version ?? static fn (): string => DiviEnvironment::version() ?? '')();
|
||||
}
|
||||
|
||||
private function stateKey(string $version): string
|
||||
{
|
||||
return ($this->stateKey ?? static fn (string $v): string => ReleaseResolver::stateKey($v))($version);
|
||||
}
|
||||
|
||||
private function reports(): CheckReportStore
|
||||
{
|
||||
return $this->reports ?? new CheckReportStore();
|
||||
}
|
||||
}
|
||||
@@ -160,6 +160,28 @@ final class SettingsPage
|
||||
'revoked' => ['success', __('Verbindung widerrufen.', 'wp-lit-mcp')],
|
||||
'revoke_failed' => ['error', __('Die Verbindung konnte nicht widerrufen werden.', 'wp-lit-mcp')],
|
||||
'cleared' => ['success', __('Protokoll geleert.', 'wp-lit-mcp')],
|
||||
'divi_checked' => ['success', __('Divi-Prüfung abgeschlossen; das Ergebnis steht unten.', 'wp-lit-mcp')],
|
||||
'divi_check_running' => [
|
||||
'warning',
|
||||
__('Es läuft bereits eine Divi-Prüfung; bitte in ein paar Minuten erneut versuchen.', 'wp-lit-mcp'),
|
||||
],
|
||||
'divi_released' => ['success', __('Die Divi-Version ist für LIT MCP freigegeben.', 'wp-lit-mcp')],
|
||||
'divi_release_refused' => [
|
||||
'error',
|
||||
__(
|
||||
// phpcs:ignore Generic.Files.LineLength.TooLong -- WordPress.WP.I18n forbids splitting the text argument.
|
||||
'Freigabe nicht möglich: Der letzte Prüfbericht ist nicht grün oder passt nicht mehr zur installierten Divi- oder Plugin-Version. Bitte die Prüfung erneut ausführen.',
|
||||
'wp-lit-mcp'
|
||||
),
|
||||
],
|
||||
'divi_withdrawn' => [
|
||||
'success',
|
||||
__('Freigabe zurückgezogen; schreibende Divi-Werkzeuge sind wieder gesperrt.', 'wp-lit-mcp'),
|
||||
],
|
||||
'divi_withdraw_failed' => [
|
||||
'error',
|
||||
__('Für die installierte Divi-Version gibt es auf dieser Website keine Freigabe.', 'wp-lit-mcp'),
|
||||
],
|
||||
default => null,
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Integrations\Divi\Release;
|
||||
|
||||
use Closure;
|
||||
use LIT\MCP\Admin\DiviTab;
|
||||
use LIT\MCP\Admin\SettingsPage;
|
||||
use WP_REST_Response;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* "Prüfung starten" of the Divi tab (spec §6.1): POST /wp-json/lit-mcp/v1/divi-check. 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.
|
||||
* One check at a time: the option LOCK (add_option is atomic); a lock older than LOCK_TTL is a dead check's and taken
|
||||
* over. Answers 303 back to the tab.
|
||||
*/
|
||||
final class DiviCheckRoute
|
||||
{
|
||||
public const NAMESPACE = 'lit-mcp/v1';
|
||||
public const ROUTE = '/divi-check';
|
||||
public const LOCK = 'lit_mcp_divi_check_lock';
|
||||
|
||||
private const LOCK_TTL = 600;
|
||||
|
||||
/** @param Closure(): CompatibilityCheck $check */
|
||||
public function __construct(private Closure $check, private ?CheckReportStore $reports = null)
|
||||
{
|
||||
}
|
||||
|
||||
public function register(): void
|
||||
{
|
||||
add_action('rest_api_init', [$this, 'registerRoute']);
|
||||
}
|
||||
|
||||
public function registerRoute(): void
|
||||
{
|
||||
register_rest_route(self::NAMESPACE, self::ROUTE, [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'handle'],
|
||||
'permission_callback' => static fn (): bool => current_user_can('manage_options'),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function url(): string
|
||||
{
|
||||
return rest_url(self::NAMESPACE . self::ROUTE);
|
||||
}
|
||||
|
||||
public function handle(): WP_REST_Response
|
||||
{
|
||||
$notice = 'divi_check_running';
|
||||
if (self::lock()) {
|
||||
try {
|
||||
$report = ($this->check)()->run(get_current_user_id());
|
||||
($this->reports ?? new CheckReportStore())->save($report);
|
||||
ReleaseGate::forget();
|
||||
$notice = 'divi_checked';
|
||||
} finally {
|
||||
delete_option(self::LOCK);
|
||||
}
|
||||
}
|
||||
|
||||
return new WP_REST_Response(
|
||||
null,
|
||||
303,
|
||||
['Location' => SettingsPage::url(DiviTab::SLUG, ['lit_mcp_notice' => $notice])]
|
||||
);
|
||||
}
|
||||
|
||||
private static function lock(): bool
|
||||
{
|
||||
if (add_option(self::LOCK, time(), '', false)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$since = (int) get_option(self::LOCK, 0);
|
||||
if ($since > 0 && time() - $since < self::LOCK_TTL) {
|
||||
return false;
|
||||
}
|
||||
delete_option(self::LOCK);
|
||||
|
||||
return (bool) add_option(self::LOCK, time(), '', false);
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ use LIT\MCP\Admin\ConnectionRepository;
|
||||
use LIT\MCP\Admin\ConnectionStatus;
|
||||
use LIT\MCP\Admin\ConnectionTab;
|
||||
use LIT\MCP\Admin\ConnectionUsage;
|
||||
use LIT\MCP\Admin\DiviTab;
|
||||
use LIT\MCP\Admin\LimitsTab;
|
||||
use LIT\MCP\Admin\LogTab;
|
||||
use LIT\MCP\Admin\SettingsPage;
|
||||
@@ -24,6 +25,8 @@ use LIT\MCP\Guides\InstructionsBuilder;
|
||||
use LIT\MCP\Integrations\Core\CoreIntegration;
|
||||
use LIT\MCP\Integrations\Divi\DiviIntegration;
|
||||
use LIT\MCP\Integrations\Divi\Library\LibraryAccess;
|
||||
use LIT\MCP\Integrations\Divi\Release\CompatibilityCheck;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviCheckRoute;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviToolGate;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseResolver;
|
||||
use LIT\MCP\Integrations\Divi\ThemeBuilder\ThemeBuilderAccess;
|
||||
@@ -134,6 +137,10 @@ final class Plugin
|
||||
$divi->themeBuilder()
|
||||
);
|
||||
|
||||
// Spec §6: the admin check runs as a REST request (same context as MCP calls).
|
||||
$diviCheck = static fn (): CompatibilityCheck => CompatibilityCheck::create($divi->contentComposer());
|
||||
(new DiviCheckRoute($diviCheck))->register();
|
||||
|
||||
$policy = ExposurePolicy::fromOption()->withGroups($registry->groupMap(...));
|
||||
(new AbilityRegistrar($registry, $policy, new DiviToolGate($registry->groupMap(...), $changeLog)))->register();
|
||||
(new ServerRegistrar(
|
||||
@@ -153,6 +160,7 @@ final class Plugin
|
||||
new ToolsTab($registry, $policy),
|
||||
new LogTab($changeLog, $limits, $registry),
|
||||
new LimitsTab(),
|
||||
new DiviTab(log: $changeLog),
|
||||
];
|
||||
self::$settingsPage = new SettingsPage(
|
||||
$tabs,
|
||||
|
||||
+18
-11
@@ -7,19 +7,21 @@ namespace LIT\MCP;
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Removes WP-LIT-MCP's own data (uninstall.php, Task 12): options, the endpoint-check
|
||||
* transient, the log-cleanup cron hook and the change log table – on every site of a
|
||||
* network – and the Protokoll tab's per-user screen option.
|
||||
* Removes WP-LIT-MCP's own data (uninstall.php, Task 12): options, the endpoint-check and
|
||||
* Divi-release transients, the log-cleanup cron hook and the change log table – on every
|
||||
* site of a network – and the Protokoll tab's per-user screen option.
|
||||
*
|
||||
* Deliberately self-contained (no reference to any other LIT\MCP\* class): uninstall.php
|
||||
* is executed by WordPress core standalone, without loading the plugin's main file first,
|
||||
* so the Composer/Jetpack autoloader is not guaranteed to have run. The option/hook/table
|
||||
* names below are therefore duplicated from Access::OPTION, Abilities\ExposurePolicy::OPTION,
|
||||
* Limits::OPTION, ChangeLog\ChangeLogInstaller::VERSION_OPTION, Admin\ConnectionStatus::
|
||||
* ENDPOINT_TRANSIENT, ChangeLog\ChangeLogCleanup::HOOK, ChangeLog\ChangeLog::TABLE and
|
||||
* Admin\LogTab::PER_PAGE_OPTION on
|
||||
* purpose; tests/Unit/UninstallerTest.php and tests/Unit/UninstallTest.php keep them in
|
||||
* sync with those constants.
|
||||
* Limits::OPTION, ChangeLog\ChangeLogInstaller::VERSION_OPTION, Integrations\Divi\Release\
|
||||
* ReleaseStore::OPTION, Integrations\Divi\Release\CheckReportStore::OPTION, Integrations\
|
||||
* Divi\Release\DiviCheckRoute::LOCK, Admin\ConnectionStatus::ENDPOINT_TRANSIENT,
|
||||
* Integrations\Divi\Release\ReleaseResolver::CACHE, ChangeLog\ChangeLogCleanup::HOOK,
|
||||
* ChangeLog\ChangeLog::TABLE and Admin\LogTab::PER_PAGE_OPTION on purpose;
|
||||
* tests/Unit/UninstallerTest.php and tests/Unit/UninstallTest.php keep them in sync with
|
||||
* those constants.
|
||||
*
|
||||
* Never touches the bundled wp-media/mcp-oauth library's data (option mcp_jwt_secret,
|
||||
* option wpmedia_mcp_oauth_rewrite_version, user meta mcp_refresh_jti_*, application
|
||||
@@ -28,8 +30,11 @@ defined('ABSPATH') || exit;
|
||||
*/
|
||||
final class Uninstaller
|
||||
{
|
||||
private const OPTIONS = ['lit_mcp_allowed_roles', 'lit_mcp_exposure', 'lit_mcp_limits', 'lit_mcp_db_version'];
|
||||
private const TRANSIENT = 'lit_mcp_endpoint_check';
|
||||
private const OPTIONS = [
|
||||
'lit_mcp_allowed_roles', 'lit_mcp_exposure', 'lit_mcp_limits', 'lit_mcp_db_version',
|
||||
'lit_mcp_divi_releases', 'lit_mcp_divi_check_report', 'lit_mcp_divi_check_lock',
|
||||
];
|
||||
private const TRANSIENTS = ['lit_mcp_endpoint_check', 'lit_mcp_divi_state'];
|
||||
private const CRON_HOOK = 'lit_mcp_log_cleanup';
|
||||
private const TABLE = 'lit_mcp_log';
|
||||
|
||||
@@ -61,7 +66,9 @@ final class Uninstaller
|
||||
foreach (self::OPTIONS as $option) {
|
||||
delete_option($option);
|
||||
}
|
||||
delete_transient(self::TRANSIENT);
|
||||
foreach (self::TRANSIENTS as $transient) {
|
||||
delete_transient($transient);
|
||||
}
|
||||
wp_clear_scheduled_hook(self::CRON_HOOK);
|
||||
|
||||
$table = $wpdb->prefix . self::TABLE;
|
||||
|
||||
Reference in New Issue
Block a user