fix(2meet-data-optimizer): deactivate and uninstall clear every scheduled event and tmdo_* option

- One CRON_HOOKS list for deactivate() and uninstall; wp_unschedule_hook() also
  removes events scheduled with args (tmdo_drift_resync, backfill batches).
- Fix the wrong wpdo_user_stress_test_batch name; add migration tick,
  entity backfill, auto-promote and all stress-test batch hooks.
- Uninstall sweeps tmdo_* options and _transient_(timeout_)tmdo_* rows too.
- Verify: InstallerCleanupTest (3 new), unit 711, integration 611, phpcs 0
- PR: PR-138 (manual F-4, F-5)
This commit is contained in:
2026-09-28 18:25:01 +08:00
parent 90877b81e0
commit 15096f064f
5 changed files with 96 additions and 52 deletions
+49 -51
View File
@@ -780,31 +780,46 @@ class TMDO_Installer {
return $status;
}
/**
* Every cron hook the plugin schedules. Cleared with wp_unschedule_hook(),
* which also removes events scheduled with args (tmdo_drift_resync( 'post' ),
* backfill batches) that wp_clear_scheduled_hook( $hook ) leaves behind
* (2.4.2 PR-138).
*/
private const CRON_HOOKS = array(
'wpdo_warm_cleanup',
'wpdo_archive_sweep',
'wpdo_errors_gc',
'wpdo_flush_views',
'wpdo_remove_uae_plugin_dir',
'wpdo_daily_health_check',
'wpdo_snapshot_prune_daily',
'wpdo_fsm_automator_run',
'wpdo_collect_site_metrics',
'wpdo_health_snapshot_monthly',
'wpdo_post_shadow_verify',
'wpdo_term_comment_shadow_verify',
'tmdo_drift_resync',
'tmdo_ensure_group_indexes',
'wpdo_entity_backfill_batch',
'wpdo_migration_tick',
'wpdo_auto_promote_check',
'wpdo_post_stress_test_batch',
'wpdo_stress_test_batch',
'wpdo_term_stress_test_batch',
'wpdo_comment_stress_test_batch',
);
/**
* Called on plugin deactivation. Non-destructive.
*/
public static function deactivate(): void {
wp_clear_scheduled_hook( 'wpdo_warm_cleanup' );
wp_clear_scheduled_hook( 'wpdo_archive_sweep' );
// v2.14.0: clear all plugin cron hooks (was incomplete pre-v2.14.0).
wp_clear_scheduled_hook( 'wpdo_errors_gc' );
wp_clear_scheduled_hook( 'wpdo_flush_views' );
wp_clear_scheduled_hook( 'wpdo_remove_uae_plugin_dir' );
wp_clear_scheduled_hook( 'wpdo_daily_health_check' );
wp_clear_scheduled_hook( 'wpdo_snapshot_prune_daily' );
wp_clear_scheduled_hook( 'wpdo_fsm_automator_run' );
wp_clear_scheduled_hook( 'wpdo_collect_site_metrics' );
wp_clear_scheduled_hook( 'wpdo_health_snapshot_monthly' );
wp_clear_scheduled_hook( 'wpdo_post_shadow_verify' );
wp_clear_scheduled_hook( 'wpdo_term_comment_shadow_verify' );
wp_clear_scheduled_hook( 'tmdo_drift_resync' );
wp_clear_scheduled_hook( 'tmdo_ensure_group_indexes' );
wp_clear_scheduled_hook( 'wpdo_post_stress_test_batch' );
wp_clear_scheduled_hook( 'wpdo_user_stress_test_batch' );
wp_clear_scheduled_hook( 'wpdo_term_stress_test_batch' );
wp_clear_scheduled_hook( 'wpdo_comment_stress_test_batch' );
foreach ( self::CRON_HOOKS as $hook ) {
wp_unschedule_hook( $hook );
}
}
// ── v2.14.0: Multisite-aware site cleanup ─────────────────────────────────
/**
@@ -976,42 +991,25 @@ class TMDO_Installer {
// Sweep any remaining wpdo_* options (stragglers introduced post-v2.14.0
// or by 3rd-party hooks). Validates name pattern before delete to avoid
// accidental option removal.
$residual = $wpdb->get_col(
$wpdb->prepare(
"SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE %s",
$wpdb->esc_like( 'wpdo_' ) . '%'
)
);
foreach ( (array) $residual as $opt ) {
if ( preg_match( '/^wpdo_[a-zA-Z0-9_]+$/', $opt ) && delete_option( $opt ) ) {
++$options_deleted;
// 1.4.2: tmdo_* options and their transients too (tmdo_schema_deferred,
// tmdo_entity_indexes, tmdo_cov_* …) — a reinstall saw stale ones.
foreach ( array( 'wpdo_', 'tmdo_', '_transient_tmdo_', '_transient_timeout_tmdo_' ) as $prefix ) {
$residual = $wpdb->get_col(
$wpdb->prepare(
"SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE %s",
$wpdb->esc_like( $prefix ) . '%'
)
);
foreach ( (array) $residual as $opt ) {
if ( preg_match( '/^(_transient_(timeout_)?)?(wpdo|tmdo)_[a-zA-Z0-9_]+$/', $opt ) && delete_option( $opt ) ) {
++$options_deleted;
}
}
}
// ── 5) Clear cron events ──────────────────────────────────────────────
$crons = array(
'wpdo_warm_cleanup',
'wpdo_archive_sweep',
'wpdo_errors_gc',
'wpdo_flush_views',
'wpdo_remove_uae_plugin_dir',
'wpdo_daily_health_check',
'wpdo_snapshot_prune_daily',
'wpdo_fsm_automator_run',
'wpdo_collect_site_metrics',
'wpdo_health_snapshot_monthly',
'wpdo_post_shadow_verify',
'wpdo_term_comment_shadow_verify',
'tmdo_drift_resync',
'tmdo_ensure_group_indexes',
'wpdo_post_stress_test_batch',
'wpdo_user_stress_test_batch',
'wpdo_term_stress_test_batch',
'wpdo_comment_stress_test_batch',
);
foreach ( $crons as $hook ) {
if ( false !== wp_next_scheduled( $hook ) ) {
wp_clear_scheduled_hook( $hook );
foreach ( self::CRON_HOOKS as $hook ) {
if ( wp_unschedule_hook( $hook ) ) {
++$crons_cleared;
}
}