query( "CREATE TABLE `{$wpdb->usermeta}` ( umeta_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, user_id BIGINT UNSIGNED NOT NULL DEFAULT 0, meta_key VARCHAR(255) DEFAULT NULL, meta_value LONGTEXT, PRIMARY KEY (umeta_id), KEY user_id (user_id) ) ENGINE=InnoDB" ); $wpdb->query( 'CREATE TABLE `' . self::TABLE . '` ( id BIGINT NOT NULL AUTO_INCREMENT, user_id BIGINT NOT NULL, prefs TEXT DEFAULT NULL, loc VARCHAR(255) DEFAULT NULL, name VARCHAR(255) DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY uk_entity (user_id) ) ENGINE=InnoDB' ); $prefs = serialize( array( 'core' => array( 'welcomeGuide' => false ) ) ); $wpdb->insert( self::TABLE, array( 'user_id' => 1, 'prefs' => 'Array' ) ); $wpdb->insert( self::TABLE, array( 'user_id' => 2, 'loc' => 'Array' ) ); $wpdb->insert( self::TABLE, array( 'user_id' => 3, 'name' => 'Array' ) ); $wpdb->insert( self::TABLE, array( 'user_id' => 4, 'prefs' => $prefs, 'loc' => 'Taipei' ) ); $wpdb->insert( $wpdb->usermeta, array( 'user_id' => 1, 'meta_key' => 'prefs', 'meta_value' => $prefs ) ); $wpdb->insert( $wpdb->usermeta, array( 'user_id' => 2, 'meta_key' => 'loc', 'meta_value' => 'Array' ) ); $wpdb->insert( $wpdb->usermeta, array( 'user_id' => 4, 'meta_key' => 'prefs', 'meta_value' => $prefs ) ); $GLOBALS['_wp_cache'] = array(); WPDO_Entity_Registry::init(); WPDO_Entity_Registry::register_adapter( 'user', new WPDO_Adapter_User() ); WPDO_Entity_Registry::register_group( 'user', 'al_prefs', array( array( 'key' => 'prefs', 'type' => 'textarea' ), array( 'key' => 'loc', 'type' => 'text' ), array( 'key' => 'name', 'type' => 'text' ), ) ); WPDO_Schema_Manager::flush_table_exists_cache(); } protected function tearDown(): void { self::drop(); WPDO_Entity_Registry::init(); } private static function drop(): void { global $wpdb; foreach ( array( $wpdb->usermeta, self::TABLE ) as $table ) { $wpdb->query( "DROP TABLE IF EXISTS `{$table}`" ); } } private function flat( int $user_id, string $col ): ?string { global $wpdb; return $wpdb->get_var( $wpdb->prepare( "SELECT `{$col}` FROM `" . self::TABLE . '` WHERE user_id = %d', $user_id ) ); } public function test_dry_run_reports_without_writing(): void { $report = TMDO_Array_Literal_Repair::run( 'user', false ); $this->assertSame( 3, $report['found'] ); $this->assertSame( 1, $report['repairable'] ); $this->assertSame( 0, $report['repaired'] ); $this->assertSame( 'Array', $this->flat( 1, 'prefs' ) ); } public function test_apply_repairs_from_native_and_lists_the_rest(): void { $report = TMDO_Array_Literal_Repair::run( 'user', true ); $this->assertSame( 1, $report['repaired'] ); $this->assertSame( serialize( array( 'core' => array( 'welcomeGuide' => false ) ) ), $this->flat( 1, 'prefs' ) ); $this->assertSame( 'Array', $this->flat( 2, 'loc' ), 'native is "Array" too — nothing to repair from' ); $this->assertSame( 'Array', $this->flat( 3, 'name' ), 'no native row' ); $this->assertSame( 'Taipei', $this->flat( 4, 'loc' ) ); $unrepairable = array_map( static function ( $r ) { return $r['id'] . ':' . $r['key'] . ':' . $r['reason']; }, $report['unrepairable'] ); sort( $unrepairable ); $this->assertSame( array( '2:loc:native_is_array_literal', '3:name:no_native_row' ), $unrepairable ); $this->assertSame( array( array( 'group' => 'al_prefs', 'key' => 'loc', 'id' => 2 ) ), $report['native_polluted'] ); } public function test_second_run_finds_only_the_unrepairable_rows(): void { TMDO_Array_Literal_Repair::run( 'user', true ); $report = TMDO_Array_Literal_Repair::run( 'user', true ); $this->assertSame( 2, $report['found'] ); $this->assertSame( 0, $report['repaired'] ); } }