b407f235ac
- 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
121 lines
4.2 KiB
PHP
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'] );
|
|
}
|
|
}
|
|
}
|