Added dependency plugins
This commit is contained in:
2061
wordpress/wp-content/plugins/wp-migrate-db-pro/class/wpmdb-base.php
Normal file
2061
wordpress/wp-content/plugins/wp-migrate-db-pro/class/wpmdb-base.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,702 @@
|
||||
<?php
|
||||
|
||||
class WPMDB_CLI extends WPMDB_Base {
|
||||
|
||||
/**
|
||||
* Instance of WPMDB.
|
||||
*
|
||||
* @var WPMDB
|
||||
*/
|
||||
protected $wpmdb;
|
||||
|
||||
/**
|
||||
* Migration profile.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $profile;
|
||||
|
||||
/**
|
||||
* Data to post during migration.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $post_data = array();
|
||||
|
||||
/**
|
||||
* Required PHP version
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $php_version_required;
|
||||
|
||||
/**
|
||||
* Migration Data
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $migration;
|
||||
|
||||
function __construct( $plugin_file_path ) {
|
||||
parent::__construct( $plugin_file_path );
|
||||
|
||||
if ( ! version_compare( PHP_VERSION, $this->php_version_required, '>=' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
global $wpmdb;
|
||||
$this->wpmdb = $wpmdb;
|
||||
|
||||
add_filter( 'wpmdb_cli_finalize_migration_response', array( $this, 'finalize_ajax' ), 10, 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks profile data before CLI migration.
|
||||
*
|
||||
* @param int|array $profile Profile key or array.
|
||||
*
|
||||
* @return mixed|WP_Error
|
||||
*/
|
||||
public function pre_cli_migration_check( $profile ) {
|
||||
if ( ! version_compare( PHP_VERSION, $this->php_version_required, '>=' ) ) {
|
||||
return $this->cli_error( sprintf( __( 'CLI addon requires PHP %1$s+', 'wp-migrate-db-cli' ), $this->php_version_required ) );
|
||||
}
|
||||
|
||||
if ( is_array( $profile ) ) {
|
||||
$query_str = http_build_query( $profile );
|
||||
$profile = $this->wpmdb->parse_migration_form_data( $query_str );
|
||||
$profile = wp_parse_args( $profile, array(
|
||||
'save_computer' => '0',
|
||||
'gzip_file' => '0',
|
||||
'replace_guids' => '0',
|
||||
'exclude_transients' => '0',
|
||||
'exclude_spam' => '0',
|
||||
'keep_active_plugins' => '0',
|
||||
'compatibility_older_mysql' => '0',
|
||||
) );
|
||||
}
|
||||
|
||||
$this->profile = $profile = apply_filters( 'wpmdb_cli_profile_before_migration', $profile );
|
||||
|
||||
if ( is_wp_error( $profile ) ) {
|
||||
return $profile;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs CLI migration given a profile data.
|
||||
*
|
||||
* @param int|array $profile Profile key or array.
|
||||
*
|
||||
* @return bool|WP_Error Returns true if succeed or WP_Error if failed.
|
||||
*/
|
||||
public function cli_migration( $profile ) {
|
||||
$pre_check = $this->pre_cli_migration_check( $profile );
|
||||
if ( is_wp_error( $pre_check ) ) {
|
||||
return $pre_check;
|
||||
}
|
||||
|
||||
// At this point, $profile has been checked a retrieved into $this->profile, so should not be used in this function any further.
|
||||
if ( empty( $this->profile ) ) {
|
||||
return $this->cli_error( __( 'Profile not found or unable to be generated from params.', 'wp-migrate-db-cli' ) );
|
||||
}
|
||||
unset( $profile );
|
||||
|
||||
$this->set_time_limit();
|
||||
$this->wpmdb->set_cli_migration();
|
||||
|
||||
if ( 'savefile' === $this->profile['action'] ) {
|
||||
$this->post_data['intent'] = 'savefile';
|
||||
if ( ! empty( $this->profile['export_dest'] ) ) {
|
||||
$this->post_data['export_dest'] = $this->profile['export_dest'];
|
||||
} else {
|
||||
$this->post_data['export_dest'] = 'ORIGIN';
|
||||
}
|
||||
}
|
||||
|
||||
if ( 'find_replace' === $this->profile['action'] ) {
|
||||
$this->post_data['intent'] = 'find_replace';
|
||||
}
|
||||
|
||||
// Ensure local site_details available.
|
||||
$this->post_data['site_details']['local'] = $this->site_details();
|
||||
|
||||
// Check for tables specified in migration profile that do not exist in the source database
|
||||
if ( ! empty( $this->profile['select_tables'] ) ) {
|
||||
$source_tables = apply_filters( 'wpmdb_cli_filter_source_tables', $this->get_tables() );
|
||||
|
||||
if ( ! empty( $source_tables ) ) {
|
||||
// Return error if selected tables do not exist in source database
|
||||
$nonexistent_tables = array();
|
||||
foreach ( $this->profile['select_tables'] as $table ) {
|
||||
if ( ! in_array( $table, $source_tables ) ) {
|
||||
$nonexistent_tables[] = $table;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $nonexistent_tables ) ) {
|
||||
$local_or_remote = ( 'pull' === $this->profile['action'] ) ? 'remote' : 'local';
|
||||
|
||||
return $this->cli_error( sprintf( __( 'The following table(s) do not exist in the %1$s database: %2$s', 'wp-migrate-db-cli' ), $local_or_remote, implode( ', ', $nonexistent_tables ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->profile = apply_filters( 'wpmdb_cli_filter_before_cli_initiate_migration', $this->profile );
|
||||
if ( is_wp_error( $this->profile ) ) {
|
||||
return $this->profile;
|
||||
}
|
||||
|
||||
do_action( 'wpmdb_cli_before_migration', $this->post_data, $this->profile );
|
||||
$this->migration = $this->cli_initiate_migration();
|
||||
|
||||
if ( is_wp_error( $this->migration ) ) {
|
||||
return $this->migration;
|
||||
}
|
||||
|
||||
$this->post_data['migration_state_id'] = $this->migration['migration_state_id'];
|
||||
|
||||
$tables_to_process = $this->migrate_tables();
|
||||
if ( is_wp_error( $tables_to_process ) ) {
|
||||
return $tables_to_process;
|
||||
}
|
||||
|
||||
$this->post_data['tables'] = implode( ',', $tables_to_process );
|
||||
|
||||
$finalize = $this->finalize_migration();
|
||||
if ( is_wp_error( $finalize ) || 'savefile' === $this->profile['action'] ) {
|
||||
return $finalize;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify CLI response from endpoint.
|
||||
*
|
||||
* @param string $response Response from endpoint.
|
||||
* @param string $function_name Name of called function.
|
||||
*
|
||||
* @return WP_Error|string
|
||||
*/
|
||||
function verify_cli_response( $response, $function_name ) {
|
||||
$response = trim( $response );
|
||||
if ( false === $response ) {
|
||||
return $this->cli_error( $this->error );
|
||||
}
|
||||
|
||||
if ( false === $this->wpmdb->is_json( $response ) ) {
|
||||
return $this->cli_error( sprintf( __( 'We were expecting a JSON response, instead we received: %2$s (function name: %1$s)', 'wp-migrate-db-cli' ), $function_name, $response ) );
|
||||
}
|
||||
|
||||
$response = json_decode( $response, true );
|
||||
if ( isset( $response['wpmdb_error'] ) ) {
|
||||
return $this->cli_error( $response['body'] );
|
||||
}
|
||||
|
||||
// Display warnings and non fatal error messages as CLI warnings without aborting.
|
||||
if ( isset( $response['wpmdb_warning'] ) || isset( $response['wpmdb_non_fatal_error'] ) ) {
|
||||
$body = ( isset ( $response['cli_body'] ) ) ? $response['cli_body'] : $response['body'];
|
||||
$messages = maybe_unserialize( $body );
|
||||
foreach ( ( array ) $messages as $message ) {
|
||||
if ( $message ) {
|
||||
WP_CLI::warning( self::cleanup_message( $message ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return instance of WP_Error.
|
||||
*
|
||||
* @param string $message Error message.
|
||||
*
|
||||
* @return WP_Error.
|
||||
*/
|
||||
function cli_error( $message ) {
|
||||
return new WP_Error( 'wpmdb_cli_error', self::cleanup_message( $message ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup message, replacing <br> with \n and removing HTML.
|
||||
*
|
||||
* @param string $message Error message.
|
||||
*
|
||||
* @return string $message.
|
||||
*/
|
||||
static function cleanup_message( $message ) {
|
||||
$message = html_entity_decode( $message, ENT_QUOTES );
|
||||
$message = preg_replace( '#<br\s*/?>#', "\n", $message );
|
||||
$message = trim( strip_tags( $message ) );
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates migration and verifies result
|
||||
*
|
||||
* @return array|WP_Error
|
||||
*/
|
||||
function cli_initiate_migration() {
|
||||
do_action( 'wpmdb_cli_before_initiate_migration', $this->profile );
|
||||
|
||||
WP_CLI::log( __( 'Initiating migration...', 'wp-migrate-db-cli' ) );
|
||||
|
||||
$migration_args = $this->post_data;
|
||||
$migration_args['form_data'] = http_build_query( $this->profile );
|
||||
$migration_args['stage'] = 'migrate';
|
||||
$migration_args['site_details']['local'] = $this->site_details();
|
||||
|
||||
if ( 'find_replace' === $this->profile['action'] ) {
|
||||
$migration_args['stage'] = 'find_replace';
|
||||
|
||||
}
|
||||
|
||||
$this->post_data = apply_filters( 'wpmdb_cli_initiate_migration_args', $migration_args, $this->profile );
|
||||
|
||||
$this->post_data['site_details'] = json_encode( $this->post_data['site_details'] );
|
||||
|
||||
$response = $this->initiate_migration( $this->post_data );
|
||||
|
||||
$initiate_migration_response = $this->verify_cli_response( $response, 'initiate_migration()' );
|
||||
if ( ! is_wp_error( $initiate_migration_response ) ) {
|
||||
$initiate_migration_response = apply_filters( 'wpmdb_cli_initiate_migration_response', $initiate_migration_response );
|
||||
}
|
||||
|
||||
return $initiate_migration_response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine which tables to migrate
|
||||
*
|
||||
* @return array|WP_Error
|
||||
*/
|
||||
function get_tables_to_migrate() {
|
||||
$tables_to_migrate = $this->get_tables( 'prefix' );
|
||||
|
||||
return apply_filters( 'wpmdb_cli_tables_to_migrate', $tables_to_migrate, $this->profile, $this->migration );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a WP-CLI progress bar instance
|
||||
*
|
||||
* @param array $tables
|
||||
* @param int $stage
|
||||
*
|
||||
* @return \cli\progress\Bar
|
||||
*/
|
||||
function get_progress_bar( $tables, $stage ) {
|
||||
|
||||
$progress_label = __( 'Exporting tables', 'wp-migrate-db-cli' );
|
||||
|
||||
if ( 'find_replace' === $this->profile['action'] ) {
|
||||
$progress_label = __( 'Running find & replace', 'wp-migrate-db-cli' );
|
||||
}
|
||||
|
||||
$progress_label = apply_filters( 'wpmdb_cli_progress_label', $progress_label, $stage, $tables );
|
||||
|
||||
$progress_label = str_pad( $progress_label, 20, ' ' );
|
||||
|
||||
$count = $this->get_total_rows_from_table_list( $tables, $stage );
|
||||
|
||||
return new \cli\progress\Bar( $progress_label, $count );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns total rows from list of tables
|
||||
*
|
||||
* @param array $tables
|
||||
* @param int $stage
|
||||
*
|
||||
* @return Int
|
||||
*/
|
||||
function get_total_rows_from_table_list( $tables, $stage ) {
|
||||
static $cached_results = array();
|
||||
|
||||
if ( isset( $cached_results[ $stage ] ) ) {
|
||||
return $cached_results[ $stage ];
|
||||
}
|
||||
|
||||
$table_rows = $this->get_row_counts_from_table_list( $tables, $stage );
|
||||
$cached_results[ $stage ] = array_sum( array_intersect_key( $table_rows, array_flip( $tables ) ) );
|
||||
|
||||
return $cached_results[ $stage ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns row counts from list of tables
|
||||
*
|
||||
* @param array $tables
|
||||
* @param int $stage
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function get_row_counts_from_table_list( $tables, $stage ) {
|
||||
static $cached_results = array();
|
||||
|
||||
if ( isset( $cached_results[ $stage ] ) ) {
|
||||
return $cached_results[ $stage ];
|
||||
}
|
||||
|
||||
$local_table_rows = $this->wpmdb->get_table_row_count();
|
||||
$cached_results[ $stage ] = apply_filters( 'wpmdb_cli_get_row_counts_from_table_list', $local_table_rows, $stage );
|
||||
|
||||
return $cached_results[ $stage ];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|mixed|string|void|WP_Error
|
||||
*/
|
||||
function migrate_tables() {
|
||||
$tables_to_migrate = $this->get_tables_to_migrate();
|
||||
|
||||
$tables = $tables_to_migrate;
|
||||
$stage_iterator = 2;
|
||||
|
||||
$filtered_vars = apply_filters( 'wpmdb_cli_filter_before_migrate_tables', array(
|
||||
'tables' => $tables,
|
||||
'stage_iterator' => $stage_iterator,
|
||||
) );
|
||||
if ( ! is_array( $filtered_vars ) ) {
|
||||
return $filtered_vars;
|
||||
} else {
|
||||
extract( $filtered_vars, EXTR_OVERWRITE );
|
||||
}
|
||||
|
||||
if ( empty( $tables ) ) {
|
||||
return $this->cli_error( __( 'No tables selected for migration.', 'wp-migrate-db' ) );
|
||||
}
|
||||
|
||||
$table_rows = $this->get_row_counts_from_table_list( $tables, $stage_iterator );
|
||||
|
||||
do_action( 'wpmdb_cli_before_migrate_tables', $this->profile, $this->migration );
|
||||
|
||||
$notify = $this->get_progress_bar( $tables, $stage_iterator );
|
||||
$args = $this->post_data;
|
||||
|
||||
do {
|
||||
$migration_progress = 0;
|
||||
|
||||
foreach ( $tables as $key => $table ) {
|
||||
$current_row = -1;
|
||||
$primary_keys = '';
|
||||
$table_progress = 0;
|
||||
$table_progress_last = 0;
|
||||
|
||||
$args['table'] = $table;
|
||||
$args['last_table'] = ( $key == count( $tables ) - 1 ) ? '1' : '0';
|
||||
|
||||
do {
|
||||
// reset the current chunk
|
||||
$this->wpmdb->empty_current_chunk();
|
||||
|
||||
$args['current_row'] = $current_row;
|
||||
$args['primary_keys'] = $primary_keys;
|
||||
$args = apply_filters( 'wpmdb_cli_migrate_table_args', $args, $this->profile, $this->migration );
|
||||
|
||||
$response = $this->migrate_table( $args );
|
||||
|
||||
$migrate_table_response = $this->verify_cli_response( $response, 'migrate_table()' );
|
||||
|
||||
if ( is_wp_error( $migrate_table_response ) ) {
|
||||
return $migrate_table_response;
|
||||
}
|
||||
|
||||
$migrate_table_response = apply_filters( 'wpmdb_cli_migrate_table_response', $migrate_table_response, $_POST, $this->profile, $this->migration );
|
||||
|
||||
$current_row = $migrate_table_response['current_row'];
|
||||
$primary_keys = $migrate_table_response['primary_keys'];
|
||||
|
||||
$last_migration_progress = $migration_progress;
|
||||
|
||||
if ( -1 == $current_row ) {
|
||||
$migration_progress -= $table_progress;
|
||||
$migration_progress += $table_rows[ $table ];
|
||||
} else {
|
||||
if ( 0 === $table_progress_last ) {
|
||||
$table_progress_last = $current_row;
|
||||
$table_progress = $table_progress_last;
|
||||
$migration_progress += $table_progress_last;
|
||||
} else {
|
||||
$iteration_progress = $current_row - $table_progress_last;
|
||||
$table_progress_last = $current_row;
|
||||
$table_progress += $iteration_progress;
|
||||
$migration_progress += $iteration_progress;
|
||||
}
|
||||
}
|
||||
|
||||
$increment = $migration_progress - $last_migration_progress;
|
||||
|
||||
$notify->tick( $increment );
|
||||
|
||||
} while ( -1 != $current_row );
|
||||
}
|
||||
|
||||
$notify->finish();
|
||||
|
||||
++$stage_iterator;
|
||||
$args['stage'] = 'migrate';
|
||||
$tables = $tables_to_migrate;
|
||||
$table_rows = $this->get_row_counts_from_table_list( $tables, $stage_iterator );
|
||||
|
||||
if ( $stage_iterator < 3 ) {
|
||||
$notify = $this->get_progress_bar( $tables, $stage_iterator );
|
||||
}
|
||||
} while ( $stage_iterator < 3 );
|
||||
|
||||
$this->post_data = $args;
|
||||
|
||||
return $tables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalize migration
|
||||
*
|
||||
* @return bool|WP_Error
|
||||
*/
|
||||
function finalize_migration() {
|
||||
do_action( 'wpmdb_cli_before_finalize_migration', $this->profile, $this->migration );
|
||||
|
||||
WP_CLI::log( __( 'Cleaning up...', 'wp-migrate-db-cli' ) );
|
||||
|
||||
$finalize = apply_filters( 'wpmdb_cli_finalize_migration', true, $this->profile, $this->migration );
|
||||
if ( is_wp_error( $finalize ) ) {
|
||||
return $finalize;
|
||||
}
|
||||
|
||||
$this->post_data = apply_filters( 'wpmdb_cli_finalize_migration_args', $this->post_data, $this->profile, $this->migration );
|
||||
|
||||
if ( 'savefile' === $this->post_data['intent'] ) {
|
||||
return $this->finalize_export();
|
||||
}
|
||||
|
||||
$response = null;
|
||||
$response = apply_filters( 'wpmdb_cli_finalize_migration_response', $response );
|
||||
if ( ! empty( $response ) && '1' !== $response ) {
|
||||
return $this->cli_error( $response );
|
||||
}
|
||||
|
||||
do_action( 'wpmdb_cli_after_finalize_migration', $this->profile, $this->migration );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stub for ajax_initiate_migration()
|
||||
*
|
||||
* @param array|bool $args
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function initiate_migration( $args = false ) {
|
||||
$_POST = $args;
|
||||
$response = $this->wpmdb->ajax_initiate_migration();
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* stub for ajax_migrate_table()
|
||||
*
|
||||
* @param array|bool $args
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function migrate_table( $args = false ) {
|
||||
$_POST = $args;
|
||||
$response = $this->wpmdb->ajax_migrate_table();
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stub for ajax_finalize_migration()
|
||||
* hooks on: wpmdb_cli_finalize_migration_response
|
||||
*
|
||||
* @param string $response
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function finalize_ajax( $response ) {
|
||||
// don't send redundant POST variables
|
||||
$args = $this->filter_post_elements( $this->post_data, array( 'action', 'migration_state_id', 'prefix', 'tables' ) );
|
||||
$_POST = $args;
|
||||
$response = $this->wpmdb->ajax_finalize_migration();
|
||||
|
||||
return trim( $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalize Export by moving file to specified destination
|
||||
*
|
||||
* @return string|error
|
||||
*/
|
||||
function finalize_export() {
|
||||
$state_data = $this->wpmdb->state_data;
|
||||
$temp_file = $state_data['dump_path'];
|
||||
if ( 'ORIGIN' === $state_data['export_dest'] ) {
|
||||
$response = $temp_file;
|
||||
} else {
|
||||
$dest_file = $state_data['export_dest'];
|
||||
if ( file_exists( $temp_file ) && rename( $temp_file, $dest_file ) ) {
|
||||
$response = $dest_file;
|
||||
} else {
|
||||
$response = $this->cli_error( __( 'Unable to move exported file.', 'wp-migrate-db' ) );
|
||||
}
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
/**
|
||||
* Returns array of CLI options that are unknown to plugin and addons.
|
||||
*
|
||||
* @param array $assoc_args
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_unknown_args( $assoc_args = array() ) {
|
||||
$unknown_args = array();
|
||||
|
||||
if ( empty( $assoc_args ) ) {
|
||||
return $unknown_args;
|
||||
}
|
||||
|
||||
$known_args = array(
|
||||
'action',
|
||||
'export_dest',
|
||||
'find',
|
||||
'replace',
|
||||
'exclude-spam',
|
||||
'gzip-file',
|
||||
'exclude-post-revisions',
|
||||
'skip-replace-guids',
|
||||
'include-transients',
|
||||
);
|
||||
|
||||
$known_args = apply_filters( 'wpmdb_cli_filter_get_extra_args', $known_args );
|
||||
$unknown_args = array_diff( array_keys( $assoc_args ), $known_args );
|
||||
|
||||
return $unknown_args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get profile data from CLI args.
|
||||
*
|
||||
* @param array $args
|
||||
* @param array $assoc_args
|
||||
*
|
||||
* @return array|WP_Error
|
||||
*/
|
||||
public function get_profile_data_from_args( $args, $assoc_args ) {
|
||||
|
||||
//load correct cli class
|
||||
if ( function_exists( 'wp_migrate_db_pro_cli_addon' ) ) {
|
||||
$wpmdb_cli = wp_migrate_db_pro_cli_addon();
|
||||
} elseif ( function_exists( 'wpmdb_pro_cli' ) ) {
|
||||
$wpmdb_cli = wpmdb_pro_cli();
|
||||
} else {
|
||||
$wpmdb_cli = wpmdb_cli();
|
||||
}
|
||||
|
||||
$unknown_args = $this->get_unknown_args( $assoc_args );
|
||||
|
||||
if ( ! empty( $unknown_args ) ) {
|
||||
$message = __( 'Parameter errors: ', 'wp-migrate-db-cli' );
|
||||
foreach ( $unknown_args as $unknown_arg ) {
|
||||
$message .= "\n " . sprintf( __( 'unknown %s parameter', 'wp-migrate-db-cli' ), '--' . $unknown_arg );
|
||||
}
|
||||
|
||||
if ( is_a( $wpmdb_cli, 'WPMDBPro_CLI' ) ) {
|
||||
$message .= "\n" . __( 'Please make sure that you have activated the appropriate addons for WP Migrate DB Pro.', 'wp-migrate-db-cli' );
|
||||
}
|
||||
|
||||
return $wpmdb_cli->cli_error( $message );
|
||||
}
|
||||
|
||||
if ( empty( $assoc_args['action'] ) ) {
|
||||
return $wpmdb_cli->cli_error( __( 'Missing action parameter', 'wp-migrate-db-cli' ) );
|
||||
}
|
||||
|
||||
if ( 'savefile' === $assoc_args['action'] && ! empty( $assoc_args['export_dest'] ) ) {
|
||||
$export_dest = $assoc_args['export_dest'];
|
||||
}
|
||||
|
||||
$action = $assoc_args['action'];
|
||||
|
||||
// --find=<old> and --replace=<new>
|
||||
$replace_old = array();
|
||||
$replace_new = array();
|
||||
if ( ! empty( $assoc_args['find'] ) ) {
|
||||
$replace_old = str_getcsv( $assoc_args['find'] );
|
||||
} else {
|
||||
if ( 'find_replace' === $assoc_args['action'] ) {
|
||||
return $wpmdb_cli->cli_error( __( 'Missing find and replace values.', 'wp-migrate-db-cli' ) );
|
||||
}
|
||||
}
|
||||
if ( ! empty( $assoc_args['replace'] ) ) {
|
||||
$replace_new = str_getcsv( $assoc_args['replace'] );
|
||||
}
|
||||
if ( count( $replace_old ) !== count( $replace_new ) ) {
|
||||
return $wpmdb_cli->cli_error( sprintf( __( '%1$s and %2$s must contain the same number of values', 'wp-migrate-db-cli' ), '--find', '--replace' ) );
|
||||
}
|
||||
array_unshift( $replace_old, '' );
|
||||
array_unshift( $replace_new, '' );
|
||||
|
||||
// --exclude-spam
|
||||
$exclude_spam = intval( isset( $assoc_args['exclude-spam'] ) );
|
||||
|
||||
// --gzip-file
|
||||
$gzip_file = intval( isset( $assoc_args['gzip-file'] ) );
|
||||
|
||||
$select_post_types = array();
|
||||
|
||||
// --exclude-post-revisions
|
||||
if ( ! empty( $assoc_args['exclude-post-revisions'] ) ) {
|
||||
$select_post_types[] = 'revision';
|
||||
}
|
||||
|
||||
$exclude_post_types = count( $select_post_types ) > 0 ? 1 : 0;
|
||||
|
||||
// --skip-replace-guids
|
||||
$replace_guids = 1;
|
||||
if ( isset( $assoc_args['skip-replace-guids'] ) ) {
|
||||
$replace_guids = 0;
|
||||
}
|
||||
|
||||
$select_tables = array();
|
||||
$table_migrate_option = 'migrate_only_with_prefix';
|
||||
|
||||
// --include-transients.
|
||||
$exclude_transients = intval( ! isset( $assoc_args['include-transients'] ) );
|
||||
|
||||
//cleanup filename for exports
|
||||
if ( ! empty( $export_dest ) ) {
|
||||
if ( $gzip_file ) {
|
||||
if ( 'gz' !== pathinfo( $export_dest, PATHINFO_EXTENSION ) ) {
|
||||
if ( 'sql' === pathinfo( $export_dest, PATHINFO_EXTENSION ) ) {
|
||||
$export_dest .= '.gz';
|
||||
} else {
|
||||
$export_dest .= '.sql.gz';
|
||||
}
|
||||
}
|
||||
} elseif ( 'sql' !== pathinfo( $export_dest, PATHINFO_EXTENSION ) ) {
|
||||
$export_dest = preg_replace( '/(\.sql)?(\.gz)?$/i', '', $export_dest ) . '.sql';
|
||||
}
|
||||
|
||||
// ensure export destination is writable
|
||||
if ( ! @touch( $export_dest ) ) {
|
||||
return $wpmdb_cli->cli_error( sprintf( __( 'Cannot write to file "%1$s". Please ensure that the specified directory exists and is writable.', 'wp-migrate-db-cli' ), $export_dest ) );
|
||||
}
|
||||
}
|
||||
|
||||
$profile = compact( 'action', 'replace_old', 'table_migrate_option', 'replace_new', 'select_tables', 'exclude_post_types', 'select_post_types', 'replace_guids', 'exclude_spam', 'gzip_file', 'exclude_transients', 'export_dest' );
|
||||
|
||||
$profile = apply_filters( 'wpmdb_cli_filter_get_profile_data_from_args', $profile, $args, $assoc_args );
|
||||
|
||||
return $profile;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Migrate your DB using WP Migrate DB.
|
||||
*/
|
||||
class WPMDB_Command extends WP_CLI_Command {
|
||||
|
||||
/**
|
||||
* Export local DB to file.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* <output-file>
|
||||
* : A file path to export to. Filename will be modified to end in .sql or
|
||||
* .sql.gz if necessary.
|
||||
*
|
||||
* [--find=<strings>]
|
||||
* : A comma separated list of strings to find when performing a string find
|
||||
* and replace across the database.
|
||||
*
|
||||
* Table names should be quoted as needed, i.e. when using a comma in the
|
||||
* find/replace string.
|
||||
*
|
||||
* The --replace=<strings> argument should be used in conjunction to specify
|
||||
* the replace values for the strings found using this argument. The number
|
||||
* of strings specified in this argument should match the number passed into
|
||||
* --replace=<strings> argument.
|
||||
*
|
||||
* [--replace=<strings>]
|
||||
* : A comma separated list of replace value strings to implement when
|
||||
* performing a string find & replace across the database.
|
||||
*
|
||||
* Should be used in conjunction with the --find=<strings> argument, see it's
|
||||
* documentation for further explanation of the find & replace functionality.
|
||||
*
|
||||
* [--exclude-post-revisions]
|
||||
* : Exclude post revisions from export.
|
||||
*
|
||||
* [--skip-replace-guids]
|
||||
* : Do not perform a find & replace on the guid column in the wp_posts table.
|
||||
*
|
||||
* [--exclude-spam]
|
||||
* : Exclude spam comments.
|
||||
*
|
||||
* [--gzip-file]
|
||||
* : GZip compress export file.
|
||||
*
|
||||
* [--include-transients]
|
||||
* : Include transients (temporary cached data).
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp migratedb export ./migratedb.sql \
|
||||
* --find=http://dev.bradt.ca,/Users/bradt/home/bradt.ca
|
||||
* --replace=http://bradt.ca,/home/bradt.ca
|
||||
*
|
||||
* @param array $args
|
||||
* @param array $assoc_args
|
||||
*/
|
||||
public function export( $args, $assoc_args ) {
|
||||
|
||||
$assoc_args['action'] = 'savefile';
|
||||
$assoc_args['export_dest'] = trim( $args[0] );
|
||||
|
||||
if ( empty( $assoc_args['export_dest'] ) ) {
|
||||
WP_CLI::error( WPMDB_CLI::cleanup_message( __( 'You must provide a destination filename.', 'wp-migrate-db-cli' ) ) );
|
||||
}
|
||||
|
||||
$profile = $this->_get_profile_data_from_args( $args, $assoc_args );
|
||||
|
||||
if ( is_wp_error( $profile ) ) {
|
||||
WP_CLI::error( $profile );
|
||||
}
|
||||
|
||||
$this->_perform_cli_migration( $profile );
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a find/replace on the database.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* [--find=<strings>]
|
||||
* : A comma separated list of strings to find when performing a string find
|
||||
* and replace across the database.
|
||||
*
|
||||
* Table names should be quoted as needed, i.e. when using a comma in the
|
||||
* find/replace string.
|
||||
*
|
||||
* The --replace=<strings> argument should be used in conjunction to specify
|
||||
* the replace values for the strings found using this argument. The number
|
||||
* of strings specified in this argument should match the number passed into
|
||||
* --replace=<strings> argument.
|
||||
*
|
||||
* [--replace=<strings>]
|
||||
* : A comma separated list of replace value strings to implement when
|
||||
* performing a string find & replace across the database.
|
||||
*
|
||||
* Should be used in conjunction with the --find=<strings> argument, see it's
|
||||
* documentation for further explanation of the find & replace functionality.
|
||||
*
|
||||
* [--exclude-post-revisions]
|
||||
* : Exclude post revisions from the find & replace.
|
||||
*
|
||||
* [--skip-replace-guids]
|
||||
* : Do not perform a find & replace on the guid column in the wp_posts table.
|
||||
*
|
||||
* [--exclude-spam]
|
||||
* : Exclude spam comments.
|
||||
*
|
||||
* [--include-transients]
|
||||
* : Include transients (temporary cached data).
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp migratedb find-replace
|
||||
* --find=http://dev.bradt.ca,/Users/bradt/home/bradt.ca
|
||||
* --replace=http://bradt.ca,/home/bradt.ca
|
||||
*
|
||||
* @param array $args
|
||||
* @param array $assoc_args
|
||||
*
|
||||
* @subcommand find-replace
|
||||
*/
|
||||
public function find_replace( $args, $assoc_args ) {
|
||||
|
||||
$assoc_args['action'] = 'find_replace';
|
||||
|
||||
$profile = $this->_get_profile_data_from_args( $args, $assoc_args );
|
||||
|
||||
if ( is_wp_error( $profile ) ) {
|
||||
WP_CLI::error( $profile );
|
||||
}
|
||||
|
||||
$this->_perform_cli_migration( $profile );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get profile data from CLI args.
|
||||
*
|
||||
* @param array $args
|
||||
* @param array $assoc_args
|
||||
*
|
||||
* @return array|WP_Error
|
||||
*/
|
||||
protected function _get_profile_data_from_args( $args, $assoc_args ) {
|
||||
// Load the correct CLI class
|
||||
if ( function_exists( 'wpmdb_pro_cli' ) ) {
|
||||
if ( function_exists( 'wp_migrate_db_pro_cli_addon' ) ) {
|
||||
$wpmdb_cli = wp_migrate_db_pro_cli_addon();
|
||||
} else {
|
||||
$wpmdb_cli = wpmdb_pro_cli();
|
||||
}
|
||||
} else {
|
||||
$wpmdb_cli = wpmdb_cli();
|
||||
}
|
||||
|
||||
return $wpmdb_cli->get_profile_data_from_args( $args, $assoc_args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform CLI migration.
|
||||
*
|
||||
* @param mixed $profile Profile key or array
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function _perform_cli_migration( $profile ) {
|
||||
$wpmdb_cli = null;
|
||||
|
||||
//load correct cli class
|
||||
if ( function_exists( 'wpmdb_pro_cli' ) ) {
|
||||
$wpmdb_cli = wpmdb_pro_cli();
|
||||
} else {
|
||||
$wpmdb_cli = wpmdb_cli();
|
||||
}
|
||||
|
||||
if ( empty( $wpmdb_cli ) ) {
|
||||
WP_CLI::error( __( 'WP Migrate DB CLI class not available.', 'wp-migrate-db-cli' ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$result = $wpmdb_cli->cli_migration( $profile );
|
||||
|
||||
if ( ! is_wp_error( $result ) ) {
|
||||
$success_msg = sprintf( __( 'Export saved to: %s', 'wp-migrate-db-cli' ), $result );
|
||||
|
||||
if ( 'find_replace' === $profile['action'] ) {
|
||||
$success_msg = __( 'Find & Replace complete', 'wp-migrate-db-cli' );
|
||||
}
|
||||
|
||||
WP_CLI::success( $success_msg );
|
||||
} elseif ( is_wp_error( $result ) ) {
|
||||
WP_CLI::error( WPMDB_CLI::cleanup_message( $result->get_error_message() ) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
WP_CLI::add_command( 'migratedb', 'WPMDB_Command' );
|
||||
@@ -0,0 +1,561 @@
|
||||
<?php
|
||||
|
||||
class WPMDB_Filesystem {
|
||||
|
||||
private $wp_filesystem;
|
||||
private $credentials;
|
||||
private $use_filesystem = false;
|
||||
private $chmod_dir;
|
||||
private $chmod_file;
|
||||
|
||||
/**
|
||||
* Pass `true` when instantiating to skip using WP_Filesystem
|
||||
*
|
||||
* @param bool $force_no_fs
|
||||
*/
|
||||
public function __construct( $force_no_fs = false ) {
|
||||
if ( ! $force_no_fs && function_exists( 'request_filesystem_credentials' ) ) {
|
||||
if ( ( defined( 'WPMDB_WP_FILESYSTEM' ) && WPMDB_WP_FILESYSTEM ) || ! defined( 'WPMDB_WP_FILESYSTEM' ) ) {
|
||||
$this->maybe_init_wp_filesystem();
|
||||
}
|
||||
}
|
||||
|
||||
// Set default permissions
|
||||
if ( defined( 'FS_CHMOD_DIR' ) ) {
|
||||
$this->chmod_dir = FS_CHMOD_DIR;
|
||||
} else {
|
||||
$this->chmod_dir = ( fileperms( ABSPATH ) & 0777 | 0755 );
|
||||
}
|
||||
|
||||
if ( defined( 'FS_CHMOD_FILE' ) ) {
|
||||
$this->chmod_file = FS_CHMOD_FILE;
|
||||
} else {
|
||||
$this->chmod_file = ( fileperms( ABSPATH . 'index.php' ) & 0777 | 0644 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the instantiated WP_Filesystem
|
||||
*
|
||||
* @return WP_Filesystem|false
|
||||
*
|
||||
* This should be used carefully since $wp_filesystem won't always have a value.
|
||||
*/
|
||||
public function get_wp_filesystem() {
|
||||
if ( $this->use_filesystem ) {
|
||||
return $this->wp_filesystem;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is WP_Filesystem being used?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function using_wp_filesystem() {
|
||||
return $this->use_filesystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to use the correct path for the FS method being used
|
||||
*
|
||||
* @param string $abs_path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_sanitized_path( $abs_path ) {
|
||||
if ( $this->using_wp_filesystem() ) {
|
||||
return str_replace( ABSPATH, $this->wp_filesystem->abspath(), $abs_path );
|
||||
}
|
||||
|
||||
return $abs_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to initiate WP_Filesystem
|
||||
*
|
||||
* If this fails, $use_filesystem is set to false and all methods in this class should use native php fallbacks
|
||||
* Thwarts `request_filesystem_credentials()` attempt to display a form for obtaining creds from users
|
||||
*
|
||||
* TODO: provide notice and input in wp-admin for users when this fails
|
||||
*/
|
||||
public function maybe_init_wp_filesystem() {
|
||||
ob_start();
|
||||
$this->credentials = request_filesystem_credentials( '', '', false, false, null );
|
||||
$ob_contents = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
if ( wp_filesystem( $this->credentials ) ) {
|
||||
global $wp_filesystem;
|
||||
$this->wp_filesystem = $wp_filesystem;
|
||||
$this->use_filesystem = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create file if not exists then set mtime and atime on file
|
||||
*
|
||||
* @param string $abs_path
|
||||
* @param int $time
|
||||
* @param int $atime
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function touch( $abs_path, $time = 0, $atime = 0 ) {
|
||||
if ( 0 == $time ) {
|
||||
$time = time();
|
||||
}
|
||||
if ( 0 == $atime ) {
|
||||
$atime = time();
|
||||
}
|
||||
|
||||
$return = @touch( $abs_path, $time, $atime );
|
||||
|
||||
if ( ! $return && $this->use_filesystem ) {
|
||||
$abs_path = $this->get_sanitized_path( $abs_path );
|
||||
$return = $this->wp_filesystem->touch( $abs_path, $time, $atime );
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* file_put_contents with chmod
|
||||
*
|
||||
* @param string $abs_path
|
||||
* @param string $contents
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function put_contents( $abs_path, $contents ) {
|
||||
$return = @file_put_contents( $abs_path, $contents );
|
||||
$this->chmod( $abs_path );
|
||||
|
||||
if ( ! $return && $this->use_filesystem ) {
|
||||
$abs_path = $this->get_sanitized_path( $abs_path );
|
||||
$return = $this->wp_filesystem->put_contents( $abs_path, $contents, $this->chmod_file );
|
||||
}
|
||||
|
||||
return (bool) $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the specified file or dir exist
|
||||
*
|
||||
* @param string $abs_path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function file_exists( $abs_path ) {
|
||||
$return = file_exists( $abs_path );
|
||||
|
||||
if ( ! $return && $this->use_filesystem ) {
|
||||
$abs_path = $this->get_sanitized_path( $abs_path );
|
||||
$return = $this->wp_filesystem->exists( $abs_path );
|
||||
}
|
||||
|
||||
return (bool) $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a file's size
|
||||
*
|
||||
* @param string $abs_path
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function filesize( $abs_path ) {
|
||||
$return = filesize( $abs_path );
|
||||
|
||||
if ( ! $return && $this->use_filesystem ) {
|
||||
$abs_path = $this->get_sanitized_path( $abs_path );
|
||||
$return = $this->wp_filesystem->size( $abs_path );
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contents of a file as a string
|
||||
*
|
||||
* @param string $abs_path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_contents( $abs_path ) {
|
||||
$return = @file_get_contents( $abs_path );
|
||||
|
||||
if ( ! $return && $this->use_filesystem ) {
|
||||
$abs_path = $this->get_sanitized_path( $abs_path );
|
||||
$return = $this->wp_filesystem->get_contents( $abs_path );
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a file
|
||||
*
|
||||
* @param string $abs_path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function unlink( $abs_path ) {
|
||||
$return = @unlink( $abs_path );
|
||||
|
||||
if ( ! $return && $this->use_filesystem ) {
|
||||
$abs_path = $this->get_sanitized_path( $abs_path );
|
||||
$return = $this->wp_filesystem->delete( $abs_path, false, false );
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* chmod a file
|
||||
*
|
||||
* @param string $abs_path
|
||||
* @param int $perms
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* Leave $perms blank to use $this->chmod_file/DIR or pass value like 0777
|
||||
*/
|
||||
public function chmod( $abs_path, $perms = null ) {
|
||||
if ( is_null( $perms ) ) {
|
||||
$perms = $this->is_file( $abs_path ) ? $this->chmod_file : $this->chmod_dir;
|
||||
}
|
||||
|
||||
$return = @chmod( $abs_path, $perms );
|
||||
|
||||
if ( ! $return && $this->use_filesystem ) {
|
||||
$abs_path = $this->get_sanitized_path( $abs_path );
|
||||
$return = $this->wp_filesystem->chmod( $abs_path, $perms, false );
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the specified pat a directory?
|
||||
*
|
||||
* @param string $abs_path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_dir( $abs_path ) {
|
||||
$return = is_dir( $abs_path );
|
||||
|
||||
if ( ! $return && $this->use_filesystem ) {
|
||||
$abs_path = $this->get_sanitized_path( $abs_path );
|
||||
$return = $this->wp_filesystem->is_dir( $abs_path );
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the specified path a file?
|
||||
*
|
||||
* @param string $abs_path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_file( $abs_path ) {
|
||||
$return = is_file( $abs_path );
|
||||
|
||||
if ( ! $return && $this->use_filesystem ) {
|
||||
$abs_path = $this->get_sanitized_path( $abs_path );
|
||||
$return = $this->wp_filesystem->is_file( $abs_path );
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the specified path readable
|
||||
*
|
||||
* @param string $abs_path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_readable( $abs_path ) {
|
||||
$return = is_readable( $abs_path );
|
||||
|
||||
if ( ! $return && $this->use_filesystem ) {
|
||||
$abs_path = $this->get_sanitized_path( $abs_path );
|
||||
$return = $this->wp_filesystem->is_readable( $abs_path );
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the specified path writable
|
||||
*
|
||||
* @param string $abs_path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_writable( $abs_path ) {
|
||||
$return = is_writable( $abs_path );
|
||||
|
||||
if ( ! $return && $this->use_filesystem ) {
|
||||
$abs_path = $this->get_sanitized_path( $abs_path );
|
||||
$return = $this->wp_filesystem->is_writable( $abs_path );
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive mkdir
|
||||
*
|
||||
* @param string $abs_path
|
||||
* @param int $perms
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function mkdir( $abs_path, $perms = null ) {
|
||||
if ( is_null( $perms ) ) {
|
||||
$perms = $this->chmod_dir;
|
||||
}
|
||||
|
||||
if ( $this->is_dir( $abs_path ) ) {
|
||||
$this->chmod( $perms );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
$mkdirp = wp_mkdir_p( $abs_path );
|
||||
} catch ( Exception $e ) {
|
||||
$mkdirp = false;
|
||||
}
|
||||
|
||||
if ( $mkdirp ) {
|
||||
$this->chmod( $perms );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$return = @mkdir( $abs_path, $perms, true );
|
||||
|
||||
if ( ! $return && $this->use_filesystem ) {
|
||||
$abs_path = $this->get_sanitized_path( $abs_path );
|
||||
|
||||
if ( $this->is_dir( $abs_path ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// WP_Filesystem doesn't offer a recursive mkdir()
|
||||
$abs_path = str_replace( '//', '/', $abs_path );
|
||||
$abs_path = rtrim( $abs_path, '/' );
|
||||
if ( empty( $abs_path ) ) {
|
||||
$abs_path = '/';
|
||||
}
|
||||
|
||||
$dirs = explode( '/', ltrim( $abs_path, '/' ) );
|
||||
$current_dir = '';
|
||||
|
||||
foreach ( $dirs as $dir ) {
|
||||
$current_dir .= '/' . $dir;
|
||||
if ( ! $this->is_dir( $current_dir ) ) {
|
||||
$this->wp_filesystem->mkdir( $current_dir, $perms );
|
||||
}
|
||||
}
|
||||
|
||||
$return = $this->is_dir( $abs_path );
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a directory
|
||||
*
|
||||
* @param string $abs_path
|
||||
* @param bool $recursive
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function rmdir( $abs_path, $recursive = false ) {
|
||||
if ( ! $this->is_dir( $abs_path ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// taken from WP_Filesystem_Direct
|
||||
if ( ! $recursive ) {
|
||||
$return = @rmdir( $abs_path );
|
||||
} else {
|
||||
|
||||
// At this point it's a folder, and we're in recursive mode
|
||||
$abs_path = trailingslashit( $abs_path );
|
||||
$filelist = $this->scandir( $abs_path );
|
||||
|
||||
$return = true;
|
||||
if ( is_array( $filelist ) ) {
|
||||
foreach ( $filelist as $filename => $fileinfo ) {
|
||||
|
||||
if ( 'd' === $fileinfo['type'] ) {
|
||||
$return = $this->rmdir( $abs_path . $filename, $recursive );
|
||||
} else {
|
||||
$return = $this->unlink( $abs_path . $filename );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( file_exists( $abs_path ) && ! @rmdir( $abs_path ) ) {
|
||||
$return = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $return && $this->use_filesystem ) {
|
||||
$abs_path = $this->get_sanitized_path( $abs_path );
|
||||
|
||||
return $this->wp_filesystem->rmdir( $abs_path, $recursive );
|
||||
}
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of files/folders under specified directory
|
||||
*
|
||||
* @param $abs_path
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public function scandir( $abs_path ) {
|
||||
|
||||
$dirlist = @scandir( $abs_path );
|
||||
if ( false === $dirlist ) {
|
||||
if ( $this->use_filesystem ) {
|
||||
$abs_path = $this->get_sanitized_path( $abs_path );
|
||||
|
||||
return $this->wp_filesystem->dirlist( $abs_path, true, false );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$return = array();
|
||||
|
||||
// normalize return to look somewhat like the return value for WP_Filesystem::dirlist
|
||||
foreach ( $dirlist as $entry ) {
|
||||
if ( '.' === $entry || '..' === $entry ) {
|
||||
continue;
|
||||
}
|
||||
$return[ $entry ] = array(
|
||||
'name' => $entry,
|
||||
'type' => $this->is_dir( $abs_path . '/' . $entry ) ? 'd' : 'f',
|
||||
);
|
||||
}
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Light wrapper for move_uploaded_file with chmod
|
||||
*
|
||||
* @param string $file
|
||||
* @param string $destination
|
||||
* @param int $perms
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* TODO: look into replicating more functionality from wp_handle_upload()
|
||||
*/
|
||||
public function move_uploaded_file( $file, $destination, $perms = null ) {
|
||||
$return = @move_uploaded_file( $file, $destination );
|
||||
|
||||
if ( $return ) {
|
||||
$this->chmod( $destination, $perms );
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a file
|
||||
*
|
||||
* @param string $source_abs_path
|
||||
* @param string $destination_abs_path
|
||||
* @param bool $overwrite
|
||||
* @param int $perms
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* Taken from WP_Filesystem_Direct
|
||||
*/
|
||||
public function copy( $source_abs_path, $destination_abs_path, $overwrite = true, $perms = false ) {
|
||||
|
||||
// error if source file doesn't exist
|
||||
if ( ! $this->file_exists( $source_abs_path ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! $overwrite && $this->file_exists( $destination_abs_path ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$return = copy( $source_abs_path, $destination_abs_path );
|
||||
if ( $perms && $return ) {
|
||||
$this->chmod( $destination_abs_path, $perms );
|
||||
}
|
||||
|
||||
if ( ! $return && $this->use_filesystem ) {
|
||||
$source_abs_path = $this->get_sanitized_path( $source_abs_path );
|
||||
$destination_abs_path = $this->get_sanitized_path( $destination_abs_path );
|
||||
$return = $this->wp_filesystem->copy( $source_abs_path, $destination_abs_path, $overwrite, $perms );
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a file
|
||||
*
|
||||
* @param string $source_abs_path
|
||||
* @param string $destination_abs_path
|
||||
* @param bool $overwrite
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function move( $source_abs_path, $destination_abs_path, $overwrite = true ) {
|
||||
|
||||
// error if source file doesn't exist
|
||||
if ( ! $this->file_exists( $source_abs_path ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try using rename first. if that fails (for example, source is read only) try copy.
|
||||
// Taken in part from WP_Filesystem_Direct
|
||||
if ( ! $overwrite && $this->file_exists( $destination_abs_path ) ) {
|
||||
return false;
|
||||
} elseif ( @rename( $source_abs_path, $destination_abs_path ) ) {
|
||||
return true;
|
||||
} else {
|
||||
if ( $this->copy( $source_abs_path, $destination_abs_path, $overwrite ) && $this->file_exists( $destination_abs_path ) ) {
|
||||
$this->unlink( $source_abs_path );
|
||||
|
||||
return true;
|
||||
} else {
|
||||
$return = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $return && $this->use_filesystem ) {
|
||||
$source_abs_path = $this->get_sanitized_path( $source_abs_path );
|
||||
$destination_abs_path = $this->get_sanitized_path( $destination_abs_path );
|
||||
|
||||
$return = $this->wp_filesystem->move( $source_abs_path, $destination_abs_path, $overwrite );
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
<?php
|
||||
|
||||
class WPMDB_Migration_State {
|
||||
const OPTION_PREFIX = 'wpmdb_state_';
|
||||
const TIMEOUT_PREFIX = 'wpmdb_state_timeout_';
|
||||
const EXPIRATION = 86400; // 60s * 60m * 24h
|
||||
|
||||
private $_value = null;
|
||||
private $_id = null;
|
||||
|
||||
/**
|
||||
* @param string $id
|
||||
*/
|
||||
function __construct( $id = '' ) {
|
||||
if ( ! empty( $id ) ) {
|
||||
$value = get_site_option( $this->_option( $id ), false, false );
|
||||
|
||||
if ( false !== $value ) {
|
||||
$this->_id = $id;
|
||||
$this->_value = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique id of the instance.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function id() {
|
||||
if ( empty( $this->_id ) ) {
|
||||
$this->_id = uniqid();
|
||||
}
|
||||
|
||||
return $this->_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the site option string used to save the migration state.
|
||||
*
|
||||
* @param string $id
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function _option( $id = null ) {
|
||||
if ( empty( $id ) ) {
|
||||
$id = $this->id();
|
||||
}
|
||||
|
||||
return self::OPTION_PREFIX . $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the site option string used to save the migration state timeout.
|
||||
*
|
||||
* @param string $id
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function _timeout_option( $id = null ) {
|
||||
if ( empty( $id ) ) {
|
||||
$id = $this->id();
|
||||
}
|
||||
|
||||
return self::TIMEOUT_PREFIX . $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the migration state.
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function set( $value ) {
|
||||
if ( $this->_update_timeout() && update_site_option( $this->_option(), $value ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If nothing changed it's still OK.
|
||||
if ( $this->get() === $value ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the companion timeout setting to the current migration state option.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function _update_timeout() {
|
||||
$value = time() + self::EXPIRATION;
|
||||
|
||||
if ( update_site_option( $this->_timeout_option(), $value ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If nothing changed it's still OK.
|
||||
if ( get_site_option( $this->_timeout_option(), false, false ) == $value ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current saved migration state.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function get() {
|
||||
return get_site_option( $this->_option(), false, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the site options for migration state and its companion timeout record.
|
||||
*
|
||||
* @param $id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function _delete_id( $id ) {
|
||||
if ( false === get_site_option( self::OPTION_PREFIX . $id, false, false ) || delete_site_option( self::OPTION_PREFIX . $id ) ) {
|
||||
delete_site_option( self::TIMEOUT_PREFIX . $id );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the current migration state.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function delete() {
|
||||
return $this->_delete_id( $this->id() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all migration state ids that have timed out.
|
||||
*
|
||||
* @param int $timeout Optional UNIX timestamp for timeout, default of 0 uses current timestamp.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private static function _timed_out_ids( $timeout = 0 ) {
|
||||
global $wpdb;
|
||||
|
||||
$ids = array();
|
||||
|
||||
if ( empty( $timeout ) ) {
|
||||
$timeout = time();
|
||||
}
|
||||
|
||||
if ( is_multisite() ) {
|
||||
$timeout_keys = $wpdb->get_col(
|
||||
$wpdb->prepare(
|
||||
"SELECT meta_key FROM {$wpdb->sitemeta} WHERE site_id = %d AND meta_key like %s AND meta_value < %d",
|
||||
$wpdb->siteid,
|
||||
addcslashes( self::TIMEOUT_PREFIX, '_' ) . '%',
|
||||
$timeout
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$timeout_keys = $wpdb->get_col(
|
||||
$wpdb->prepare(
|
||||
"SELECT option_name FROM $wpdb->options WHERE option_name LIKE %s and option_value < %d",
|
||||
addcslashes( self::TIMEOUT_PREFIX, '_' ) . '%',
|
||||
$timeout
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! empty( $timeout_keys ) ) {
|
||||
$id_start = strlen( self::TIMEOUT_PREFIX );
|
||||
|
||||
foreach ( $timeout_keys as $timeout_key ) {
|
||||
$ids[] = substr( $timeout_key, $id_start );
|
||||
}
|
||||
}
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all migration state ids that have no time out companion.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private static function _orphaned_ids() {
|
||||
global $wpdb;
|
||||
|
||||
$ids = array();
|
||||
|
||||
if ( is_multisite() ) {
|
||||
$keys = $wpdb->get_col(
|
||||
$wpdb->prepare( "
|
||||
SELECT meta_key
|
||||
FROM {$wpdb->sitemeta}
|
||||
WHERE site_id = %d
|
||||
AND meta_key LIKE %s
|
||||
AND meta_key NOT LIKE %s
|
||||
AND meta_key NOT IN (
|
||||
SELECT CONCAT(%s, SUBSTR(meta_key, %d))
|
||||
FROM {$wpdb->sitemeta}
|
||||
WHERE site_id = %d
|
||||
AND meta_key LIKE %s
|
||||
)
|
||||
",
|
||||
$wpdb->siteid,
|
||||
addcslashes( self::OPTION_PREFIX, '_' ) . '%',
|
||||
addcslashes( self::TIMEOUT_PREFIX, '_' ) . '%',
|
||||
self::OPTION_PREFIX,
|
||||
strlen( self::TIMEOUT_PREFIX ) + 1,
|
||||
$wpdb->siteid,
|
||||
addcslashes( self::TIMEOUT_PREFIX, '_' ) . '%'
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$keys = $wpdb->get_col(
|
||||
$wpdb->prepare( "
|
||||
SELECT option_name
|
||||
FROM $wpdb->options
|
||||
WHERE option_name LIKE %s
|
||||
AND option_name NOT LIKE %s
|
||||
AND option_name NOT IN (
|
||||
SELECT CONCAT(%s, SUBSTR(option_name, %d))
|
||||
FROM $wpdb->options
|
||||
WHERE option_name LIKE %s
|
||||
)
|
||||
",
|
||||
addcslashes( self::OPTION_PREFIX, '_' ) . '%',
|
||||
addcslashes( self::TIMEOUT_PREFIX, '_' ) . '%',
|
||||
self::OPTION_PREFIX,
|
||||
strlen( self::TIMEOUT_PREFIX ) + 1,
|
||||
addcslashes( self::TIMEOUT_PREFIX, '_' ) . '%'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! empty( $keys ) ) {
|
||||
$id_start = strlen( self::OPTION_PREFIX );
|
||||
|
||||
foreach ( $keys as $key ) {
|
||||
$ids[] = substr( $key, $id_start );
|
||||
}
|
||||
}
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns count of all migration state records that have timed out.
|
||||
*
|
||||
* @param int $timeout Optional UNIX timestamp for timeout, default of 0 uses current timestamp.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
static function cleanup_count( $timeout = 0 ) {
|
||||
return count( self::_timed_out_ids( $timeout ) ) + count( self::_orphaned_ids() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all migration state records that have timed out or are orphaned from their timeout companion.
|
||||
*
|
||||
* @param int $timeout Optional UNIX timestamp for timeout, default of 0 uses current timestamp.
|
||||
*
|
||||
* @return int Count of successfully cleaned up options.
|
||||
*/
|
||||
static function cleanup( $timeout = 0 ) {
|
||||
$count = 0;
|
||||
|
||||
$timed_out_ids = self::_timed_out_ids( $timeout );
|
||||
|
||||
if ( ! empty( $timed_out_ids ) ) {
|
||||
foreach ( $timed_out_ids as $id ) {
|
||||
if ( self::_delete_id( $id ) ) {
|
||||
$count ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$orphaned_ids = self::_orphaned_ids();
|
||||
|
||||
if ( ! empty( $orphaned_ids ) ) {
|
||||
foreach ( $orphaned_ids as $id ) {
|
||||
if ( self::_delete_id( $id ) ) {
|
||||
$count ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,365 @@
|
||||
<?php
|
||||
|
||||
final class WPMDB_Replace {
|
||||
protected $search;
|
||||
protected $replace;
|
||||
protected $subdomain_replaces_on;
|
||||
protected $wpmdb;
|
||||
protected $intent;
|
||||
protected $base_domain;
|
||||
protected $site_domain;
|
||||
protected $site_details;
|
||||
protected $source_protocol;
|
||||
protected $destination_protocol;
|
||||
protected $destination_url;
|
||||
protected $is_protocol_mismatch = false;
|
||||
|
||||
private $table;
|
||||
private $column;
|
||||
private $row;
|
||||
|
||||
function __construct( $args ) {
|
||||
$keys = array( 'table', 'search', 'replace', 'intent', 'base_domain', 'site_domain', 'wpmdb', 'site_details' );
|
||||
|
||||
if ( ! is_array( $args ) ) {
|
||||
throw new InvalidArgumentException( 'WPMDB_Replace constructor expects the argument to be an array' );
|
||||
}
|
||||
|
||||
foreach ( $keys as $key ) {
|
||||
if ( ! isset( $args[ $key ] ) ) {
|
||||
throw new InvalidArgumentException( "WPMDB_Replace constructor expects '$key' key to be present in the array argument" );
|
||||
}
|
||||
}
|
||||
|
||||
$this->table = $args['table'];
|
||||
$this->search = $args['search'];
|
||||
$this->replace = $args['replace'];
|
||||
$this->intent = $args['intent'];
|
||||
$this->base_domain = $args['base_domain'];
|
||||
$this->site_domain = $args['site_domain'];
|
||||
$this->wpmdb = $args['wpmdb'];
|
||||
$this->site_details = $args['site_details'];
|
||||
|
||||
// Detect a protocol mismatch between the remote and local sites involved in the migration
|
||||
$this->detect_protocol_mismatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether to apply a subdomain replace over each value in the database.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function is_subdomain_replaces_on() {
|
||||
if ( ! isset( $this->subdomain_replaces_on ) ) {
|
||||
$this->subdomain_replaces_on = ( is_multisite() && is_subdomain_install() && ! $this->has_same_base_domain() && apply_filters( 'wpmdb_subdomain_replace', true ) );
|
||||
}
|
||||
|
||||
return $this->subdomain_replaces_on;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the replacement has the same base domain as the search. Produces doubled replacement strings
|
||||
* otherwise.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function has_same_base_domain() {
|
||||
$destination_url = isset( $this->destination_url ) ? $this->destination_url : $this->site_details['local']['site_url'];
|
||||
if ( stripos( $destination_url, $this->site_domain ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Automatically replace URLs for subdomain based multisite installations
|
||||
* e.g. //site1.example.com -> //site1.example.local for site with domain example.com
|
||||
* NB: only handles the current network site, does not work for additional networks / mapped domains
|
||||
*
|
||||
* @param $new
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function subdomain_replaces( $new ) {
|
||||
if ( empty( $this->base_domain ) ) {
|
||||
return $new;
|
||||
}
|
||||
|
||||
$pattern = '|//(.*?)\\.' . preg_quote( $this->site_domain, '|' ) . '|';
|
||||
$replacement = '//$1.' . trim( $this->base_domain );
|
||||
$new = preg_replace( $pattern, $replacement, $new );
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect a protocol mismatch between the remote and local sites involved in the migration
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function detect_protocol_mismatch() {
|
||||
if ( ! isset( $this->site_details['remote'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the site_urls used to check if there is a protocol mismatch.
|
||||
*
|
||||
* @param array
|
||||
*/
|
||||
$wpmdb_home_urls = apply_filters( 'wpmdb_replace_site_urls', array(
|
||||
// TODO: rewrite unit tests that only pass site_url so that we can rely on home_url's existence
|
||||
'local' => isset( $this->site_details['local']['home_url'] ) ? $this->site_details['local']['home_url'] : $this->site_details['local']['site_url'],
|
||||
'remote' => isset( $this->site_details['remote']['home_url'] ) ? $this->site_details['remote']['home_url'] : $this->site_details['remote']['site_url'],
|
||||
)
|
||||
);
|
||||
|
||||
$local_url_is_https = false === stripos( $wpmdb_home_urls['local'], 'https' ) ? false : true;
|
||||
$remote_url_is_https = false === stripos( $wpmdb_home_urls['remote'], 'https' ) ? false : true;
|
||||
$local_protocol = $local_url_is_https ? 'https' : 'http';
|
||||
$remote_protocol = $remote_url_is_https ? 'https' : 'http';
|
||||
|
||||
if ( ( $local_url_is_https && ! $remote_url_is_https ) || ( ! $local_url_is_https && $remote_url_is_https ) ) {
|
||||
$this->is_protocol_mismatch = true;
|
||||
}
|
||||
|
||||
if ( 'push' === $this->intent ) {
|
||||
$this->destination_protocol = $remote_protocol;
|
||||
$this->source_protocol = $local_protocol;
|
||||
$this->destination_url = $wpmdb_home_urls['remote'];
|
||||
} else {
|
||||
$this->destination_protocol = $local_protocol;
|
||||
$this->source_protocol = $remote_protocol;
|
||||
$this->destination_url = $wpmdb_home_urls['local'];
|
||||
}
|
||||
|
||||
return $this->is_protocol_mismatch;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Handles replacing the protocol if the local and destination don't have matching protocols (http > https and
|
||||
* vice-versa).
|
||||
*
|
||||
* Can be filtered to disable entirely.
|
||||
*
|
||||
* @param $new
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function do_protocol_replace( $new ) {
|
||||
/**
|
||||
* Filters $do_protocol_replace, return false to prevent protocol replacement.
|
||||
*
|
||||
* @param bool true If the replace should be skipped.
|
||||
* @param string $this->destination_url The URL of the target site.
|
||||
*/
|
||||
$do_protocol_replace = apply_filters( 'wpmdb_replace_destination_protocol', true, $this->destination_url );
|
||||
|
||||
if ( true !== $do_protocol_replace ) {
|
||||
return $new;
|
||||
}
|
||||
|
||||
$parsed_destination = wp_parse_url( $this->destination_url );
|
||||
unset( $parsed_destination['scheme'] );
|
||||
|
||||
$protocol_search = $this->source_protocol . '://' . implode( '', $parsed_destination );
|
||||
$protocol_replace = $this->destination_url;
|
||||
$new = str_ireplace( $protocol_search, $protocol_replace, $new, $count );
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies find/replace pairs to a given string.
|
||||
*
|
||||
* @param string $subject
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function apply_replaces( $subject ) {
|
||||
$new = str_ireplace( $this->search, $this->replace, $subject, $count );
|
||||
if ( $this->is_subdomain_replaces_on() ) {
|
||||
$new = $this->subdomain_replaces( $new );
|
||||
}
|
||||
|
||||
if ( true === $this->is_protocol_mismatch ) {
|
||||
$new = $this->do_protocol_replace( $new );
|
||||
}
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a serialized array and unserialize it replacing elements as needed and
|
||||
* unserialising any subordinate arrays and performing the replace on those too.
|
||||
*
|
||||
* Mostly from https://github.com/interconnectit/Search-Replace-DB
|
||||
*
|
||||
* @param mixed $data Used to pass any subordinate arrays back to in.
|
||||
* @param bool $serialized Does the array passed via $data need serialising.
|
||||
* @param bool $parent_serialized Passes whether the original data passed in was serialized
|
||||
* @param bool $filtered Should we apply before and after filters successively
|
||||
*
|
||||
* @return mixed The original array with all elements replaced as needed.
|
||||
*/
|
||||
function recursive_unserialize_replace( $data, $serialized = false, $parent_serialized = false, $filtered = true ) {
|
||||
$pre = apply_filters( 'wpmdb_pre_recursive_unserialize_replace', false, $data, $this );
|
||||
if ( false !== $pre ) {
|
||||
return $pre;
|
||||
}
|
||||
|
||||
$is_json = false;
|
||||
$before_fired = false;
|
||||
$successive_filter = $filtered;
|
||||
|
||||
if ( true === $filtered ) {
|
||||
list( $data, $before_fired, $successive_filter ) = apply_filters( 'wpmdb_before_replace_custom_data', array( $data, $before_fired, $successive_filter ), $this );
|
||||
}
|
||||
|
||||
// some unserialized data cannot be re-serialized eg. SimpleXMLElements
|
||||
try {
|
||||
if ( is_string( $data ) && ( $unserialized = WPMDB_Utils::unserialize( $data, __METHOD__ ) ) !== false ) {
|
||||
// PHP currently has a bug that doesn't allow you to clone the DateInterval / DatePeriod classes.
|
||||
// We skip them here as they probably won't need data to be replaced anyway
|
||||
if ( is_object( $unserialized ) ) {
|
||||
if ( $unserialized instanceof DateInterval || $unserialized instanceof DatePeriod ) {
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
$data = $this->recursive_unserialize_replace( $unserialized, true, true, $successive_filter );
|
||||
} elseif ( is_array( $data ) ) {
|
||||
$_tmp = array();
|
||||
foreach ( $data as $key => $value ) {
|
||||
$_tmp[ $key ] = $this->recursive_unserialize_replace( $value, false, $parent_serialized, $successive_filter );
|
||||
}
|
||||
|
||||
$data = $_tmp;
|
||||
unset( $_tmp );
|
||||
} elseif ( is_object( $data ) ) { // Submitted by Tina Matter
|
||||
$_tmp = clone $data;
|
||||
foreach ( $data as $key => $value ) {
|
||||
// Integer properties are crazy and the best thing we can do is to just ignore them.
|
||||
// see http://stackoverflow.com/a/10333200 and https://github.com/deliciousbrains/wp-migrate-db-pro/issues/853
|
||||
if ( is_int( $key ) ) {
|
||||
continue;
|
||||
}
|
||||
$_tmp->$key = $this->recursive_unserialize_replace( $value, false, $parent_serialized, $successive_filter );
|
||||
}
|
||||
|
||||
$data = $_tmp;
|
||||
unset( $_tmp );
|
||||
} elseif ( $this->wpmdb->is_json( $data, true ) ) {
|
||||
$_tmp = array();
|
||||
$data = json_decode( $data, true );
|
||||
|
||||
foreach ( $data as $key => $value ) {
|
||||
$_tmp[ $key ] = $this->recursive_unserialize_replace( $value, false, $parent_serialized, $successive_filter );
|
||||
}
|
||||
|
||||
$data = $_tmp;
|
||||
unset( $_tmp );
|
||||
$is_json = true;
|
||||
} elseif ( is_string( $data ) ) {
|
||||
list( $data, $do_replace ) = apply_filters( 'wpmdb_replace_custom_data', array( $data, true ), $this );
|
||||
|
||||
if ( $do_replace ) {
|
||||
$data = $this->apply_replaces( $data );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $is_json ) {
|
||||
$data = json_encode( $data );
|
||||
}
|
||||
|
||||
if ( $serialized ) {
|
||||
$data = serialize( $data );
|
||||
}
|
||||
} catch ( Exception $error ) {
|
||||
$error_msg = __( 'Failed attempting to do the recursive unserialize replace. Please contact support.', 'wp-migrate-db' );
|
||||
$error_details = $error->getMessage() . "\n\n";
|
||||
$error_details .= var_export( $data, true );
|
||||
$this->wpmdb->log_error( $error_msg, $error_details );
|
||||
}
|
||||
|
||||
if ( true === $filtered ) {
|
||||
$data = apply_filters( 'wpmdb_after_replace_custom_data', $data, $before_fired, $this );
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the $table class property.
|
||||
*
|
||||
* @return string Name of the table currently being processed in the migration.
|
||||
*/
|
||||
public function get_table() {
|
||||
return $this->table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the $column class property.
|
||||
*
|
||||
* @return string Name of the column currently being processed in the migration.
|
||||
*/
|
||||
public function get_column() {
|
||||
return $this->column;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the $row class property.
|
||||
*
|
||||
* @return string Name of the row currently being processed in the migration.
|
||||
*/
|
||||
public function get_row() {
|
||||
return $this->row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the $column class property.
|
||||
*
|
||||
* @param string $column Name of the column currently being processed in the migration.
|
||||
*/
|
||||
public function set_column( $column ) {
|
||||
$this->column = $column;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the $row class property.
|
||||
*
|
||||
* @param string $row Name of the row currently being processed in the migration.
|
||||
*/
|
||||
public function set_row( $row ) {
|
||||
$this->row = $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multsite safe way of comparing the table currently being processed in the migration against a desired table.
|
||||
*
|
||||
* The table prefix should be omitted, example:
|
||||
*
|
||||
* $is_posts = $this->table_is( 'posts' );
|
||||
*
|
||||
* @param string $desired_table Name of the desired table, table prefix omitted.
|
||||
*
|
||||
* @return boolean Whether or not the desired table is the table currently being processed.
|
||||
*/
|
||||
public function table_is( $desired_table ) {
|
||||
return $this->wpmdb->table_is( $desired_table, $this->table );
|
||||
}
|
||||
|
||||
/**
|
||||
* Intent of the current replace migration.
|
||||
*
|
||||
* Helpful for hookers who need to know what intent they are working on.
|
||||
*
|
||||
* @return string Intent of the current migration
|
||||
*/
|
||||
public function get_intent() {
|
||||
return $this->intent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
|
||||
class WPMDB_Sanitize {
|
||||
/**
|
||||
* Sanitize and validate data.
|
||||
*
|
||||
* @param string|array $data The data to the sanitized.
|
||||
* @param string|array $key_rules The keys in the data (if data is an array) and the sanitization rule(s) to apply for each key.
|
||||
* @param string $context Additional context data for messages etc.
|
||||
*
|
||||
* @return mixed The sanitized data, the data if no key rules supplied or `false` if an unrecognized rule supplied.
|
||||
*/
|
||||
static function sanitize_data( $data, $key_rules, $context ) {
|
||||
if ( empty( $data ) || empty( $key_rules ) ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
return WPMDB_Sanitize::_sanitize_data( $data, $key_rules, $context );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize and validate data.
|
||||
*
|
||||
* @param string|array $data The data to the sanitized.
|
||||
* @param string|array $key_rules The keys in the data (if data is an array) and the sanitization rule(s) to apply for each key.
|
||||
* @param string $context Additional context data for messages etc.
|
||||
* @param int $recursion_level How deep in the recursion are we? Optional, defaults to 0.
|
||||
*
|
||||
* @return mixed The sanitized data, the data if no key rules supplied or `false` if an unrecognized rule supplied.
|
||||
*/
|
||||
private static function _sanitize_data( $data, $key_rules, $context, $recursion_level = 0 ) {
|
||||
if ( empty( $data ) || empty( $key_rules ) ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if ( 0 === $recursion_level && is_array( $data ) ) {
|
||||
// We always expect associative arrays.
|
||||
if ( ! is_array( $key_rules ) ) {
|
||||
wp_die( sprintf( __( '%1$s was not expecting data to be an array.', 'wp-db-migrate-pro' ), $context ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
foreach ( $data as $key => $value ) {
|
||||
// If a key does not have a rule it's not ours and can be removed.
|
||||
// We should not fail if there is extra data as plugins like Polylang add their own data to each ajax request.
|
||||
if ( ! array_key_exists( $key, $key_rules ) ) {
|
||||
unset( $data[ $key ] );
|
||||
continue;
|
||||
}
|
||||
$data[ $key ] = WPMDB_Sanitize::_sanitize_data( $value, $key_rules[ $key ], $context, ( $recursion_level + 1 ) );
|
||||
}
|
||||
} elseif ( is_array( $key_rules ) ) {
|
||||
foreach ( $key_rules as $rule ) {
|
||||
$data = WPMDB_Sanitize::_sanitize_data( $data, $rule, $context, ( $recursion_level + 1 ) );
|
||||
}
|
||||
} else {
|
||||
// Neither $data or $key_rules are a first level array so can be analysed.
|
||||
if ( 'array' == $key_rules ) {
|
||||
if ( ! is_array( $data ) ) {
|
||||
wp_die( sprintf( __( '%1$s was expecting an array but got something else: "%2$s"', 'wp-db-migrate-pro' ), $context, $data ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
} elseif ( 'string' == $key_rules ) {
|
||||
if ( ! is_string( $data ) ) {
|
||||
wp_die( sprintf( __( '%1$s was expecting a string but got something else: "%2$s"', 'wp-db-migrate-pro' ), $context, $data ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
} elseif ( 'key' == $key_rules ) {
|
||||
$key_name = sanitize_key( $data );
|
||||
if ( $key_name !== $data ) {
|
||||
wp_die( sprintf( __( '%1$s was expecting a valid key but got something else: "%2$s"', 'wp-db-migrate-pro' ), $context, $data ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
$data = $key_name;
|
||||
} elseif ( 'text' == $key_rules ) {
|
||||
$text = sanitize_text_field( $data );
|
||||
if ( $text !== $data ) {
|
||||
wp_die( sprintf( __( '%1$s was expecting text but got something else: "%2$s"', 'wp-db-migrate-pro' ), $context, $data ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
$data = $text;
|
||||
} elseif ( 'serialized' == $key_rules ) {
|
||||
if ( ! is_string( $data ) || ! is_serialized( $data ) ) {
|
||||
wp_die( sprintf( __( '%1$s was expecting serialized data but got something else: "%2$s"', 'wp-db-migrate-pro' ), $context, $data ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
} elseif ( 'json_array' == $key_rules ) {
|
||||
if ( ! is_string( $data ) || ! WPMDB::is_json( $data ) ) {
|
||||
wp_die( sprintf( __( '%1$s was expecting JSON data but got something else: "%2$s"', 'wp-db-migrate-pro' ), $context, $data ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
$data = json_decode( $data, true );
|
||||
} elseif ( 'json' == $key_rules ) {
|
||||
if ( ! is_string( $data ) || ! WPMDB::is_json( $data ) ) {
|
||||
wp_die( sprintf( __( '%1$s was expecting JSON data but got something else: "%2$s"', 'wp-db-migrate-pro' ), $context, $data ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
} elseif ( 'numeric' == $key_rules ) {
|
||||
if ( ! is_numeric( $data ) ) {
|
||||
wp_die( sprintf( __( '%1$s was expecting a valid numeric but got something else: "%2$s"', 'wp-db-migrate-pro' ), $context, $data ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
} elseif ( 'int' == $key_rules ) {
|
||||
// As we are sanitizing form data, even integers are within a string.
|
||||
if ( ! is_numeric( $data ) || (int) $data != $data ) {
|
||||
wp_die( sprintf( __( '%1$s was expecting an integer but got something else: "%2$s"', 'wp-db-migrate-pro' ), $context, $data ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
$data = (int) $data;
|
||||
} elseif ( 'positive_int' == $key_rules ) {
|
||||
if ( ! is_numeric( $data ) || (int) $data != $data || 0 > $data ) {
|
||||
wp_die( sprintf( __( '%1$s was expecting a positive number (int) but got something else: "%2$s"', 'wp-db-migrate-pro' ), $context, $data ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
$data = floor( $data );
|
||||
} elseif ( 'negative_int' == $key_rules ) {
|
||||
if ( ! is_numeric( $data ) || (int) $data != $data || 0 < $data ) {
|
||||
wp_die( sprintf( __( '%1$s was expecting a negative number (int) but got something else: "%2$s"', 'wp-db-migrate-pro' ), $context, $data ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
$data = ceil( $data );
|
||||
} elseif ( 'zero_int' == $key_rules ) {
|
||||
if ( ! is_numeric( $data ) || (int) $data != $data || 0 !== $data ) {
|
||||
wp_die( sprintf( __( '%1$s was expecting 0 (int) but got something else: "%2$s"', 'wp-db-migrate-pro' ), $context, $data ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
$data = 0;
|
||||
} elseif ( 'empty' == $key_rules ) {
|
||||
if ( ! empty( $data ) ) {
|
||||
wp_die( sprintf( __( '%1$s was expecting an empty value but got something else: "%2$s"', 'wp-db-migrate-pro' ), $context, $data ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
} elseif ( 'url' == $key_rules ) {
|
||||
$url = esc_url_raw( $data );
|
||||
if ( empty( $url ) ) {
|
||||
wp_die( sprintf( __( '%1$s was expecting a URL but got something else: "%2$s"', 'wp-db-migrate-pro' ), $context, $data ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
$data = $url;
|
||||
} elseif ( 'bool' == $key_rules ) {
|
||||
$bool = sanitize_key( $data );
|
||||
if ( empty( $bool ) || ! in_array( $bool, array( 'true', 'false' ) ) ) {
|
||||
wp_die( sprintf( __( '%1$s was expecting a bool but got something else: "%2$s"', 'wp-db-migrate-pro' ), $context, $data ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
$data = $bool;
|
||||
} else {
|
||||
wp_die( sprintf( __( 'Unknown sanitization rule "%1$s" supplied by %2$s', 'wp-db-migrate-pro' ), $key_rules, $context ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
class WPMDB_Utils {
|
||||
|
||||
/**
|
||||
* Test to see if executing an AJAX call specific to the WP Migrate DB family of plugins.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_ajax() {
|
||||
// must be doing AJAX the WordPress way
|
||||
if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// must be one of our actions -- e.g. core plugin (wpmdb_*), media files (wpmdbmf_*)
|
||||
if ( ! isset( $_POST['action'] ) || 0 !== strpos( $_POST['action'], 'wpmdb' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// must be on blog #1 (first site) if multisite
|
||||
if ( is_multisite() && 1 != get_current_site()->id ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if another version of WPMDB(Pro) is active and deactivates it.
|
||||
* To be hooked on `activated_plugin` so other plugin is deactivated when current plugin is activated.
|
||||
*
|
||||
* @param string $plugin
|
||||
*
|
||||
*/
|
||||
public static function deactivate_other_instances( $plugin ) {
|
||||
if ( ! in_array( basename( $plugin ), array( 'wp-migrate-db-pro.php', 'wp-migrate-db.php' ) ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$plugin_to_deactivate = 'wp-migrate-db.php';
|
||||
$deactivated_notice_id = '1';
|
||||
if ( basename( $plugin ) == $plugin_to_deactivate ) {
|
||||
$plugin_to_deactivate = 'wp-migrate-db-pro.php';
|
||||
$deactivated_notice_id = '2';
|
||||
}
|
||||
|
||||
if ( is_multisite() ) {
|
||||
$active_plugins = (array) get_site_option( 'active_sitewide_plugins', array() );
|
||||
$active_plugins = array_keys( $active_plugins );
|
||||
} else {
|
||||
$active_plugins = (array) get_option( 'active_plugins', array() );
|
||||
}
|
||||
|
||||
foreach ( $active_plugins as $basename ) {
|
||||
if ( false !== strpos( $basename, $plugin_to_deactivate ) ) {
|
||||
set_transient( 'wp_migrate_db_deactivated_notice_id', $deactivated_notice_id, 1 * HOUR_IN_SECONDS );
|
||||
deactivate_plugins( $basename );
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return unserialized object or array
|
||||
*
|
||||
* @param string $serialized_string Serialized string.
|
||||
* @param string $method The name of the caller method.
|
||||
*
|
||||
* @return mixed, false on failure
|
||||
*/
|
||||
public static function unserialize( $serialized_string, $method = '' ) {
|
||||
if ( ! is_serialized( $serialized_string ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$serialized_string = trim( $serialized_string );
|
||||
$unserialized_string = @unserialize( $serialized_string );
|
||||
|
||||
if ( false === $unserialized_string && defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ) {
|
||||
$scope = $method ? sprintf( __( 'Scope: %s().', 'wp-migrate-db' ), $method ) : false;
|
||||
$error = sprintf( __( 'WPMDB Error: Data cannot be unserialized. %s', 'wp-migrate-db' ), $scope );
|
||||
error_log( $error );
|
||||
}
|
||||
|
||||
return $unserialized_string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use wp_unslash if available, otherwise fall back to stripslashes_deep
|
||||
*
|
||||
* @param string|array $arg
|
||||
*
|
||||
* @return string|array
|
||||
*/
|
||||
public static function safe_wp_unslash( $arg ){
|
||||
if ( function_exists( 'wp_unslash' ) ) {
|
||||
return wp_unslash( $arg );
|
||||
} else {
|
||||
return stripslashes_deep( $arg );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
3692
wordpress/wp-content/plugins/wp-migrate-db-pro/class/wpmdb.php
Normal file
3692
wordpress/wp-content/plugins/wp-migrate-db-pro/class/wpmdb.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
class WPMDBPro_Addon extends WPMDB_Base {
|
||||
protected $version_required;
|
||||
|
||||
function __construct( $plugin_file_path ) {
|
||||
$this->is_addon = true;
|
||||
parent::__construct( $plugin_file_path );
|
||||
}
|
||||
|
||||
function meets_version_requirements( $version_required ) {
|
||||
$wpmdb_pro_version = $GLOBALS['wpmdb_meta']['wp-migrate-db-pro']['version'];
|
||||
$result = version_compare( $wpmdb_pro_version, $version_required, '>=' );
|
||||
$this->version_required = $version_required;
|
||||
|
||||
if ( false == $result ) {
|
||||
$this->hook_version_requirement_actions();
|
||||
}
|
||||
|
||||
if ( $result ) {
|
||||
// If pre-1.1.2 version of Media Files addon,
|
||||
// then it's not supported by this version of core
|
||||
if ( empty( $this->plugin_version ) ) {
|
||||
$result = false;
|
||||
} else { // Check that this version of core supports the addon version
|
||||
$plugin_basename = sprintf( '%1$s/%1$s.php', $this->plugin_slug );
|
||||
$required_addon_version = $this->addons[ $plugin_basename ]['required_version'];
|
||||
$result = version_compare( $this->plugin_version, $required_addon_version, '>=' );
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
function hook_version_requirement_actions() {
|
||||
add_action( 'wpmdb_notices', array( $this, 'version_requirement_actions' ) );
|
||||
}
|
||||
|
||||
function version_requirement_actions() {
|
||||
$addon_requirement_check = get_site_option( 'wpmdb_addon_requirement_check', array() );
|
||||
|
||||
// we only want to delete the transients once, here we keep track of which versions we've checked
|
||||
if ( ! isset( $addon_requirement_check[ $this->plugin_slug ] ) || $addon_requirement_check[ $this->plugin_slug ] != $GLOBALS['wpmdb_meta'][ $this->plugin_slug ]['version'] ) {
|
||||
delete_site_transient( 'wpmdb_upgrade_data' );
|
||||
delete_site_transient( 'update_plugins' );
|
||||
$addon_requirement_check[ $this->plugin_slug ] = $GLOBALS['wpmdb_meta'][ $this->plugin_slug ]['version'];
|
||||
update_site_option( 'wpmdb_addon_requirement_check', $addon_requirement_check );
|
||||
}
|
||||
|
||||
$this->version_requirement_warning();
|
||||
}
|
||||
|
||||
function version_requirement_warning() { ?>
|
||||
<div class="updated warning inline-message below-h2">
|
||||
<strong>Update Required</strong> — <?php
|
||||
$addon_name = $this->get_plugin_name();
|
||||
$required = $this->version_required;
|
||||
$installed = $GLOBALS['wpmdb_meta']['wp-migrate-db-pro']['version'];
|
||||
$wpmdb_basename = sprintf( '%s/%s.php', $GLOBALS['wpmdb_meta']['wp-migrate-db-pro']['folder'], 'wp-migrate-db' );
|
||||
$update = wp_nonce_url( network_admin_url( 'update.php?action=upgrade-plugin&plugin=' . urlencode( $wpmdb_basename ) ), 'upgrade-plugin_' . $wpmdb_basename );
|
||||
printf( __( 'The version of %1$s you have installed, requires version %2$s of WP Migrate DB Pro. You currently have %3$s installed. <strong><a href="%4$s">Update Now</a></strong>', 'wp-migrate-db' ), $addon_name, $required, $installed, $update ); ?>
|
||||
</div> <?php
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/wpmdb-cli.php';
|
||||
|
||||
class WPMDBPro_CLI_Export extends WPMDB_CLI {
|
||||
|
||||
/**
|
||||
* Instance of WPMDBPro.
|
||||
*
|
||||
* @var WPMDBPro
|
||||
*/
|
||||
protected $wpmdbpro;
|
||||
|
||||
function __construct( $plugin_file_path ) {
|
||||
parent::__construct( $plugin_file_path );
|
||||
|
||||
global $wpmdbpro;
|
||||
$this->wpmdb = &$this->wpmdbpro;
|
||||
$this->wpmdbpro = $wpmdbpro;
|
||||
|
||||
// add support for extra args
|
||||
add_filter( 'wpmdb_cli_filter_get_extra_args', array( $this, 'filter_extra_args_cli_export' ), 10, 1 );
|
||||
add_filter( 'wpmdb_cli_filter_get_profile_data_from_args', array( $this, 'add_extra_args_for_pro_export' ), 10, 3 );
|
||||
|
||||
// extend get_tables_to_migrate with migrate_select
|
||||
add_filter( 'wpmdb_cli_tables_to_migrate', array( $this, 'tables_to_migrate_include_select' ), 10, 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add extra CLI args used by this plugin.
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function filter_extra_args_cli_export( $args = array() ) {
|
||||
$args[] = 'include-tables';
|
||||
$args[] = 'exclude-post-types';
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add support for extra args in export
|
||||
*
|
||||
* @param array $profile
|
||||
* @param array $args
|
||||
* @param array $assoc_args
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function add_extra_args_for_pro_export( $profile, $args, $assoc_args ) {
|
||||
if ( ! is_array( $profile ) ) {
|
||||
return $profile;
|
||||
}
|
||||
|
||||
// --include-tables=<tables>
|
||||
if ( ! empty( $assoc_args['include-tables'] ) ) {
|
||||
$table_migrate_option = 'migrate_select';
|
||||
$select_tables = explode( ',', $assoc_args['include-tables'] );
|
||||
} else {
|
||||
$select_tables = array();
|
||||
$table_migrate_option = 'migrate_only_with_prefix';
|
||||
}
|
||||
|
||||
// --exclude-post-types=<post-types>
|
||||
$select_post_types = array();
|
||||
if ( ! empty( $assoc_args['exclude-post-types'] ) ) {
|
||||
$select_post_types = explode( ',', $assoc_args['exclude-post-types'] );
|
||||
}
|
||||
|
||||
$filtered_profile = compact(
|
||||
'table_migrate_option',
|
||||
'select_post_types',
|
||||
'select_tables'
|
||||
);
|
||||
|
||||
return array_merge( $profile, $filtered_profile );
|
||||
}
|
||||
|
||||
/**
|
||||
* Use tables from --include-tables assoc arg if available
|
||||
*
|
||||
* @param array $tables_to_migrate
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function tables_to_migrate_include_select( $tables_to_migrate ) {
|
||||
if ( in_array( $this->profile['action'], array( 'find_replace', 'savefile' ) ) ) {
|
||||
if ( 'migrate_select' === $this->profile['table_migrate_option'] && ! empty( $this->profile['select_tables'] ) ) {
|
||||
$tables_to_migrate = array_intersect( $this->profile['select_tables'], $this->get_tables() );
|
||||
}
|
||||
}
|
||||
|
||||
return $tables_to_migrate;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
/**
|
||||
* Migrate your DB using WP Migrate DB Pro.
|
||||
*/
|
||||
|
||||
//require wpmdb-command.php from wp-migrate-db-pro
|
||||
require_once __DIR__ . '/wpmdb-command.php';
|
||||
|
||||
class WPMDBPro_Command extends WPMDB_Command {
|
||||
/**
|
||||
* Export local DB to file.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* <output-file>
|
||||
* : A file path to export to. Filename will be modified to end in .sql or
|
||||
* .sql.gz if necessary.
|
||||
*
|
||||
* [--find=<strings>]
|
||||
* : A comma separated list of strings to find when performing a string find
|
||||
* and replace across the database.
|
||||
*
|
||||
* Table names should be quoted as needed, i.e. when using a comma in the
|
||||
* find/replace string.
|
||||
*
|
||||
* The --replace=<strings> argument should be used in conjunction to specify
|
||||
* the replace values for the strings found using this argument. The number
|
||||
* of strings specified in this argument should match the number passed into
|
||||
* --replace=<strings> argument.
|
||||
*
|
||||
* [--replace=<strings>]
|
||||
* : A comma separated list of replace value strings to implement when
|
||||
* performing a string find & replace across the database.
|
||||
*
|
||||
* Should be used in conjunction with the --find=<strings> argument, see it's
|
||||
* documentation for further explanation of the find & replace functionality.
|
||||
*
|
||||
* [--include-tables=<tables>]
|
||||
* : The comma separated list of tables to migrate. Excluding this parameter
|
||||
* will migrate all tables in your database that begin with your
|
||||
* installation's table prefix, e.g. wp_.
|
||||
*
|
||||
* [--exclude-post-types=<post-types>]
|
||||
* : A comma separated list of post types to exclude. Excluding this parameter
|
||||
* will migrate all post types.
|
||||
*
|
||||
* [--skip-replace-guids]
|
||||
* : Do not perform a find & replace on the guid column in the wp_posts table.
|
||||
*
|
||||
* [--exclude-spam]
|
||||
* : Exclude spam comments.
|
||||
*
|
||||
* [--gzip-file]
|
||||
* : GZip compress export file.
|
||||
*
|
||||
* [--include-transients]
|
||||
* : Include transients (temporary cached data).
|
||||
*
|
||||
* [--subsite=<blog-id|subsite-url>]
|
||||
* : Export the given subsite as a single site install. Requires the Multisite Tools addon.
|
||||
*
|
||||
* [--prefix=<new-table-prefix>]
|
||||
* : A new table prefix to be used for a subsite export.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp migratedb export ./migratedb.sql \
|
||||
* --find=http://dev.bradt.ca,/Users/bradt/home/bradt.ca
|
||||
* --replace=http://bradt.ca,/home/bradt.ca
|
||||
* --include-tables=wp_posts,wp_postmeta
|
||||
*
|
||||
* @param array $args
|
||||
* @param array $assoc_args
|
||||
*/
|
||||
public function export( $args, $assoc_args ) {
|
||||
parent::export( $args, $assoc_args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a find/replace on the database.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* [--find=<strings>]
|
||||
* : A comma separated list of strings to find when performing a string find
|
||||
* and replace across the database.
|
||||
*
|
||||
* Table names should be quoted as needed, i.e. when using a comma in the
|
||||
* find/replace string.
|
||||
*
|
||||
* The --replace=<strings> argument should be used in conjunction to specify
|
||||
* the replace values for the strings found using this argument. The number
|
||||
* of strings specified in this argument should match the number passed into
|
||||
* --replace=<strings> argument.
|
||||
*
|
||||
* [--replace=<strings>]
|
||||
* : A comma separated list of replace value strings to implement when
|
||||
* performing a string find & replace across the database.
|
||||
*
|
||||
* Should be used in conjunction with the --find=<strings> argument, see it's
|
||||
* documentation for further explanation of the find & replace functionality.
|
||||
*
|
||||
* [--include-tables=<tables>]
|
||||
* : The comma separated list of tables to search. Excluding this parameter
|
||||
* will run a find & replace on all tables in your database that begin with your
|
||||
* installation's table prefix, e.g. wp_.
|
||||
*
|
||||
* [--exclude-post-types=<post-types>]
|
||||
* : A comma separated list of post types to exclude from the find & replace.
|
||||
* Excluding this parameter will run a find & replace on all post types.
|
||||
*
|
||||
* [--skip-replace-guids]
|
||||
* : Do not perform a find & replace on the guid column in the wp_posts table.
|
||||
*
|
||||
* [--exclude-spam]
|
||||
* : Exclude spam comments.
|
||||
*
|
||||
* [--include-transients]
|
||||
* : Include transients (temporary cached data).
|
||||
*
|
||||
* [--subsite=<blog-id|subsite-url>]
|
||||
* : Run a find & replace on the given subsite. Requires the Multisite Tools addon.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp migratedb find-replace
|
||||
* --find=http://dev.bradt.ca,/Users/bradt/home/bradt.ca
|
||||
* --replace=http://bradt.ca,/home/bradt.ca
|
||||
* --include-tables=wp_posts,wp_postmeta
|
||||
*
|
||||
* @param array $args
|
||||
* @param array $assoc_args
|
||||
*
|
||||
* @subcommand find-replace
|
||||
*/
|
||||
public function find_replace( $args, $assoc_args ) {
|
||||
parent::find_replace( $args, $assoc_args );
|
||||
}
|
||||
}
|
||||
|
||||
WP_CLI::add_command( 'migratedb', 'WPMDBPro_Command' );
|
||||
1660
wordpress/wp-content/plugins/wp-migrate-db-pro/class/wpmdbpro.php
Normal file
1660
wordpress/wp-content/plugins/wp-migrate-db-pro/class/wpmdbpro.php
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user