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:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,6 +188,7 @@ if ( ! function_exists( 'wp_schedule_event' ) ) {
|
||||
if ( ! function_exists( 'wp_schedule_single_event' ) ) {
|
||||
function wp_schedule_single_event( int $ts, string $hook ): bool { return true; }
|
||||
}
|
||||
if ( ! function_exists( 'wp_unschedule_hook' ) ) { function wp_unschedule_hook( string $hook ): int|false { $GLOBALS['_wp_unscheduled'][] = $hook; return 0; } }
|
||||
if ( ! function_exists( 'wp_clear_scheduled_hook' ) ) {
|
||||
function wp_clear_scheduled_hook( string $hook ): int|false { return 0; }
|
||||
}
|
||||
|
||||
@@ -303,7 +303,8 @@ class DriftCheckTest extends TestCase {
|
||||
}
|
||||
// Literal: uninstall.php does not load TMDO_Drift_Check.
|
||||
$installer = (string) file_get_contents( WPDO_PLUGIN_DIR . 'includes/class-tmdo-installer.php' );
|
||||
$this->assertSame( 2, substr_count( $installer, "'" . TMDO_Drift_Check::RESYNC_HOOK . "'" ), 'cleared on deactivate and uninstall' );
|
||||
// One CRON_HOOKS list serves deactivate and uninstall (InstallerCleanupTest covers both).
|
||||
$this->assertSame( 1, substr_count( $installer, "'" . TMDO_Drift_Check::RESYNC_HOOK . "'" ), 'listed in CRON_HOOKS' );
|
||||
}
|
||||
|
||||
public function test_the_daily_tick_runs_on_the_daily_health_check_hook(): void {
|
||||
|
||||
@@ -68,6 +68,49 @@ class InstallerCleanupTest extends TestCase {
|
||||
$GLOBALS['_wp_options'] = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Events scheduled with args (tmdo_drift_resync( 'post' ), backfill
|
||||
* batches) are not cleared by wp_clear_scheduled_hook( $hook ); the user
|
||||
* stress hook was misnamed and three hooks were missing (2.4.2 PR-138, F-4).
|
||||
*/
|
||||
private const ARG_AND_MISSED_HOOKS = array( 'tmdo_drift_resync', 'wpdo_entity_backfill_batch', 'wpdo_stress_test_batch', 'wpdo_migration_tick', 'wpdo_auto_promote_check' );
|
||||
|
||||
public function test_deactivate_unschedules_every_hook_whatever_its_args(): void {
|
||||
$GLOBALS['_wp_unscheduled'] = array();
|
||||
|
||||
WPDO_Installer::deactivate();
|
||||
|
||||
foreach ( self::ARG_AND_MISSED_HOOKS as $hook ) {
|
||||
$this->assertContains( $hook, $GLOBALS['_wp_unscheduled'], $hook );
|
||||
}
|
||||
}
|
||||
|
||||
public function test_uninstall_unschedules_every_hook_whatever_its_args(): void {
|
||||
$GLOBALS['_wp_unscheduled'] = array();
|
||||
|
||||
WPDO_Installer::drop_all_tables_for_current_blog();
|
||||
|
||||
foreach ( self::ARG_AND_MISSED_HOOKS as $hook ) {
|
||||
$this->assertContains( $hook, $GLOBALS['_wp_unscheduled'], $hook );
|
||||
}
|
||||
}
|
||||
|
||||
/** tmdo_* options and transients were left behind; a reinstall then saw stale deferrals and indexes (F-5). */
|
||||
public function test_uninstall_removes_tmdo_options_and_transients(): void {
|
||||
global $wpdb;
|
||||
foreach ( array( 'tmdo_schema_deferred', 'tmdo_entity_indexes', '_transient_tmdo_cov_x', '_transient_timeout_tmdo_cov_x', 'hivepress_settings' ) as $name ) {
|
||||
$wpdb->insert( $wpdb->options, array( 'option_name' => $name, 'option_value' => '1' ) );
|
||||
$GLOBALS['_wp_options'][ $name ] = '1';
|
||||
}
|
||||
|
||||
WPDO_Installer::drop_all_tables_for_current_blog();
|
||||
|
||||
foreach ( array( 'tmdo_schema_deferred', 'tmdo_entity_indexes', '_transient_tmdo_cov_x', '_transient_timeout_tmdo_cov_x' ) as $name ) {
|
||||
$this->assertArrayNotHasKey( $name, $GLOBALS['_wp_options'], $name );
|
||||
}
|
||||
$this->assertArrayHasKey( 'hivepress_settings', $GLOBALS['_wp_options'], 'other plugins untouched' );
|
||||
}
|
||||
|
||||
public function test_drops_static_tables(): void {
|
||||
global $wpdb;
|
||||
|
||||
|
||||
@@ -315,6 +315,7 @@ if ( ! function_exists( 'get_metadata' ) ) {
|
||||
if ( ! function_exists( 'wp_next_scheduled' ) ) { function wp_next_scheduled( string $hook ): int|false { return false; } }
|
||||
if ( ! function_exists( 'wp_schedule_event' ) ) { function wp_schedule_event( int $t, string $r, string $h ): bool { return true; } }
|
||||
if ( ! function_exists( 'wp_schedule_single_event' ) ) { function wp_schedule_single_event( int $ts, string $hook ): bool { $GLOBALS['_wp_scheduled_single'][] = $hook; return true; } }
|
||||
if ( ! function_exists( 'wp_unschedule_hook' ) ) { function wp_unschedule_hook( string $hook ): int|false { $GLOBALS['_wp_unscheduled'][] = $hook; return 0; } }
|
||||
if ( ! function_exists( 'wp_clear_scheduled_hook' ) ) { function wp_clear_scheduled_hook( string $hook ): int|false { return 0; } }
|
||||
if ( ! function_exists( 'sanitize_text_field' ) ) { function sanitize_text_field( string $s ): string { return trim( strip_tags( $s ) ); } }
|
||||
if ( ! function_exists( '__' ) ) { function __( string $text, string $domain = 'default' ): string { return $text; } }
|
||||
|
||||
Reference in New Issue
Block a user