Files
2meet-data-optimizer/tests/integration/UninstallGuardTest.php
wpdev b407f235ac fix(2meet-data-optimizer): refuse uninstall while data lives only in flat tables
- uninstall.php checks every site first and wp_die()s (keeping tables,
  options and plugin files) on aeav_only modes, misc rows, or zone
  modules past cutover; a failed bootstrap also refuses
- Multisite now checks and cleans every site: network activation is always
  false at uninstall, so only the main site was being cleaned before
- Drop the inline fallback DROP loop, unreachable now that a missing
  helper refuses instead

Verify: UninstallGuardTest (8 tests incl. running uninstall.php single and
  multisite); unit 602 OK, integration 429 OK
PR: PR-008
2026-09-25 22:16:02 +08:00

121 lines
4.2 KiB
PHP

<?php
declare(strict_types=1);
use PHPUnit\Framework\TestCase;
/**
* Integration test: uninstall refuses to drop tables while data lives only in them.
*
* Covers TMDO_Installer::uninstall_blockers() and, end to end, that uninstall.php
* stops (wp_die) before touching any table or option.
*/
class UninstallGuardTest extends TestCase {
private const TERM_MISC = 'wp_itest_wpdo_term_misc';
public static function setUpBeforeClass(): void {
global $wpdb;
$wpdb->query(
'CREATE TABLE IF NOT EXISTS `' . self::TERM_MISC . '` (
term_id bigint(20) unsigned NOT NULL,
meta_key varchar(191) NOT NULL,
meta_value longtext,
updated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (term_id, meta_key)
) DEFAULT CHARACTER SET utf8mb4'
);
}
protected function setUp(): void {
global $wpdb;
$wpdb->prefix = 'wp_itest_';
$wpdb->options = 'wp_itest_options';
$wpdb->query( 'TRUNCATE TABLE `' . self::TERM_MISC . '`' );
delete_option( 'wpdo_bridge_modes' );
delete_option( 'wpdo_features' );
}
public function test_clean_site_has_no_blockers(): void {
$this->assertSame( array(), TMDO_Installer::uninstall_blockers() );
}
public function test_aeav_only_mode_blocks(): void {
update_option( 'wpdo_bridge_modes', array( 'post' => 'aeav_only', 'user' => 'dual_write' ) );
$blockers = TMDO_Installer::uninstall_blockers();
$this->assertCount( 1, $blockers );
$this->assertStringContainsString( 'post', $blockers[0] );
}
public function test_modes_that_still_write_native_do_not_block(): void {
update_option( 'wpdo_bridge_modes', array( 'user' => 'dual_write', 'term' => 'shadow_read', 'comment' => 'disabled' ) );
$this->assertSame( array(), TMDO_Installer::uninstall_blockers() );
}
public function test_misc_rows_block(): void {
global $wpdb;
$wpdb->query( 'INSERT INTO `' . self::TERM_MISC . "` (term_id, meta_key, meta_value) VALUES (1, 'k', 'v')" );
$blockers = TMDO_Installer::uninstall_blockers();
$this->assertCount( 1, $blockers );
$this->assertStringContainsString( 'wpdo_term_misc', $blockers[0] );
}
public function test_zone_module_past_cutover_blocks(): void {
update_option( 'wpdo_features', array( 'hot_hp_listing' => 'complete', 'cold_hp_vendor' => 'cleanup', 'warm' => 'cutover' ) );
$blockers = TMDO_Installer::uninstall_blockers();
$this->assertCount( 2, $blockers );
$this->assertStringContainsString( 'hot_hp_listing', implode( ' ', $blockers ) );
$this->assertStringContainsString( 'cold_hp_vendor', implode( ' ', $blockers ) );
}
public function test_hpct_module_complete_does_not_block(): void {
// HPCT modules live in hpct_* tables, which uninstall never drops.
update_option( 'wpdo_features', array( 'reviews' => 'complete' ) );
$this->assertSame( array(), TMDO_Installer::uninstall_blockers() );
}
public function test_uninstall_script_refuses_and_keeps_data(): void {
global $wpdb;
update_option( 'wpdo_bridge_modes', array( 'post' => 'aeav_only' ) );
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
define( 'WP_UNINSTALL_PLUGIN', '2meet-data-optimizer/2meet-data-optimizer.php' );
}
try {
require TMDO_PATH . 'uninstall.php';
$this->fail( 'uninstall.php should have stopped with wp_die()' );
} catch ( RuntimeException $e ) {
$this->assertStringContainsString( 'aeav_only', $e->getMessage() );
}
$this->assertSame( array( 'post' => 'aeav_only' ), get_option( 'wpdo_bridge_modes' ) );
$this->assertSame( self::TERM_MISC, $wpdb->get_var( "SHOW TABLES LIKE '" . self::TERM_MISC . "'" ) );
}
public function test_uninstall_script_checks_every_site_on_multisite(): void {
update_option( 'wpdo_bridge_modes', array( 'user' => 'aeav_only' ) );
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
define( 'WP_UNINSTALL_PLUGIN', '2meet-data-optimizer/2meet-data-optimizer.php' );
}
$GLOBALS['_wp_is_multisite'] = true;
$GLOBALS['_wp_sites'] = array( 1, 3 );
try {
require TMDO_PATH . 'uninstall.php';
$this->fail( 'uninstall.php should have stopped with wp_die()' );
} catch ( RuntimeException $e ) {
$this->assertStringContainsString( '站台 #1', $e->getMessage() );
$this->assertStringContainsString( '站台 #3', $e->getMessage() );
} finally {
unset( $GLOBALS['_wp_is_multisite'], $GLOBALS['_wp_sites'] );
}
}
}