/**
  * The main loop triggered in step 5. Up here to keep it out of the way of the
  * HTML. This walks every table in the db that was selected in step 3 and then
  * walks every row and column replacing all occurences of a string with another.
  * We split large tables into 50,000 row blocks when dealing with them to save
  * on memmory consumption.
  *
  * @param mysql $connection The db connection object
  * @param string $search What we want to replace
  * @param string $replace What we want to replace it with.
  * @param array $tables The tables we want to look at.
  *
  * @return array    Collection of information gathered during the run.
  */
 function icit_srdb_replacer($connection, $search = '', $replace = '', $tables = array())
 {
     global $guid, $exclude_cols;
     $report = array('tables' => 0, 'rows' => 0, 'change' => 0, 'updates' => 0, 'start' => microtime(), 'end' => microtime(), 'errors' => array());
     if (is_array($tables) && !empty($tables)) {
         foreach ($tables as $table) {
             $report['tables']++;
             $columns = array();
             // Get a list of columns in this table
             $fields = MainWP_Child_DB::_query('DESCRIBE ' . $table, $connection);
             while ($column = MainWP_Child_DB::fetch_array($fields)) {
                 $columns[$column['Field']] = 'PRI' === $column['Key'] ? true : false;
             }
             // Count the number of rows we have in the table if large we'll split into blocks, This is a mod from Simon Wheatley
             $row_count = MainWP_Child_DB::_query('SELECT COUNT(*) as count FROM ' . $table, $connection);
             // to fix bug
             $rows_result = MainWP_Child_DB::fetch_array($row_count);
             $row_count = $rows_result['count'];
             if (0 === $row_count) {
                 continue;
             }
             $page_size = 50000;
             $pages = ceil($row_count / $page_size);
             for ($page = 0; $page < $pages; $page++) {
                 $current_row = 0;
                 $start = $page * $page_size;
                 $end = $start + $page_size;
                 // Grab the content of the table
                 $data = MainWP_Child_DB::_query(sprintf('SELECT * FROM %s LIMIT %d, %d', $table, $start, $end), $connection);
                 if (!$data) {
                     $report['errors'][] = MainWP_Child_DB::error();
                 }
                 while ($row = MainWP_Child_DB::fetch_array($data)) {
                     $report['rows']++;
                     // Increment the row counter
                     $current_row++;
                     $update_sql = array();
                     $where_sql = array();
                     $upd = false;
                     foreach ($columns as $column => $primary_key) {
                         if (1 === $guid && in_array($column, $exclude_cols)) {
                             continue;
                         }
                         $edited_data = $data_to_fix = $row[$column];
                         // Run a search replace on the data that'll respect the serialisation.
                         $edited_data = $this->recursive_unserialize_replace($search, $replace, $data_to_fix);
                         // Something was changed
                         if ($edited_data !== $data_to_fix) {
                             $report['change']++;
                             $update_sql[] = $column . ' = "' . MainWP_Child_DB::real_escape_string($edited_data) . '"';
                             $upd = true;
                         }
                         if ($primary_key) {
                             $where_sql[] = $column . ' = "' . MainWP_Child_DB::real_escape_string($data_to_fix) . '"';
                         }
                     }
                     if ($upd && !empty($where_sql)) {
                         $sql = 'UPDATE ' . $table . ' SET ' . implode(', ', $update_sql) . ' WHERE ' . implode(' AND ', array_filter($where_sql));
                         $result = MainWP_Child_DB::_query($sql, $connection);
                         if (!$result) {
                             $report['errors'][] = MainWP_Child_DB::error();
                         } else {
                             $report['updates']++;
                         }
                     } elseif ($upd) {
                         $report['errors'][] = sprintf('"%s" has no primary key, manual change needed on row %s.', $table, $current_row);
                     }
                 }
             }
         }
     }
     $report['end'] = microtime();
     return $report;
 }
 public function createBackupDB($filepath_prefix, $archiveExt = false, &$archiver = null)
 {
     $timeout = 20 * 60 * 60;
     //20minutes
     // @codingStandardsIgnoreStart
     @set_time_limit($timeout);
     @ini_set('max_execution_time', $timeout);
     $mem = '512M';
     @ini_set('memory_limit', $mem);
     // @codingStandardsIgnoreEnd
     /** @var $wpdb wpdb */
     global $wpdb;
     $db_files = array();
     //Get all the tables
     $tables_db = $wpdb->get_results('SHOW TABLES FROM `' . DB_NAME . '`', ARRAY_N);
     foreach ($tables_db as $curr_table) {
         if (null !== $archiver) {
             $archiver->updatePidFile();
         }
         $table = $curr_table[0];
         $currentfile = $filepath_prefix . '-' . MainWP_Helper::sanitize_filename($table) . '.sql';
         $db_files[] = $currentfile;
         if (file_exists($currentfile)) {
             continue;
         }
         $fh = fopen($currentfile . '.tmp', 'w');
         //or error;
         fwrite($fh, "\n\n" . 'DROP TABLE IF EXISTS ' . $table . ';');
         //todo fix this
         //$table_create = $wpdb->get_row( $wpdb->prepare( 'SHOW CREATE TABLE %s', $table ), ARRAY_N );
         $table_create = $wpdb->get_row('SHOW CREATE TABLE ' . $table, ARRAY_N);
         fwrite($fh, "\n" . $table_create[1] . ";\n\n");
         // @codingStandardsIgnoreStart
         $rows = @MainWP_Child_DB::_query('SELECT * FROM ' . $table, $wpdb->dbh);
         // @codingStandardsIgnoreEnd
         if ($rows) {
             $i = 0;
             $table_insert = 'INSERT INTO `' . $table . '` VALUES (';
             // @codingStandardsIgnoreStart
             while ($row = @MainWP_Child_DB::fetch_array($rows)) {
                 // @codingStandardsIgnoreEnd
                 $query = $table_insert;
                 foreach ($row as $value) {
                     $query .= '"' . MainWP_Child_DB::real_escape_string($value) . '", ';
                 }
                 $query = trim($query, ', ') . ');';
                 fwrite($fh, "\n" . $query);
                 $i++;
                 if ($i >= 50) {
                     fflush($fh);
                     $i = 0;
                 }
                 $query = null;
                 $row = null;
             }
         }
         $rows = null;
         fflush($fh);
         fclose($fh);
         rename($currentfile . '.tmp', $currentfile);
     }
     fclose(fopen($filepath_prefix . '.sql', 'w'));
     $db_files[] = $filepath_prefix . '.sql';
     $archivefilePath = null;
     if (false !== $archiveExt) {
         $archivefilePath = $filepath_prefix . '.sql.' . $archiveExt;
         if ('zip' === $archiveExt) {
             $this->archiver = null;
         } else {
             $this->archiver = new Tar_Archiver($this, $archiveExt);
         }
         if ($this->zipFile($db_files, $archivefilePath) && file_exists($archivefilePath)) {
             foreach ($db_files as $db_file) {
                 @unlink($db_file);
             }
         } else {
             //todo: throw exception!
         }
     }
     return false !== $archiveExt ? array('filepath' => $archivefilePath) : $db_files;
 }