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
This commit is contained in:
@@ -297,6 +297,58 @@ class TMDO_Installer {
|
||||
update_option( self::MISC_BUCKET_DEFAULT_FLAG, '1', true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Reasons this site's wpdo_* tables cannot be dropped yet; empty means safe.
|
||||
*
|
||||
* Reads the site's own options rather than Mode_Manager / Feature_Flags,
|
||||
* whose per-request caches do not follow switch_to_blog() during uninstall.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function uninstall_blockers(): array {
|
||||
global $wpdb;
|
||||
$blockers = array();
|
||||
|
||||
$modes = get_option( 'wpdo_bridge_modes', array() );
|
||||
foreach ( is_array( $modes ) ? $modes : array() as $entity => $mode ) {
|
||||
if ( 'aeav_only' === $mode ) {
|
||||
$blockers[] = sprintf( '%1$s 的 bridge 模式是 aeav_only:資料只存在 wpdo_%1$s_* 扁平表。', $entity );
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( array( 'wpdo_term_misc', 'wpdo_comment_misc' ) as $name ) {
|
||||
if ( self::table_has_rows( $wpdb->prefix . $name ) ) {
|
||||
$blockers[] = sprintf( '%s 有資料:這些 term / comment meta 只存在 misc 表。', $name );
|
||||
}
|
||||
}
|
||||
|
||||
$features = get_option( 'wpdo_features', array() );
|
||||
foreach ( TMDO_Feature_Flags::ZONE_MODULES as $module ) {
|
||||
$state = is_array( $features ) ? ( $features[ $module ] ?? 'idle' ) : 'idle';
|
||||
if ( in_array( $state, array( 'cleanup', 'complete' ), true ) ) {
|
||||
$blockers[] = sprintf( '區域模組 %1$s 處於 %2$s:讀取已改走 wpdo_* 表。', $module, $state );
|
||||
}
|
||||
}
|
||||
|
||||
return $blockers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a table exists and holds at least one row.
|
||||
*
|
||||
* @param string $table Full table name.
|
||||
* @return bool
|
||||
*/
|
||||
private static function table_has_rows( string $table ): bool {
|
||||
global $wpdb;
|
||||
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||
if ( $table !== $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $table ) ) ) ) {
|
||||
return false;
|
||||
}
|
||||
return null !== $wpdb->get_var( "SELECT 1 FROM `{$table}` LIMIT 1" );
|
||||
// phpcs:enable
|
||||
}
|
||||
|
||||
// ── v2.0.0 entity + audit + shadow_diffs schema (PR-2) ─────────────────
|
||||
// These tables are installed only when v2.0.0 upgrade runs (PR-7).
|
||||
// install_v2_tables() is idempotent; safe to call multiple times.
|
||||
|
||||
Reference in New Issue
Block a user