Added dependency plugins

This commit is contained in:
Moris Zen
2018-06-25 00:00:37 +02:00
parent 720a1c31a4
commit f069f6782f
698 changed files with 289637 additions and 1 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -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;
}
}

View File

@@ -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' );

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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 );
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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> &mdash; <?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
}
}

View File

@@ -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;
}
}

View File

@@ -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' );

File diff suppressed because it is too large Load Diff