File: /var/www/html/wp-content/plugins/wp-migrate-db/class/Common/Migration/FinalizeMigration.php
<?php
namespace DeliciousBrains\WPMDB\Common\Migration;
use DeliciousBrains\WPMDB\Common\Error\HandleRemotePostError;
use DeliciousBrains\WPMDB\Common\FormData\FormData;
use DeliciousBrains\WPMDB\Common\Http\Helper;
use DeliciousBrains\WPMDB\Common\Http\Http;
use DeliciousBrains\WPMDB\Common\Http\RemotePost;
use DeliciousBrains\WPMDB\Common\MigrationPersistence\Persistence;
use DeliciousBrains\WPMDB\Common\MigrationState\MigrationStateManager;
use DeliciousBrains\WPMDB\Common\Properties\Properties;
use DeliciousBrains\WPMDB\Common\Sql\Table;
use DeliciousBrains\WPMDB\Common\Sql\TableHelper;
use DeliciousBrains\WPMDB\Common\Util\Util;
class FinalizeMigration
{
public $state_data;
/**
* @var MigrationStateManager
*/
private $migration_state_manager;
/**
* @var Table
*/
private $table;
/**
* @var Http
*/
private $http;
/**
* @var Properties
*/
private $props;
/**
* @var TableHelper
*/
private $table_helper;
/**
* @var Helper
*/
private $http_helper;
/**
* @var Util
*/
private $util;
/**
* @var RemotePost
*/
private $remote_post;
/**
* @var FormData
*/
private $form_data;
/**
* @var MigrationHelper
*/
private $migration_helper;
public function __construct(
MigrationStateManager $migration_state_manager,
Table $table,
Http $http,
TableHelper $table_helper,
Helper $http_helper,
Util $util,
RemotePost $remote_post,
FormData $form_data,
Properties $properties,
MigrationHelper $migration_helper
) {
$this->migration_state_manager = $migration_state_manager;
$this->table = $table;
$this->http = $http;
$this->props = $properties;
$this->table_helper = $table_helper;
$this->http_helper = $http_helper;
$this->util = $util;
$this->remote_post = $remote_post;
$this->form_data = $form_data;
$this->migration_helper = $migration_helper;
}
/**
* After table migration, delete old tables and rename new tables removing the temporarily prefix.
*
* @return mixed
*/
function ajax_finalize_migration()
{
$_POST = $this->http_helper->convert_json_body_to_post();
$key_rules = array(
'action' => 'key',
'prefix' => 'string',
'tables' => 'string',
'nonce' => 'key',
);
$key_rules = apply_filters('wpmdb_finalize_key_rules', $key_rules);
//@todo - revisit
$migration_state = get_site_option('wpmdb_migration_state');
if (!isset($migration_state['site_details'])) {
return $this->http->end_ajax(new \WP_Error('wpmdb_finalize_failed', __('Unable to finalize the migration, migration state empty.')));
}
$state_data = Persistence::setPostData($key_rules, __METHOD__);
$state_data['site_details'] = $migration_state['site_details'];
if ('savefile' === $state_data['intent']) {
return true;
}
global $wpdb;
do_action('wpmdb_finalize_migration', $state_data); // Fires on local site
if ('push' === $state_data['intent']) {
do_action('wpmdb_migration_complete', 'push', $state_data['url']);
$data = $this->http_helper->filter_post_elements(
$state_data,
array(
'url',
'form_data',
'site_details',
'tables',
'temp_prefix',
)
);
$data['form_data'] = base64_encode($data['form_data']);
$data['site_details'] = base64_encode(json_encode($data['site_details']));
$data['action'] = 'wpmdb_remote_finalize_migration';
$data['intent'] = 'pull';
$data['prefix'] = $wpdb->base_prefix;
$data['type'] = 'push';
$data['location'] = Util::home_url();
$data['sig'] = $this->http_helper->create_signature($data, $state_data['key']);
$data['stage'] = $state_data['stage'];
$ajax_url = $this->util->ajax_url();
$response = $this->remote_post->post($ajax_url, $data, __FUNCTION__);
$return = HandleRemotePostError::handle('wpmdb-remote-finalize-failed', $response);
} else {
$return = $this->finalize_migration($state_data);
}
do_action('wpmdb_after_finalize_migration');
$result = $this->http->end_ajax($return);
return $result;
}
/**
* Internal function for finalizing a migration.
*
* @return bool|null
*/
function finalize_migration($state_data = false)
{
$state_data = !$state_data ? Persistence::getStateData() : $state_data;
if ( in_array($state_data['intent'], ['push', 'pull'])) {
$intent_type = isset($state_data['type']) ? $state_data['type'] : $state_data['intent'];
$state_data['destination_prefix'] = ('push' === $intent_type) ? $state_data['site_details']['remote']['prefix'] : $state_data['site_details']['local']['prefix'];
$state_data['source_prefix'] = ('push' === $intent_type) ? $state_data['site_details']['local']['prefix'] : $state_data['site_details']['remote']['prefix'];
}
$temp_prefix = isset($state_data['temp_prefix']) ? $state_data['temp_prefix'] : $this->props->temp_prefix;
$temp_tables = array();
$type = $state_data['intent'];
$alter_table_name = $this->table->get_alter_table_name();
$before_finalize_response = apply_filters('wpmdb_before_finalize_migration', true, $this);
if (is_wp_error($before_finalize_response)) {
return $this->http->end_ajax($before_finalize_response);
}
if (isset($state_data['type']) && 'push' === $state_data['type']) {
$type = 'push';
}
$tables = $this->get_tables($state_data);
if ('find_replace' === $state_data['intent'] || 'import' === $state_data['intent']) {
$location = Util::home_url();
} else {
$location = (isset($state_data['location'])) ? $state_data['location'] : $state_data['url'];
}
if ('import' === $state_data['intent']) {
$temp_tables = $this->table->get_tables('temp');
$tables = array();
foreach ($temp_tables as $key => $temp_table) {
if ($alter_table_name === $temp_table) {
unset($temp_tables[$key]);
continue;
}
$tables[] = substr($temp_table, strlen($temp_prefix));
}
} else {
foreach ($tables as $table) {
$temp_tables[] = $temp_prefix . apply_filters(
'wpmdb_finalize_target_table_name',
$table,
$state_data
);
}
}
$sql = "SET FOREIGN_KEY_CHECKS=0;\n";
$sql .= $this->table->get_preserved_options_queries($state_data, $temp_tables, $type);
foreach ($temp_tables as $table) {
$sql .= 'DROP TABLE IF EXISTS ' . $this->table_helper->backquote(substr($table, strlen($temp_prefix))) . ';';
$sql .= "\n";
$sql .= 'RENAME TABLE ' . $this->table_helper->backquote($table) . ' TO ' . $this->table_helper->backquote(substr($table, strlen($temp_prefix))) . ';';
$sql .= "\n";
}
$sql .= $this->table->get_alter_queries($state_data);
$sql .= 'DROP TABLE IF EXISTS ' . $this->table_helper->backquote($alter_table_name) . ";\n";
$process_chunk_result = $this->table->process_chunk($sql);
if (true !== $process_chunk_result) {
$result = $this->http->end_ajax($process_chunk_result);
return $result;
}
if (!isset($state_data['location']) && !in_array($state_data['intent'], array('find_replace', 'import'))) {
$data = array();
$data['action'] = 'wpmdb_fire_migration_complete';
$data['url'] = Util::home_url();
$data['sig'] = $this->http_helper->create_signature($data, $state_data['key']);
$ajax_url = $this->util->ajax_url();
$response = $this->remote_post->post($ajax_url, $data, __FUNCTION__);
$this->util->display_errors();
$decoded_response = json_decode($response, true);
if (!isset($decoded_response['success']) || !$decoded_response['success']) {
return $this->http->end_ajax(
new \WP_Error(
'wpmdb-remote-finalize-failed',
$response
)
);
}
}
do_action('wpmdb_migration_complete', $type, $location);
return true;
}
/**
* Convert string of table names to array, changes prefix if needed.
*
* @param array $state_data
*
* @return array of tables
*
**/
private function get_tables($state_data)
{
if ($state_data['tables'] === '') {
return [];
}
$source_tables = is_string($state_data['tables']) ? explode(',', $state_data['tables']) : $state_data['tables'];
$source_prefix = $state_data['source_prefix'];
$destination_prefix = $state_data['destination_prefix'];
if ($source_prefix === $destination_prefix || (isset($state_data['mst_select_subsite']) && '1' === $state_data['mst_select_subsite'])) {
return $source_tables;
}
return Util::change_tables_prefix($source_tables, $source_prefix, $destination_prefix);
}
}