• Resolved aldemarcalazans

    (@aldemarcalazans)


    THE PROBLEM
    Renaming the table names in a multisite installation leads to an undesirable side effect: if you have granted a special role for a user (for instance, a role of Editor) in a site with an ID different than 1, this user will lost that role after renaming the tables. If you try to give its role again, you will see that the role menu options simply “disappeared”.

    CAUSE OF THE PROBLEM
    The part of the code responsible for renaming the “options” table, works only on the site with ID 1. It renames the option_name “wp_user_roles” in the “wp_options” table, but does not rename the option_name “wp_x_user_roles” in the table “wp_x_options” table (x may be 2, 3, 4 and so on – the IDs of the sites on a multisite installation).

    SOLUTION
    Modify the code to update all wp_x_options tables, and not only the wp_options table.

    EXAMPLE OF CODE MODIFICATION

    // ===== star of modified code =====
    // create an array with all site IDs + underscore
    if (is_multisite()) {
    	global $wpdb;
    	$blog_ids = $wpdb->get_col("SELECT blog_id FROM ".$table_new_prefix."blogs");
    	$n = count($blog_ids) - 1;
    	$blog_ids[0] = '';
    	for ($i = 1; $i <= $n; $i++) {
    		$blog_ids[$i] .= '_';
    	}
    } else {
    	$blog_ids = array('');
    }
    foreach ($blog_ids as $blog_id) {
    	//Now let's update the options tables
    	$update_option_table_query = "UPDATE " . $table_new_prefix .$blog_id. "options
    															  SET option_name = '".$table_new_prefix .$blog_id."user_roles'
    															  WHERE option_name = '".$table_old_prefix.$blog_id."user_roles'
    															  LIMIT 1";
    
    	if ( false === $wpdb->query($update_option_table_query) )
    	{
    		$error = 1;
    		echo "<p class='error'>Changing value: ",
    				 $table_old_prefix.$blog_id,
    				 "user_roles in table ",
    				 $table_new_prefix.$blog_id,
    				 "options to  ",
    				 $table_new_prefix.$blog_id,
    				 "user_roles</p>";
    
    		echo '<p class="aio_error_with_icon">'.sprintf( __('There was an error when updating the options table.', 'aiowpsecurity')).'</p>';
    		$aio_wp_security->debug_logger->log_debug("DB Security Feature - Error when updating the options table",4);//Log the highly unlikely event of DB error
    	}
    }
     if ($error != 1) {
    		echo '<p class="aio_success_with_icon">'.sprintf( __('The options tables records which had references to the old DB prefix were updated successfully!', 'aiowpsecurity')).'</p>';
    }
    // ===== end of modified code =====

    https://wordpress.org/plugins/all-in-one-wp-security-and-firewall/

Viewing 11 replies - 1 through 11 (of 11 total)
  • Plugin Contributor wpsolutions

    (@wpsolutions)

    Hi aldemarcalazans,
    Thanks for your input and feedback. I will look at this more closely and implement a fix as required.

    Thread Starter aldemarcalazans

    (@aldemarcalazans)

    A little correction to the modified code suggested by me:

    INSTEAD OF
    if ($error != 1)
    
    USE
     if ( @$error != 1)

    This is just to prevent, in development environments (where php.ini directive display_errors=On), the message:

    Notice: Undefined variable: error in var/www/html/wp1/wp-content/plugins/all-in-one-wp-security-and-firewall/admin/wp-security-database-menu.php on line 499

    This message occurs because $error variable was not defined before. In fact, the best solution would be define this variable in a previous part of the code as “zero” but, as you used “@$error” in the table rename part of code, I followed the same style in this correction.

    Plugin Contributor wpsolutions

    (@wpsolutions)

    Hi @aldemarcalazans,
    This fix should be available in the next release.

    Thread Starter aldemarcalazans

    (@aldemarcalazans)

    Hi guys. I have just downloaded version 3.8.3, and tested the fix made by you. Unfortunately, I verified that the problem was not solved. To confirm it, do the following:

    – create a multisite installation, and add two more sites (ids 2 and 3)

    – with a database utility, like phpmyadmin, do a search in all tables for the expression: user_roles. You will find three ocurrences, as follows:

    TABLE………………OPTION NAME
    wp_options…………wp_user_roles
    wp_2_options……..wp_2_user_roles
    wp_3_options……..wp_3_user_roles

    – now, go to the plugin “DB Prefix” page, and rename the table prefix. Then, after doing a refresh in phpmyadmin viewing, do the same search. You will the same three ocurrences, but ONLY ONE WAS CORRECTLY RENAMED, as follows:

    TABLE……………………..OPTION NAME
    90q63q_options………..90q63q_user_roles
    90q63q_2_options…….wp_2_user_roles
    90q63q_3_options…….wp_3_user_roles

    We should not find these references to “wp_” prefix, if the fix was working correctly. All occurences of “wp_” should be substitued by the new random prefix, in this case, “90q63q_”

    Thread Starter aldemarcalazans

    (@aldemarcalazans)

    I found the bug and fixed it: you are invoking a function of yours, AIOWPSecurity_Utility::get_blog_ids() to late in the code: after renaming the table prefixes. The right is invoking this function before renaming the table prefixes.
    Your original code is as follows:

    if (AIOWPSecurity_Utility::is_multisite_install()) {
                $blog_ids = AIOWPSecurity_Utility::get_blog_ids();
                if(!empty($blog_ids)){

    To fix the bug, invoke the function here:

    $blog_ids = AIOWPSecurity_Utility::get_blog_ids();
    //Rename all the table names

    Then, remove this line of code further ahead:

    if (AIOWPSecurity_Utility::is_multisite_install()) {
    
                if(!empty($blog_ids)){

    Plugin Contributor mbrsolution

    (@mbrsolution)

    Hi aldemarcalazans thank you for pointing that out. It is much appreciated. One of the plugin developers will check your code above.

    Thread Starter aldemarcalazans

    (@aldemarcalazans)

    I found another problem, after correct the cited bug: if you select a random prefix, renaming works fine. But, if you select a custom prefix (for instance, wp_), the options table of the subsites are not correctly modified. See the logs:

    Your WordPress system has a total of 40 tables and your new DB prefix will be: dzjeca
    The options table records which had references to the old DB prefix were updated successfully!
    The dzjeca_2_options table records which had references to the old DB prefix were updated successfully!
    The dzjeca_3_options table records which had references to the old DB prefix were updated successfully!

    Your WordPress system has a total of 40 tables and your new DB prefix will be: mbjy4b
    The options table records which had references to the old DB prefix were updated successfully!
    The mbjy4b_2_options table records which had references to the old DB prefix were updated successfully!
    The mbjy4b_3_options table records which had references to the old DB prefix were updated successfully!

    Your WordPress system has a total of 40 tables and your new DB prefix will be: wp_
    The options table records which had references to the old DB prefix were updated successfully!

    Thread Starter aldemarcalazans

    (@aldemarcalazans)

    I discovered that, there is a difference between the code that generates a random prefix and the code that uses a custom prefix: the first one does not change the variable associated with the tables prefix, but the second one does. This is the cause of the second bug, mentioned above.
    This undesirable change in the value of the variable is done by the following line of code:

    $error = $wpdb->set_prefix( $new_db_prefix );

    A way to revert this change is adding the following line to the code:

    $wpdb->set_prefix( $old_db_prefix ); // this line was added
    $perform_db_change = true; // this line is already in the code

    Another solution would be change the method for testing the custom prefix informed, in a way that did not change the value of the table prefix variable.

    Plugin Contributor wpsolutions

    (@wpsolutions)

    Ok thanks for the info. I will fix that bug for the manual custom prefix case.

    Thread Starter aldemarcalazans

    (@aldemarcalazans)

    Now, I found a problem that can only be seem with the WordPress debug turned on, as follows:

    – turn WordPress debug on, editing wp-config.php as follows:

    define('WP_DEBUG', true);
    define('WP_DEBUG_LOG', true);
    define('SAVEQUERIES', true);

    – go to the Database Security section of plugin and rename the table prefix

    – go to wp-content folder. You will see a file, debug.log, with the following content:

    [18-Sep-2014 20:32:35 UTC] WordPress database error Table ‘wp0eng.wp_blogs’ doesn’t exist for query SELECT blog_id FROM wp_blogs made by do_action(‘wp-security_page_aiowpsec_database’), call_user_func_array, AIOWPSecurity_Admin_Init->handle_database_menu_rendering, AIOWPSecurity_Database_Menu->__construct, AIOWPSecurity_Database_Menu->render_menu_page, call_user_func, AIOWPSecurity_Database_Menu->render_tab1, AIOWPSecurity_Database_Menu->change_db_prefix, AIOWPSecurity_Utility::get_blog_ids

    [18-Sep-2014 20:32:35 UTC] WordPress database error Table ‘wp0eng.wp_sitemeta’ doesn’t exist for query SELECT meta_value FROM wp_sitemeta WHERE meta_key = ‘dismissed_update_core’ AND site_id = 1 made by include(‘D:\Var\www\html\wp0eng\wp-admin\admin-footer.php’), apply_filters(‘update_footer’), call_user_func_array, core_update_footer, get_preferred_from_update_core, get_core_updates, get_site_option

    Note: wp0eng is the name of my database.
    Tests were made with your original code and with my modified code. Both returned this error.

    Thread Starter aldemarcalazans

    (@aldemarcalazans)

    Solution to the bug related above: add a line at the end of the function “change_db_prefix”, informing WordPress about the new prefix set, as follows:

    echo ($tasks_finished_msg_string); // line already in the code
    $wpdb->set_prefix($table_new_prefix); // line added

    Now, you won’t see any debug.log file beeing produced every time you rename the tables!

Viewing 11 replies - 1 through 11 (of 11 total)
  • The topic ‘Problem when renaming tables prefixes on a multisite installation’ is closed to new replies.