name 1.1.0 wrote. * * @var array */ const OLD_META = array( '_adminkeep_live_draft_of' => '_wppa_live_draft_of', '_adminkeep_replaced_file' => '_wppa_replaced_file', ); /** * Keep URL table as 1.1.0 created it. * * @return string */ public static function old_table() { global $wpdb; return $wpdb->prefix . 'wppa_path_redirects'; } /** * Carry everything across, if there is anything to carry. * * @return bool Whether a migration ran. */ public static function maybe_migrate() { $old_settings = get_option( self::OLD_SETTINGS, null ); $old_schema = get_option( self::OLD_REDIRECT_SCHEMA, null ); if ( null === $old_settings && null === $old_schema ) { return false; } if ( is_array( $old_settings ) && false === get_option( Settings::OPTION ) ) { update_option( Settings::OPTION, $old_settings, true ); } if ( null !== $old_schema ) { self::move_table( $old_schema ); } self::move_meta(); wp_clear_scheduled_hook( self::OLD_CLEANUP_HOOK ); // Last, and only once the settings are readable under the new name: these rows are what // makes the next request try again. if ( ! is_array( $old_settings ) || is_array( get_option( Settings::OPTION ) ) ) { delete_option( self::OLD_SETTINGS ); } delete_option( self::OLD_REDIRECT_SCHEMA ); Settings::flush_cache(); return true; } /** * Rename the Keep URL table, keeping every redirect. * * A new table that already holds rows is never replaced: those redirects were recorded by * this version and the old table is left where it is rather than merged blind. * * @param mixed $old_schema Schema version stored under the old option name. * @return void */ private static function move_table( $old_schema ) { global $wpdb; $old = self::old_table(); $new = PathRedirectStore::table(); $suppressed = $wpdb->suppress_errors( true ); // Plugin-owned tables; names are $wpdb->prefix plus a literal, and DDL has no prepared form. // phpcs:disable WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL, PluginCheck.Security.DirectDB.UnescapedDBParameter if ( false !== get_option( PathRedirectStore::VERSION_OPTION ) ) { $rows = $wpdb->get_var( "SELECT COUNT(*) FROM {$new}" ); if ( null !== $rows && (int) $rows > 0 ) { $wpdb->suppress_errors( $suppressed ); return; } $wpdb->query( "DROP TABLE IF EXISTS {$new}" ); delete_option( PathRedirectStore::VERSION_OPTION ); } // ALTER ... RENAME rather than RENAME TABLE: the latter refuses temporary tables. $renamed = $wpdb->query( "ALTER TABLE {$old} RENAME TO {$new}" ); // phpcs:enable $wpdb->suppress_errors( $suppressed ); if ( false !== $renamed ) { update_option( PathRedirectStore::VERSION_OPTION, (int) $old_schema, false ); } } /** * Rename the two post-meta keys in place. * * @return void */ private static function move_meta() { global $wpdb; foreach ( self::OLD_META as $new_key => $old_key ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.SlowDBQuery $wpdb->update( $wpdb->postmeta, array( 'meta_key' => $new_key ), array( 'meta_key' => $old_key ), array( '%s' ), array( '%s' ) ); } } }