Added dependency plugins
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
class WPMDBPro_Media_Files_CLI_Bar extends \cli\progress\Bar {
|
||||
|
||||
public function setMessage( $message ) {
|
||||
$this->_message = $message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
class WPMDBPro_Media_Files_CLI extends WPMDBPro_Media_Files {
|
||||
|
||||
function __construct( $plugin_file_path ) {
|
||||
parent::__construct( $plugin_file_path );
|
||||
|
||||
// compatibility with CLI migrations
|
||||
add_filter( 'wpmdb_pro_cli_finalize_migration', array( $this, 'cli_migration' ), 10, 4 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the media migration from the CLI
|
||||
*
|
||||
* @param bool $outcome
|
||||
* @param array $profile
|
||||
* @param array $verify_connection_response
|
||||
* @param array $initiate_migration_response
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function cli_migration( $outcome, $profile, $verify_connection_response, $initiate_migration_response ) {
|
||||
global $wpmdbpro, $wpmdbpro_cli;
|
||||
if ( true !== $outcome ) {
|
||||
return $outcome;
|
||||
}
|
||||
if ( empty( $profile['media_files'] ) ) {
|
||||
return $outcome;
|
||||
}
|
||||
|
||||
if ( ! isset( $verify_connection_response['media_files_max_file_uploads'] ) ) {
|
||||
return $wpmdbpro_cli->cli_error( __( 'WP Migrate DB Pro Media Files does not seem to be installed/active on the remote website.', 'wp-migrate-db-pro-media-files' ) );
|
||||
}
|
||||
|
||||
WP_CLI::log( __( 'Initiating media migration...', 'wp-migrate-db-pro-media-files' ) );
|
||||
|
||||
$this->set_time_limit();
|
||||
$wpmdbpro->set_cli_migration();
|
||||
$this->set_cli_migration();
|
||||
$this->media_files_local->set_cli_migration();
|
||||
|
||||
$intent = $profile['action'];
|
||||
$_POST['migration_state_id'] = $initiate_migration_response['migration_state_id'];
|
||||
|
||||
$media_type = ( isset( $profile['media_migration_option'] ) ) ? $profile['media_migration_option'] : 'compare';
|
||||
$copy_entire_media = ( 'entire' === $media_type ) ? 1 : 0;
|
||||
$remove_local_media = ( 'compare' === $media_type && isset( $profile['remove_local_media'] ) ) ? $profile['remove_local_media'] : 0;
|
||||
if ( 'compare-remove' == $media_type ) {
|
||||
$media_type = 'compare';
|
||||
$remove_local_media = 1;
|
||||
}
|
||||
|
||||
// seems like this value needs to be different depending on pull/push?
|
||||
$bottleneck = $wpmdbpro->get_bottleneck();
|
||||
|
||||
// if skipping comparison delete all files before migration
|
||||
if ( 'entire' === $media_type ) {
|
||||
do_action( 'wpmdb_cli_before_remove_files_recursive', $profile, $verify_connection_response, $initiate_migration_response );
|
||||
WP_CLI::log( $this->get_string( 'removing_all_files_' . $intent ) . '...' );
|
||||
|
||||
$compare = 0;
|
||||
$offset = 0;
|
||||
$remove_files = 1;
|
||||
while ( 1 == $remove_files ) {
|
||||
$_POST['compare'] = $compare;
|
||||
$_POST['offset'] = json_encode( $offset );
|
||||
|
||||
$response = $this->media_files_local->ajax_remove_files_recursive();
|
||||
if ( is_wp_error( $remove_files_recursive_response = $wpmdbpro_cli->verify_cli_response( $response, 'ajax_remove_files_recursive()' ) ) ) {
|
||||
return $remove_files_recursive_response;
|
||||
}
|
||||
|
||||
$remove_files = $remove_files_recursive_response['remove_files'];
|
||||
$compare = $remove_files_recursive_response['compare'];
|
||||
$offset = $remove_files_recursive_response['offset'];
|
||||
} // END recursive removal of files
|
||||
}
|
||||
|
||||
// start the recursive determine
|
||||
do_action( 'wpmdb_cli_before_determine_media_to_migrate', $profile, $verify_connection_response, $initiate_migration_response );
|
||||
|
||||
$response = $this->media_files_local->ajax_prepare_determine_media();
|
||||
if ( is_wp_error( $prepare_media_to_migrate_response = $wpmdbpro_cli->verify_cli_response( $response, 'ajax_prepare_determine_media()' ) ) ) {
|
||||
return $prepare_media_to_migrate_response;
|
||||
}
|
||||
|
||||
$attachment_batch_limit = $prepare_media_to_migrate_response['attachment_batch_limit'];
|
||||
$remote_uploads_url = $prepare_media_to_migrate_response['remote_uploads_url'];
|
||||
$attachment_count = $prepare_media_to_migrate_response['attachment_count'];
|
||||
$blogs = $prepare_media_to_migrate_response['blogs'];
|
||||
$determine_progress = 0;
|
||||
|
||||
// determine the media to migrate in batches
|
||||
while ( $determine_progress < $attachment_count ) {
|
||||
|
||||
$_POST['attachment_batch_limit'] = $attachment_batch_limit;
|
||||
$_POST['remote_uploads_url'] = $remote_uploads_url;
|
||||
$_POST['attachment_count'] = $attachment_count;
|
||||
$_POST['blogs'] = $blogs;
|
||||
$_POST['determine_progress'] = $determine_progress;
|
||||
$_POST['copy_entire_media'] = $copy_entire_media;
|
||||
$_POST['remove_local_media'] = $remove_local_media;
|
||||
|
||||
$response = $this->media_files_local->ajax_determine_media_to_migrate_recursive();
|
||||
if ( is_wp_error( $determine_media_to_migrate_recursive_response = $wpmdbpro_cli->verify_cli_response( $response, 'ajax_determine_media_to_migrate_recursive_response()' ) ) ) {
|
||||
return $determine_media_to_migrate_recursive_response;
|
||||
}
|
||||
|
||||
$blogs = $determine_media_to_migrate_recursive_response['blogs'];
|
||||
$determine_progress = $determine_media_to_migrate_recursive_response['determine_progress'];
|
||||
$total_size = $determine_media_to_migrate_recursive_response['total_size'];
|
||||
$files_to_migrate = $determine_media_to_migrate_recursive_response['files_to_migrate'];
|
||||
|
||||
$percent = ( $determine_progress / $attachment_count ) * 100;
|
||||
WP_CLI::log( sprintf( $this->get_string( 'determining_progress' ), $determine_progress, $attachment_count, round( $percent ) ) );
|
||||
|
||||
$total_files = count( $files_to_migrate );
|
||||
if ( $total_files > 0 ) {
|
||||
$migrate_bar = new WPMDBPro_Media_Files_CLI_Bar( sprintf( $this->get_string( 'migrate_media_files_cli_' . $intent ), 0, $total_files ), 0 );
|
||||
$migrate_bar->setTotal( $total_size );
|
||||
|
||||
$current_file_index = 0;
|
||||
|
||||
// start the recursive migration of the files we have just determined
|
||||
while ( ! empty( $files_to_migrate ) ) {
|
||||
|
||||
$file_chunk_to_migrate = array();
|
||||
$file_chunk_size = 0;
|
||||
$number_of_files_to_migrate = 0;
|
||||
foreach ( $files_to_migrate as $file_to_migrate => $file_size ) {
|
||||
if ( empty( $file_chunk_to_migrate ) ) {
|
||||
$file_chunk_to_migrate[] = $file_to_migrate;
|
||||
$file_chunk_size += $file_size;
|
||||
unset( $files_to_migrate[ $file_to_migrate ] );
|
||||
++$number_of_files_to_migrate;
|
||||
} else {
|
||||
if ( ( $file_chunk_size + $file_size ) > $bottleneck || $number_of_files_to_migrate >= $verify_connection_response['media_files_max_file_uploads'] ) {
|
||||
break;
|
||||
} else {
|
||||
$file_chunk_to_migrate[] = $file_to_migrate;
|
||||
$file_chunk_size += $file_size;
|
||||
unset( $files_to_migrate[ $file_to_migrate ] );
|
||||
++$number_of_files_to_migrate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$current_file_index += $number_of_files_to_migrate;
|
||||
$migrate_bar->setMessage( sprintf( $this->get_string( 'migrate_media_files_cli_' . $intent ), $current_file_index, $total_files ) );
|
||||
|
||||
$_POST['file_chunk'] = $file_chunk_to_migrate;
|
||||
|
||||
do_action( 'wpmdb_media_files_cli_before_migrate_media' );
|
||||
|
||||
$response = $this->media_files_local->ajax_migrate_media();
|
||||
if ( is_wp_error( $migrate_media_response = $wpmdbpro_cli->verify_cli_response( $response, 'ajax_migrate_media()' ) ) ) {
|
||||
return $migrate_media_response;
|
||||
}
|
||||
|
||||
$migrate_bar->tick( $file_chunk_size );
|
||||
} // END recursive media migration
|
||||
|
||||
// force migrate bar to show completion
|
||||
$migrate_bar->setMessage( sprintf( $this->get_string( 'migrate_media_files_cli_' . $intent ), $total_files, $total_files ) );
|
||||
$migrate_bar->finish();
|
||||
}
|
||||
} // END recursive media determine
|
||||
|
||||
// if removing local media not found on remote after comparison
|
||||
if ( 1 == $remove_local_media ) {
|
||||
// start recursive batch delete of local files not found on remote
|
||||
do_action( 'wpmdb_cli_before_remove_files_not_found_recursive', $profile, $verify_connection_response, $initiate_migration_response );
|
||||
WP_CLI::log( $this->get_string( 'removing_files_' . $intent ) . '...' );
|
||||
$compare = 1;
|
||||
$offset = '';
|
||||
$remove_files = 1;
|
||||
while ( 1 == $remove_files ) {
|
||||
$_POST['compare'] = $compare;
|
||||
$_POST['offset'] = json_encode( $offset );
|
||||
|
||||
$response = $this->media_files_local->ajax_remove_files_recursive();
|
||||
if ( is_wp_error( $remove_files_recursive_response = $wpmdbpro_cli->verify_cli_response( $response, 'ajax_remove_files_recursive()' ) ) ) {
|
||||
return $remove_files_recursive_response;
|
||||
}
|
||||
|
||||
$remove_files = $remove_files_recursive_response['remove_files'];
|
||||
$compare = $remove_files_recursive_response['compare'];
|
||||
$offset = $remove_files_recursive_response['offset'];
|
||||
} // END recursive removal of files
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,844 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class WPMDBPro_Media_Files_Base
|
||||
*
|
||||
* Base class that holds common functionality required by both WPMDBPro_Media_Files_Local and
|
||||
* WPMDBPro_Media_Files_Remote. Extends WPMDBPro_Addon as we require functionality included in the WPMDB base classes.
|
||||
* Never instantiated on its own.
|
||||
*/
|
||||
class WPMDBPro_Media_Files_Base extends WPMDBPro_Addon {
|
||||
|
||||
/**
|
||||
* The number of seconds a batch should run for when queueing or comparing attachments
|
||||
*
|
||||
* @var int $media_diff_batch_time
|
||||
*/
|
||||
protected $media_diff_batch_time;
|
||||
|
||||
/**
|
||||
* The max number of attachments in a batch
|
||||
*
|
||||
* @var int $media_diff_batch_limit
|
||||
*/
|
||||
protected $media_diff_batch_limit;
|
||||
|
||||
/**
|
||||
* The number of seconds a batch should run for when scanning for files
|
||||
*
|
||||
* @var int $media_files_batch_time_limit
|
||||
*/
|
||||
protected $media_files_batch_time_limit;
|
||||
|
||||
protected $accepted_fields;
|
||||
|
||||
public function __construct( $plugin_file_path ) {
|
||||
parent::__construct( $plugin_file_path );
|
||||
|
||||
$this->media_diff_batch_time = apply_filters( 'wpmdb_media_diff_batch_time', 10 );
|
||||
$this->media_diff_batch_limit = apply_filters( 'wpmdb_media_diff_batch_limit', 300 );
|
||||
$this->media_files_batch_time_limit = apply_filters( 'wpmdb_media_files_batch_time_limit', 15 );
|
||||
|
||||
$this->accepted_fields = array(
|
||||
'media_files',
|
||||
'remove_local_media',
|
||||
'media_migration_option',
|
||||
'mf_select_subsites',
|
||||
'mf_selected_subsites',
|
||||
);
|
||||
|
||||
add_filter( 'wpmdb_accepted_profile_fields', array( $this, 'accepted_profile_fields' ) );
|
||||
add_filter( 'wpmdbmf_include_subsite', array( $this, 'include_subsite' ), 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Whitelist media setting fields for use in AJAX save in core
|
||||
*
|
||||
* @param array $profile_fields Array of profile fields
|
||||
*
|
||||
* @return array Updated array of profile fields
|
||||
*/
|
||||
function accepted_profile_fields( $profile_fields ) {
|
||||
return array_merge( $profile_fields, $this->accepted_fields );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return total number of local attachments
|
||||
*
|
||||
* For multisite returns the total number of attachments for all blogs
|
||||
*
|
||||
* @return int Total number of local attachments
|
||||
*/
|
||||
function get_local_attachments_count() {
|
||||
global $wpdb;
|
||||
$count = 0;
|
||||
|
||||
if ( is_multisite() ) {
|
||||
$blogs = $this->get_blog_ids();
|
||||
foreach ( $blogs as $blog ) {
|
||||
$blog_prefix = $wpdb->get_blog_prefix( $blog );
|
||||
$count += $this->get_attachments_count( $blog_prefix );
|
||||
}
|
||||
} else {
|
||||
$count += $this->get_attachments_count( $wpdb->base_prefix );
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the count of attachments for a blog
|
||||
*
|
||||
* @param string $prefix Blog db prefix
|
||||
*
|
||||
* @return int Number of attachments
|
||||
*/
|
||||
function get_attachments_count( $prefix ) {
|
||||
return $this->get_attachment_results( $prefix, 'count' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all attachments for a blog
|
||||
*
|
||||
* @param string $prefix Blog db prefix
|
||||
* @param int $blog Blog ID
|
||||
* @param int $limit Limit passed to SQL query (for batching)
|
||||
* @param array $offset Offset (blog ID, post ID) passed to SQL query (for batching)
|
||||
*
|
||||
* @return array Attachments
|
||||
*/
|
||||
function get_attachments( $prefix, $blog, $limit, $offset ) {
|
||||
return $this->get_attachment_results( $prefix, 'rows', array( $blog, $offset, $limit ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function for retrieving attachments
|
||||
*
|
||||
* @param string $prefix Blog db prefix
|
||||
* @param string $result_type Type of result we want to retrieve (count / rows / row)
|
||||
* @param array $args Dependant of $result_type.
|
||||
* 'count' - none
|
||||
* 'rows' - $blog_id, $offset, $limit
|
||||
* 'row' - $blog_id, $filename
|
||||
*
|
||||
* @return array Attachments
|
||||
*/
|
||||
function get_attachment_results( $prefix, $result_type = 'rows', $args = array() ) {
|
||||
global $wpdb;
|
||||
|
||||
$core = " FROM `{$prefix}posts`
|
||||
INNER JOIN `{$prefix}postmeta` pm1 ON `{$prefix}posts`.`ID` = pm1.`post_id` AND pm1.`meta_key` = '_wp_attached_file'
|
||||
LEFT OUTER JOIN `{$prefix}postmeta` pm2 ON `{$prefix}posts`.`ID` = pm2.`post_id` AND pm2.`meta_key` = '_wp_attachment_metadata'
|
||||
WHERE `{$prefix}posts`.`post_type` = 'attachment' ";
|
||||
|
||||
if ( 'count' == $result_type ) {
|
||||
$sql = 'SELECT COUNT(*)' . $core;
|
||||
|
||||
return $wpdb->get_var( $sql );
|
||||
}
|
||||
|
||||
$select = "SELECT `{$prefix}posts`.`ID` AS 'ID', `{$prefix}posts`.`post_modified_gmt` AS 'date', pm1.`meta_value` AS 'file', pm2.`meta_value` AS 'metadata', %d AS 'blog_id'";
|
||||
$sql = $select . $core;
|
||||
|
||||
if ( 'rows' == $result_type ) {
|
||||
$action = 'get_results';
|
||||
$sql .= "AND `{$prefix}posts`.`ID` > %d
|
||||
ORDER BY `{$prefix}posts`.`ID`
|
||||
LIMIT %d";
|
||||
} else {
|
||||
$action = 'get_row';
|
||||
$sql .= 'AND pm1.`meta_value` = %s';
|
||||
}
|
||||
|
||||
$sql = $wpdb->prepare( $sql, $args );
|
||||
|
||||
$results = $wpdb->$action( $sql, ARRAY_A );
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a batch of attachments across all blogs
|
||||
*
|
||||
* @param mixed $blogs Blogs
|
||||
* @param int $limit Max attachments limit (for batching)
|
||||
* @param array $offset Optional offset (blog ID, post ID) to use instead of $blog['last_post']
|
||||
*
|
||||
* @return array Local attachments and blogs
|
||||
*/
|
||||
function get_local_attachments_batch( $blogs, $limit, $offset = null ) {
|
||||
$all_limit = $limit;
|
||||
|
||||
if ( ! is_array( $blogs ) ) {
|
||||
$blogs = unserialize( stripslashes( $blogs ) );
|
||||
}
|
||||
|
||||
$all_attachments = array();
|
||||
$all_count = 0;
|
||||
|
||||
foreach ( $blogs as $blog_id => $blog ) {
|
||||
if ( 1 == $blog['processed'] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$blog_offset = $blog['last_post'];
|
||||
if ( is_array( $offset ) ) {
|
||||
if ( $offset[0] > $blog_id ) {
|
||||
$blogs[ $blog_id ]['processed'] = 1;
|
||||
continue;
|
||||
} elseif ( $blog_id == $offset[0] ) {
|
||||
$blog_offset = $offset[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$attachments = $this->get_attachments( $blog['prefix'], $blog_id, $limit, $blog_offset );
|
||||
$count = count( $attachments );
|
||||
if ( 0 == $count ) {
|
||||
// no more attachments, record the blog ID to skip next time
|
||||
$blogs[ $blog_id ]['processed'] = 1;
|
||||
} else {
|
||||
$all_count += $count;
|
||||
// process attachments for sizes files
|
||||
$attachments = array_map( array( $this, 'process_attachment_data' ), $attachments );
|
||||
$attachments = array_filter( $attachments );
|
||||
|
||||
$all_attachments[ $blog_id ] = $attachments;
|
||||
}
|
||||
|
||||
if ( $all_count >= $all_limit ) {
|
||||
break;
|
||||
}
|
||||
|
||||
$limit = $limit - $count;
|
||||
}
|
||||
|
||||
$return = array(
|
||||
'attachments' => $all_attachments,
|
||||
'blogs' => $blogs,
|
||||
);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all attachment files across all blogs
|
||||
*
|
||||
* @param array $offset (blog ID, attachment ID) offset
|
||||
*
|
||||
* @return array Local media attachment files and last attachment ID
|
||||
*/
|
||||
function get_local_media_attachment_files_batch( $offset ) {
|
||||
$local_media_attachment_files = array();
|
||||
$last_attachment_id = 0;
|
||||
|
||||
$blogs = $this->get_blogs();
|
||||
$local_media_attachments = $this->get_local_attachments_batch( $blogs, $this->media_diff_batch_limit, $offset );
|
||||
$last_blog_id = 1;
|
||||
|
||||
// Get file paths from attachments
|
||||
foreach ( $local_media_attachments['attachments'] as $blog_id => $attachments ) {
|
||||
foreach ( $attachments as $attachment ) {
|
||||
if ( ! empty( $attachment['file_size'] ) ) {
|
||||
$local_media_attachment_files[] = $attachment['file'];
|
||||
$last_blog_id = $blog_id;
|
||||
$last_attachment_id = $attachment['ID'];
|
||||
}
|
||||
|
||||
if ( isset( $attachment['sizes'] ) && ! empty( $attachment['sizes'] ) ) {
|
||||
foreach ( $attachment['sizes'] as $size ) {
|
||||
if ( ! empty( $size['file_size'] ) ) {
|
||||
$local_media_attachment_files[] = $size['file'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'files' => $local_media_attachment_files,
|
||||
'last_blog_id' => $last_blog_id,
|
||||
'last_attachment_id' => $last_attachment_id,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a batch of local media files
|
||||
*
|
||||
* Scans the uploads directory for physical files
|
||||
*
|
||||
* @param string $start_file The file or directory to start at
|
||||
*
|
||||
* @return array Local media files
|
||||
*/
|
||||
function get_local_media_files_batch( $start_file ) {
|
||||
$local_media_files = array();
|
||||
|
||||
$upload_dir = $this->uploads_dir();
|
||||
|
||||
if ( ! $this->filesystem->file_exists( $upload_dir ) ) {
|
||||
return $local_media_files;
|
||||
}
|
||||
|
||||
// Check if we're just kicking off with the root uploads dir
|
||||
if ( empty( $start_file ) ) {
|
||||
$this->get_local_media_files_batch_recursive( '', '', $local_media_files );
|
||||
} else {
|
||||
$dir = dirname( $start_file );
|
||||
$start_filename = basename( $start_file );
|
||||
$this->get_local_media_files_batch_recursive( trailingslashit( $dir ), $start_filename, $local_media_files );
|
||||
|
||||
$dirs = explode( '/', $dir );
|
||||
while ( $dirs ) {
|
||||
$start_filename = array_pop( $dirs );
|
||||
$dir = trailingslashit( implode( '/', $dirs ) );
|
||||
$this->get_local_media_files_batch_recursive( $dir, $start_filename, $local_media_files );
|
||||
}
|
||||
}
|
||||
|
||||
return $local_media_files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively go through uploads directories and get a batch of media files.
|
||||
* Stops when it has scanned all files/directories or after it has run for
|
||||
* $this->media_files_batch_time_limit seconds, whichever comes first.
|
||||
*
|
||||
* @param string $dir The directory to start in
|
||||
* @param string $start_filename The file or directory to start at within $dir
|
||||
* @param array $local_media_files Array to populate with media files found
|
||||
*/
|
||||
function get_local_media_files_batch_recursive( $dir, $start_filename, &$local_media_files ) {
|
||||
$upload_dir = $this->uploads_dir();
|
||||
|
||||
static $allowed_mime_types;
|
||||
if ( is_null( $allowed_mime_types ) ) {
|
||||
$allowed_mime_types = array_flip( get_allowed_mime_types() );
|
||||
}
|
||||
|
||||
static $finish_time;
|
||||
if ( is_null( $finish_time ) ) {
|
||||
$finish_time = microtime( true ) + $this->media_files_batch_time_limit;
|
||||
}
|
||||
|
||||
$dir = ( '/' == $dir ) ? '' : $dir;
|
||||
$dir_path = $upload_dir . $dir;
|
||||
$sub_paths = glob( $dir_path . '*', GLOB_MARK );
|
||||
|
||||
// Get all the files except the one we use to store backups.
|
||||
$wpmdb_upload_folder = $this->get_upload_info();
|
||||
$pattern = '/' . preg_quote( $wpmdb_upload_folder, '/' ) . '/';
|
||||
$files = preg_grep( $pattern, $sub_paths ? $sub_paths : array(), PREG_GREP_INVERT );
|
||||
|
||||
$reached_start_file = false;
|
||||
|
||||
foreach ( $files as $file_path ) {
|
||||
if ( microtime( true ) >= $finish_time ) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Are we starting from a certain file within the directory?
|
||||
// If so, we skip all the files that come before it.
|
||||
if ( $start_filename ) {
|
||||
if ( basename( $file_path ) == $start_filename ) {
|
||||
$reached_start_file = true;
|
||||
continue;
|
||||
} elseif ( ! $reached_start_file ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$short_file_path = str_replace( array( $upload_dir, '\\' ), array( '', '/' ), $file_path );
|
||||
|
||||
// Is directory? We use this instead of is_dir() to save us an I/O call
|
||||
if ( substr( $file_path, -1 ) == DIRECTORY_SEPARATOR ) {
|
||||
$this->get_local_media_files_batch_recursive( $short_file_path, '', $local_media_files );
|
||||
continue;
|
||||
}
|
||||
|
||||
// ignore files that we shouldn't touch, e.g. .php, .sql, etc
|
||||
$filetype = wp_check_filetype( $short_file_path );
|
||||
if ( ! isset( $allowed_mime_types[ $filetype['type'] ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( apply_filters( 'wpmdbmf_exclude_local_media_file_from_removal', false, $upload_dir, $short_file_path, $this ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$local_media_files[] = $short_file_path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues attachment file and image size files for migration if they exist on the source filesystem
|
||||
*
|
||||
* @param array $files_to_migrate List of files to migrate
|
||||
* @param array $attachment Attachment data
|
||||
* @param bool $local_attachment Used to compare if files actually exist locally
|
||||
*/
|
||||
function maybe_queue_attachment( &$files_to_migrate, $attachment, $local_attachment = false ) {
|
||||
if ( isset( $attachment['file_size'] ) && ( ! $local_attachment || ( $local_attachment && ! isset( $local_attachment['file_size'] ) ) ) ) {
|
||||
// if the remote attachment exists on the remote file system
|
||||
// and if a local attachment is supplied, if the file doesn't exist on local file system
|
||||
$files_to_migrate[ $attachment['file'] ] = $attachment['file_size'];
|
||||
}
|
||||
// check other image sizes of the attachment
|
||||
if ( empty( $attachment['sizes'] ) || apply_filters( 'wpmdb_exclude_resized_media', false ) ) {
|
||||
return;
|
||||
}
|
||||
foreach ( $attachment['sizes'] as $size ) {
|
||||
$original_file_name = $size['file'];
|
||||
// if dir_prefix is set, then the remote is a multisite and we need to compare the file without the subsite directory prefix
|
||||
if ( ! is_multisite() && $attachment['dir_prefix'] ) {
|
||||
$size['file'] = str_replace( $attachment['dir_prefix'], '', $size['file'] );
|
||||
}
|
||||
if ( isset( $size['file_size'] ) && ( ! $local_attachment || ( $local_attachment && ! $this->local_image_size_file_exists( $size, $local_attachment ) ) ) ) {
|
||||
// if the remote image size file exists on the remote file system
|
||||
$files_to_migrate[ $original_file_name ] = $size['file_size'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare a batch of remote attachments with those on local site
|
||||
*
|
||||
* @param mixed $blogs Blogs
|
||||
* @param mixed $all_attachments Batch of attachments
|
||||
* @param int $progress Progress count
|
||||
*
|
||||
* @return array Data to return to AJAX response
|
||||
*/
|
||||
function compare_remote_attachments( $blogs, $all_attachments, $progress ) {
|
||||
if ( ! is_array( $blogs ) ) {
|
||||
$blogs = unserialize( stripslashes( $blogs ) );
|
||||
}
|
||||
if ( ! is_array( $all_attachments ) ) {
|
||||
$all_attachments = unserialize( stripslashes( $all_attachments ) );
|
||||
}
|
||||
|
||||
$files_to_migrate = array();
|
||||
$finish = time() + $this->media_diff_batch_time;
|
||||
|
||||
foreach ( $all_attachments as $blog_id => $attachments ) {
|
||||
foreach ( $attachments as $remote_attachment ) {
|
||||
|
||||
if ( time() >= $finish ) {
|
||||
break;
|
||||
}
|
||||
|
||||
// find local attachment
|
||||
$local_attachment = $this->find_attachment( $remote_attachment );
|
||||
if ( false === $local_attachment ) {
|
||||
// local attachment doesn't exist, definitely migrate remote
|
||||
$this->maybe_queue_attachment( $files_to_migrate, $remote_attachment );
|
||||
} else {
|
||||
// local attachment already exists
|
||||
// check the timestamps on the attachment
|
||||
$remote_timestamp = strtotime( $remote_attachment['date'] );
|
||||
$local_timestamp = strtotime( $local_attachment['date'] );
|
||||
|
||||
if ( $remote_timestamp != $local_timestamp ) {
|
||||
// timestamps are different, let's migrate remote
|
||||
$this->maybe_queue_attachment( $files_to_migrate, $remote_attachment );
|
||||
} else {
|
||||
// only migrate if the local files are missing
|
||||
$this->maybe_queue_attachment( $files_to_migrate, $remote_attachment, $local_attachment );
|
||||
}
|
||||
}
|
||||
|
||||
$blogs[ $blog_id ]['last_post'] = $remote_attachment['ID'];
|
||||
$progress++;
|
||||
}
|
||||
}
|
||||
|
||||
$return = array(
|
||||
'files_to_migrate' => $files_to_migrate,
|
||||
'blogs' => $blogs,
|
||||
'determine_progress' => $progress,
|
||||
);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an attachment in a specific blog
|
||||
*
|
||||
* @param array $attachment
|
||||
*
|
||||
* @return array|bool Attachment, false if not found
|
||||
*/
|
||||
function find_attachment( $attachment ) {
|
||||
global $wpdb;
|
||||
$prefix = $wpdb->base_prefix;
|
||||
|
||||
if ( is_multisite() ) {
|
||||
$blog_ids = $this->get_blog_ids();
|
||||
|
||||
// check the blog exists
|
||||
if ( ! in_array( $attachment['blog_id'], $blog_ids ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$prefix = $wpdb->get_blog_prefix( $attachment['blog_id'] );
|
||||
}
|
||||
|
||||
$filename = $attachment['file'];
|
||||
|
||||
$dir_prefix = ( isset( $attachment['dir_prefix'] ) && strlen( $attachment['dir_prefix'] ) ) ? $attachment['dir_prefix'] : $this->get_dir_prefix( $attachment );
|
||||
// file names are stored in DB without dir prefix, so if the file has one then we need to remove it
|
||||
$filename = str_replace( $dir_prefix, '', $filename );
|
||||
|
||||
$local_attachment = $this->get_attachment_results( $prefix, 'row', array( $attachment['blog_id'], $filename ) );
|
||||
|
||||
if ( empty( $local_attachment ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$local_attachment = $this->process_attachment_data( $local_attachment );
|
||||
|
||||
return $local_attachment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an attachment
|
||||
*
|
||||
* Adds the physical file size to an attachment including file sizes for all resized images
|
||||
*
|
||||
* @param array $attachment The attachment to process
|
||||
*
|
||||
* @return array The updated attachment
|
||||
*/
|
||||
function process_attachment_data( $attachment ) {
|
||||
// prepend site directory prefix for multisite blogs
|
||||
$attachment['dir_prefix'] = $this->get_dir_prefix( $attachment );
|
||||
if ( is_multisite() && $attachment['dir_prefix'] ) {
|
||||
$attachment['file'] = $attachment['dir_prefix'] . $attachment['file'];
|
||||
}
|
||||
|
||||
// use the correct directory for image size files
|
||||
$upload_dir = str_replace( basename( $attachment['file'] ), '', $attachment['file'] );
|
||||
if ( ! empty( $attachment['metadata'] ) ) {
|
||||
$attachment['metadata'] = @unserialize( $attachment['metadata'] );
|
||||
if ( ! empty( $attachment['metadata']['sizes'] ) && is_array( $attachment['metadata']['sizes'] ) ) {
|
||||
foreach ( $attachment['metadata']['sizes'] as $size ) {
|
||||
if ( empty( $size['file'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$size_data = array( 'file' => $upload_dir . $size['file'] );
|
||||
$size_data = $this->apply_file_size( $size_data );
|
||||
|
||||
$attachment['sizes'][] = $size_data;
|
||||
}
|
||||
}
|
||||
}
|
||||
unset( $attachment['metadata'] );
|
||||
|
||||
// get size of image on disk
|
||||
$attachment = $this->apply_file_size( $attachment );
|
||||
|
||||
return $attachment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove local files from the uploads directory
|
||||
*
|
||||
* @param mixed $local_files Files to remove
|
||||
*
|
||||
* @return array $errors Array of errors
|
||||
*/
|
||||
function remove_local_media_files( $local_files ) {
|
||||
if ( ! is_array( $local_files ) ) {
|
||||
$local_files = @unserialize( $local_files );
|
||||
}
|
||||
|
||||
$errors = array();
|
||||
|
||||
if ( empty( $local_files ) ) {
|
||||
return $errors;
|
||||
}
|
||||
|
||||
$upload_dir = $this->uploads_dir();
|
||||
|
||||
foreach ( $local_files as $local_file ) {
|
||||
if ( false === $this->filesystem->unlink( $upload_dir . $local_file ) && $this->filesystem->file_exists( $upload_dir . $local_file ) ) {
|
||||
$errors[] = sprintf( __( 'Could not delete "%s"', 'wp-migrate-db-pro-media-files' ), $upload_dir . $local_file ) . ' (#122mf)';
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare a set of files with those on the local filesystem
|
||||
*
|
||||
* @param mixed $files Files to compare
|
||||
* @param string $intent
|
||||
*
|
||||
* @return array $files_to_remove Files that do not exist locally
|
||||
*/
|
||||
function get_files_not_on_local( $files, $intent ) {
|
||||
if ( ! is_array( $files ) ) {
|
||||
$files = @unserialize( $files );
|
||||
}
|
||||
$upload_dir = $this->uploads_dir();
|
||||
|
||||
$files_to_remove = array();
|
||||
|
||||
foreach ( $files as $file ) {
|
||||
if ( ! $this->filesystem->file_exists( $upload_dir . apply_filters( 'wpmdbmf_file_not_on_local', $file, $intent, $this ) ) ) {
|
||||
$files_to_remove[] = $file;
|
||||
}
|
||||
}
|
||||
|
||||
return $files_to_remove;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a remote image size file exists locally
|
||||
*
|
||||
* @param array $remote_size Remote attachment size
|
||||
* @param array $local_attachment Local attachment
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function local_image_size_file_exists( $remote_size, $local_attachment ) {
|
||||
if ( empty( $local_attachment['sizes'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ( $local_attachment['sizes'] as $size ) {
|
||||
if ( $size['file'] == $remote_size['file'] ) {
|
||||
if ( isset( $size['file_size'] ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the physical file size in an attachment
|
||||
*
|
||||
* Used for attachments files and resized images files
|
||||
*
|
||||
* @param array $attachment Attachment
|
||||
*
|
||||
* @return array Updated attachment
|
||||
*/
|
||||
function apply_file_size( $attachment ) {
|
||||
if ( ! isset( $attachment['file'] ) ) {
|
||||
return $attachment;
|
||||
}
|
||||
|
||||
// get size of image on disk
|
||||
$size = $this->get_file_size( $attachment['file'], ( isset( $attachment['dir_prefix'] ) ? $attachment['dir_prefix'] : '' ) );
|
||||
if ( false !== $size ) {
|
||||
$attachment['file_size'] = $size;
|
||||
}
|
||||
|
||||
return $attachment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate size on disk of a file
|
||||
*
|
||||
* @param string $file File path
|
||||
* @param string $dir_prefix Multisite blog specific directory
|
||||
*
|
||||
* @return int|bool File size if exists, false otherwise
|
||||
*/
|
||||
function get_file_size( $file, $dir_prefix = '' ) {
|
||||
$upload_dir = untrailingslashit( $this->uploads_dir() );
|
||||
if ( ! $this->filesystem->file_exists( $upload_dir ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! is_multisite() && $dir_prefix ) {
|
||||
$file = str_replace( $dir_prefix, '', $file );
|
||||
}
|
||||
|
||||
$file = $upload_dir . DIRECTORY_SEPARATOR . $file;
|
||||
if ( ! $this->filesystem->file_exists( $file ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->filesystem->filesize( $file );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the directory prefix for an attachment in a multisite blog
|
||||
*
|
||||
* @param array $attachment Attachment
|
||||
*
|
||||
* @return string Directory prefix
|
||||
*/
|
||||
function get_dir_prefix( $attachment ) {
|
||||
$dir_prefix = ''; // nothing for default blogs
|
||||
|
||||
if ( isset( $attachment['blog_id'] ) && ! $this->is_current_blog( $attachment['blog_id'] ) ) {
|
||||
if ( defined( 'UPLOADBLOGSDIR' ) ) {
|
||||
$dir_prefix = sprintf( '%s/files/', $attachment['blog_id'] );
|
||||
} else {
|
||||
$dir_prefix = sprintf( 'sites/%s/', $attachment['blog_id'] );
|
||||
}
|
||||
}
|
||||
|
||||
return $dir_prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base uploads directory
|
||||
*
|
||||
* @return string Path to uploads directory
|
||||
*/
|
||||
function uploads_dir() {
|
||||
static $upload_dir;
|
||||
|
||||
if ( ! is_null( $upload_dir ) ) {
|
||||
return $upload_dir;
|
||||
}
|
||||
|
||||
if ( defined( 'UPLOADBLOGSDIR' ) ) {
|
||||
$upload_dir = trailingslashit( ABSPATH ) . UPLOADBLOGSDIR;
|
||||
} else {
|
||||
$upload_dir = wp_upload_dir();
|
||||
$upload_dir = $upload_dir['basedir'];
|
||||
}
|
||||
|
||||
if ( is_multisite() ) {
|
||||
// Remove multisite postfix
|
||||
$upload_dir = untrailingslashit( $upload_dir );
|
||||
$upload_dir = preg_replace( '/\/sites\/(\d)+$/', '', $upload_dir );
|
||||
}
|
||||
|
||||
$upload_dir = trailingslashit( $upload_dir );
|
||||
|
||||
return $upload_dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of the blogs in the site to be processed by the addon
|
||||
*
|
||||
* @return array Blogs to be processed
|
||||
*/
|
||||
function get_blogs() {
|
||||
global $wpdb;
|
||||
|
||||
$blogs = array();
|
||||
|
||||
if ( is_multisite() ) {
|
||||
$blog_ids = $this->get_blog_ids();
|
||||
foreach ( $blog_ids as $blog_id ) {
|
||||
$blogs[ $blog_id ] = array(
|
||||
'prefix' => $wpdb->get_blog_prefix( $blog_id ),
|
||||
'last_post' => 0,
|
||||
'processed' => 0,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$blogs[1] = array(
|
||||
'prefix' => $wpdb->base_prefix,
|
||||
'last_post' => 0, // record last post id process to be used as an offset in the next batch for the blog
|
||||
'processed' => 0, // flag to record if we have processed all attachments for the blog
|
||||
);
|
||||
}
|
||||
|
||||
return $blogs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the IDs of the blogs for the multisite
|
||||
*
|
||||
* @return array Blog ID's
|
||||
*/
|
||||
function get_blog_ids() {
|
||||
$blog_ids = array();
|
||||
|
||||
if ( ! is_multisite() ) {
|
||||
return $blog_ids;
|
||||
}
|
||||
|
||||
$args = array(
|
||||
'spam' => 0,
|
||||
'deleted' => 0,
|
||||
'archived' => 0,
|
||||
'number' => false
|
||||
);
|
||||
|
||||
if ( version_compare( $GLOBALS['wp_version'], '4.6', '>=' ) ) {
|
||||
$blogs = get_sites( $args );
|
||||
} else {
|
||||
$blogs = wp_get_sites( $args );
|
||||
}
|
||||
|
||||
foreach ( $blogs as $blog ) {
|
||||
$blog = (array) $blog;
|
||||
if ( apply_filters( 'wpmdbmf_include_subsite', true, $blog['blog_id'], $this ) ) {
|
||||
$blog_ids[] = $blog['blog_id'];
|
||||
}
|
||||
}
|
||||
|
||||
return $blog_ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the blog ID with the current site specified in wp-config.php
|
||||
*
|
||||
* @param int $blog_id Blog ID
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function is_current_blog( $blog_id ) {
|
||||
$default = defined( 'BLOG_ID_CURRENT_SITE' ) ? BLOG_ID_CURRENT_SITE : 1;
|
||||
|
||||
if ( $default === (int) $blog_id ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for "wpmdbmf_include_subsite" filter to disallow subsite's media to be migrated if not selected.
|
||||
*
|
||||
* @param bool $value
|
||||
* @param int $blog_id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function include_subsite( $value, $blog_id ) {
|
||||
$this->set_post_data();
|
||||
|
||||
if ( is_null( $this->form_data ) && ! empty( $this->state_data['form_data'] ) ) {
|
||||
$this->form_data = $this->parse_migration_form_data( $this->state_data['form_data'] );
|
||||
}
|
||||
|
||||
if ( false === $value || empty( $this->form_data['mf_select_subsites'] ) || empty( $this->form_data['mf_selected_subsites'] ) ) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if ( ! in_array( $blog_id, $this->form_data['mf_selected_subsites'] ) ) {
|
||||
$value = false;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns validated and sanitized form data.
|
||||
*
|
||||
* @param array|string $data
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
function parse_migration_form_data( $data ) {
|
||||
$form_data = parent::parse_migration_form_data( $data );
|
||||
|
||||
$form_data = array_intersect_key( $form_data, array_flip( $this->accepted_fields ) );
|
||||
|
||||
return $form_data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,619 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class WPMDBPro_Media_Files_Local
|
||||
*
|
||||
* Handles all functionality and AJAX requests that are only required on the "local" site.
|
||||
*/
|
||||
class WPMDBPro_Media_Files_Local extends WPMDBPro_Media_Files_Base {
|
||||
|
||||
public function __construct( $plugin_file_path ) {
|
||||
parent::__construct( $plugin_file_path );
|
||||
|
||||
// Local AJAX handlers
|
||||
add_action( 'wp_ajax_wpmdbmf_prepare_determine_media', array( $this, 'ajax_prepare_determine_media' ) );
|
||||
add_action( 'wp_ajax_wpmdbmf_determine_media_to_migrate_recursive', array( $this, 'ajax_determine_media_to_migrate_recursive', ) );
|
||||
add_action( 'wp_ajax_wpmdbmf_migrate_media', array( $this, 'ajax_migrate_media' ) );
|
||||
add_action( 'wp_ajax_wpmdbmf_remove_files_recursive', array( $this, 'ajax_remove_files_recursive' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX initial request before determining media to migrate
|
||||
*
|
||||
* @see WPMDBPro_Media_Files_Remote::respond_to_get_remote_media_info
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function ajax_prepare_determine_media() {
|
||||
$this->check_ajax_referer( 'prepare-determine-media' );
|
||||
$this->set_time_limit();
|
||||
|
||||
$key_rules = array(
|
||||
'action' => 'key',
|
||||
'migration_state_id' => 'key',
|
||||
'nonce' => 'key',
|
||||
);
|
||||
|
||||
$this->set_post_data( $key_rules );
|
||||
|
||||
$data = array();
|
||||
$data['action'] = 'wpmdbmf_get_remote_media_info';
|
||||
$data['remote_state_id'] = $this->state_data['remote_state_id'];
|
||||
$data['intent'] = $this->state_data['intent'];
|
||||
$data['sig'] = $this->create_signature( $data, $this->state_data['key'] );
|
||||
$ajax_url = trailingslashit( $this->state_data['url'] ) . 'wp-admin/admin-ajax.php';
|
||||
$response = $this->remote_post( $ajax_url, $data, __FUNCTION__ );
|
||||
$response = $this->verify_remote_post_response( $response );
|
||||
if ( isset( $response['wpmdb_error'] ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$return['attachment_batch_limit'] = $this->media_diff_batch_limit;
|
||||
$return['remote_uploads_url'] = $response['remote_uploads_url'];
|
||||
$return['remote_max_upload_size'] = $response['remote_max_upload_size'];
|
||||
|
||||
// determine the size of the attachments in scope for migration
|
||||
if ( 'pull' == $this->state_data['intent'] ) {
|
||||
$return['attachment_count'] = $response['remote_total_attachments'];
|
||||
$return['blogs'] = $response['blogs'];
|
||||
} else {
|
||||
$return['attachment_count'] = $this->get_local_attachments_count();
|
||||
$return['blogs'] = serialize( $this->get_blogs() );
|
||||
}
|
||||
|
||||
$result = $this->end_ajax( json_encode( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback used by the recursive AJAX request to determine media to migrate
|
||||
*
|
||||
* @see WPMDBPro_Media_Files_Remote::respond_to_get_remote_attachment_batch
|
||||
* @see WPMDBPro_Media_Files_Remote::respond_to_compare_remote_attachments
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function ajax_determine_media_to_migrate_recursive() {
|
||||
$this->check_ajax_referer( 'determine-media-to-migrate-recursive' );
|
||||
$this->set_time_limit();
|
||||
|
||||
$key_rules = array(
|
||||
'action' => 'key',
|
||||
'migration_state_id' => 'key',
|
||||
'determine_progress' => 'positive_int',
|
||||
'attachment_count' => 'positive_int',
|
||||
'remote_uploads_url' => 'url',
|
||||
'remove_local_media' => 'positive_int',
|
||||
'copy_entire_media' => 'positive_int',
|
||||
'blogs' => 'serialized',
|
||||
'attachment_batch_limit' => 'positive_int',
|
||||
'nonce' => 'key',
|
||||
);
|
||||
|
||||
$this->set_post_data( $key_rules );
|
||||
|
||||
if ( ! in_array( $this->state_data['intent'], array( 'pull', 'push' ) ) ) {
|
||||
$error_msg = __( 'Incorrect migration type supplied', 'wp-migrate-db-pro-media-files' ) . ' (#120mf)';
|
||||
$return = array( 'wpmdb_error' => 1, 'body' => $error_msg );
|
||||
$this->log_error( $error_msg );
|
||||
$result = $this->end_ajax( json_encode( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
// get batch of attachments and check if they need migrating
|
||||
if ( 'pull' == $this->state_data['intent'] ) {
|
||||
// get the remote batch
|
||||
$data = array();
|
||||
$data['action'] = 'wpmdbmf_get_remote_attachment_batch';
|
||||
$data['remote_state_id'] = $this->state_data['remote_state_id'];
|
||||
$data['intent'] = $this->state_data['intent'];
|
||||
$data['blogs'] = stripslashes( $this->state_data['blogs'] );
|
||||
$data['attachment_batch_limit'] = $this->state_data['attachment_batch_limit'];
|
||||
$data['sig'] = $this->create_signature( $data, $this->state_data['key'] );
|
||||
$ajax_url = trailingslashit( $this->state_data['url'] ) . 'wp-admin/admin-ajax.php';
|
||||
$response = $this->remote_post( $ajax_url, $data, __FUNCTION__ );
|
||||
$response = $this->verify_remote_post_response( $response );
|
||||
if ( isset( $response['wpmdb_error'] ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$response = apply_filters( 'wpmdbmf_get_remote_attachment_batch_response', $response, 'pull', $this );
|
||||
|
||||
if ( '1' == $this->state_data['copy_entire_media'] ) {
|
||||
// skip comparison
|
||||
$return = $this->queue_all_attachments( $response['blogs'], $response['remote_attachments'], $this->state_data['determine_progress'] );
|
||||
} else {
|
||||
// compare batch against local attachments
|
||||
$return = $this->compare_remote_attachments( $response['blogs'], $response['remote_attachments'], $this->state_data['determine_progress'] );
|
||||
}
|
||||
} else {
|
||||
// get the local batch
|
||||
$batch = $this->get_local_attachments_batch( $this->state_data['blogs'], $this->state_data['attachment_batch_limit'] );
|
||||
|
||||
if ( '1' == $this->state_data['copy_entire_media'] ) {
|
||||
// skip comparison
|
||||
$return = $this->queue_all_attachments( $batch['blogs'], $batch['attachments'], $this->state_data['determine_progress'] );
|
||||
} else {
|
||||
// send batch to remote to compare against remote attachments
|
||||
$data = array();
|
||||
$data['action'] = 'wpmdbmf_compare_remote_attachments';
|
||||
$data['remote_state_id'] = $this->state_data['remote_state_id'];
|
||||
$data['intent'] = $this->state_data['intent'];
|
||||
$data['blogs'] = serialize( $batch['blogs'] );
|
||||
$data['determine_progress'] = $this->state_data['determine_progress'];
|
||||
$data['remote_attachments'] = serialize( $batch['attachments'] );
|
||||
$data['sig'] = $this->create_signature( $data, $this->state_data['key'] );
|
||||
$data['remote_attachments'] = addslashes( $data['remote_attachments'] ); // will be unslashed before sig is checked
|
||||
$ajax_url = trailingslashit( $this->state_data['url'] ) . 'wp-admin/admin-ajax.php';
|
||||
$response = $this->remote_post( $ajax_url, $data, __FUNCTION__ );
|
||||
$return = $this->verify_remote_post_response( $response );
|
||||
if ( isset( $return['wpmdb_error'] ) ) {
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// persist settings across requests
|
||||
$return['copy_entire_media'] = $this->state_data['copy_entire_media'];
|
||||
$return['remove_local_media'] = $this->state_data['remove_local_media'];
|
||||
$return['remote_uploads_url'] = $this->state_data['remote_uploads_url'];
|
||||
$return['attachment_count'] = $this->state_data['attachment_count'];
|
||||
$return['determine_progress'] = isset( $return['determine_progress'] ) ? $return['determine_progress'] : 0;
|
||||
$return['blogs'] = serialize( $return['blogs'] );
|
||||
$return['total_size'] = array_sum( $return['files_to_migrate'] );
|
||||
$return['files_to_migrate'] = isset( $return['files_to_migrate'] ) ? $return['files_to_migrate'] : array();
|
||||
|
||||
$result = $this->end_ajax( json_encode( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX wrapper for the push/pull migration of media files,
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function ajax_migrate_media() {
|
||||
$this->check_ajax_referer( 'migrate-media' );
|
||||
$this->set_time_limit();
|
||||
|
||||
$key_rules = array(
|
||||
'action' => 'key',
|
||||
'migration_state_id' => 'key',
|
||||
'file_chunk' => 'array',
|
||||
'nonce' => 'key',
|
||||
);
|
||||
|
||||
$this->set_post_data( $key_rules );
|
||||
|
||||
if ( 'pull' == $this->state_data['intent'] ) {
|
||||
$result = $this->process_pull_request();
|
||||
} else {
|
||||
$result = $this->process_push_request();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Download files from the remote site
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
function process_pull_request() {
|
||||
$files_to_download = $this->state_data['file_chunk'];
|
||||
$remote_uploads_url = trailingslashit( $this->state_data['remote_uploads_url'] );
|
||||
$parsed = $this->parse_url( $this->state_data['url'] );
|
||||
|
||||
if ( ! empty( $parsed['user'] ) ) {
|
||||
$credentials = sprintf( '%s:%s@', $parsed['user'], $parsed['pass'] );
|
||||
$remote_uploads_url = str_replace( '://', '://' . $credentials, $remote_uploads_url );
|
||||
}
|
||||
|
||||
$upload_dir = $this->uploads_dir();
|
||||
|
||||
$errors = array();
|
||||
$transfers = array();
|
||||
foreach ( $files_to_download as $file_to_download ) {
|
||||
$current_transfer = array( 'file' => $file_to_download, 'error' => false );
|
||||
$remote_url = $remote_uploads_url . apply_filters( 'wpmdbmf_file_to_download', $file_to_download, 'pull', $this );
|
||||
$temp_file_path = $this->download_url( $remote_url );
|
||||
|
||||
if ( is_wp_error( $temp_file_path ) ) {
|
||||
$download_error = $temp_file_path->get_error_message();
|
||||
$current_transfer['error'] = $download_error;
|
||||
$errors[] = sprintf( __( 'Could not download file: %1$s - %2$s', 'wp-migrate-db-pro-media-files' ), $remote_url, $download_error );
|
||||
$transfers[] = $current_transfer;
|
||||
continue;
|
||||
}
|
||||
|
||||
$date = str_replace( basename( $file_to_download ), '', $file_to_download );
|
||||
$new_path = $upload_dir . $date . basename( $file_to_download );
|
||||
$folder = dirname( $new_path );
|
||||
|
||||
// WPMDB_Filesystem::mkdir will return true straight away if the dir exists
|
||||
if ( false === $this->filesystem->mkdir( $folder ) ) {
|
||||
$error_string = sprintf( __( 'Error attempting to create required directory: %s', 'wp-migrate-db-pro-media-files' ), $folder ) . ' (#104mf)';
|
||||
$errors[] = $error_string;
|
||||
$current_transfer['error'] = $error_string;
|
||||
|
||||
} elseif ( false === $this->filesystem->move( $temp_file_path, $new_path ) ) {
|
||||
$error_string = sprintf( __( 'Error attempting to move downloaded file. Temp path: %1$s - New Path: %2$s', 'wp-migrate-db-pro-media-files' ), $temp_file_path, $new_path ) . ' (#105mf)';
|
||||
$errors[] = $error_string;
|
||||
$current_transfer['error'] = $error_string;
|
||||
}
|
||||
|
||||
$transfers[] = $current_transfer;
|
||||
|
||||
// set default permissions on moved file
|
||||
$this->filesystem->chmod( $new_path );
|
||||
}
|
||||
|
||||
$return = array( 'success' => 1, 'transfers' => $transfers );
|
||||
|
||||
if ( ! empty( $errors ) ) {
|
||||
$return['wpmdb_non_fatal_error'] = 1;
|
||||
|
||||
$return['cli_body'] = $errors;
|
||||
$return['body'] = implode( '<br />', $errors ) . '<br />';
|
||||
$error_msg = __( 'Failed attempting to process pull request', 'wp-migrate-db-pro-media-files' ) . ' (#112mf)';
|
||||
$this->log_error( $error_msg, $errors );
|
||||
}
|
||||
|
||||
$result = $this->end_ajax( json_encode( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload files to the remote site
|
||||
*
|
||||
* @see WPMDBPro_Media_Files_Remote::respond_to_push_request
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
function process_push_request() {
|
||||
$files_to_migrate = $this->state_data['file_chunk'];
|
||||
|
||||
$upload_dir = $this->uploads_dir();
|
||||
|
||||
$body = '';
|
||||
foreach ( $files_to_migrate as $file_to_migrate ) {
|
||||
$body .= $this->file_to_multipart( $upload_dir . $file_to_migrate );
|
||||
}
|
||||
|
||||
$post_args = array(
|
||||
'action' => 'wpmdbmf_push_request',
|
||||
'remote_state_id' => $this->state_data['remote_state_id'],
|
||||
'files' => serialize( $files_to_migrate ),
|
||||
);
|
||||
|
||||
$post_args['sig'] = $this->create_signature( $post_args, $this->state_data['key'] );
|
||||
|
||||
$body .= $this->array_to_multipart( $post_args );
|
||||
|
||||
$args['body'] = $body;
|
||||
$ajax_url = trailingslashit( $this->state_data['url'] ) . 'wp-admin/admin-ajax.php';
|
||||
$response = $this->remote_post( $ajax_url, '', __FUNCTION__, $args );
|
||||
$response = $this->verify_remote_post_response( $response );
|
||||
if ( isset( $response['wpmdb_error'] ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$result = $this->end_ajax( json_encode( $response ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue up all attachments in batch to be migrated
|
||||
*
|
||||
* @param mixed $blogs Blogs
|
||||
* @param mixed $all_attachments Batch of attachments
|
||||
* @param int $progress Progress count
|
||||
*
|
||||
* @return array Data to return to AJAX response
|
||||
*/
|
||||
function queue_all_attachments( $blogs, $all_attachments, $progress ) {
|
||||
if ( ! is_array( $blogs ) ) {
|
||||
$blogs = unserialize( stripslashes( $blogs ) );
|
||||
}
|
||||
if ( ! is_array( $all_attachments ) ) {
|
||||
$all_attachments = unserialize( stripslashes( $all_attachments ) );
|
||||
}
|
||||
|
||||
$files_to_migrate = array();
|
||||
$finish = time() + $this->media_diff_batch_time;
|
||||
|
||||
foreach ( $all_attachments as $blog_id => $attachments ) {
|
||||
foreach ( $attachments as $remote_attachment ) {
|
||||
|
||||
if ( time() >= $finish ) {
|
||||
break;
|
||||
}
|
||||
|
||||
$this->maybe_queue_attachment( $files_to_migrate, $remote_attachment );
|
||||
|
||||
$blogs[ $blog_id ]['last_post'] = $remote_attachment['ID'];
|
||||
$progress++;
|
||||
}
|
||||
}
|
||||
|
||||
$return = array(
|
||||
'files_to_migrate' => $files_to_migrate,
|
||||
'blogs' => $blogs,
|
||||
'determine_progress' => $progress,
|
||||
);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX recursive request to remove all media files if skipping comparison in batches
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function ajax_remove_files_recursive() {
|
||||
$this->check_ajax_referer( 'remove-files-recursive' );
|
||||
$this->set_time_limit();
|
||||
|
||||
$key_rules = array(
|
||||
'action' => 'key',
|
||||
'migration_state_id' => 'key',
|
||||
'compare' => 'positive_int',
|
||||
'offset' => 'string',
|
||||
'nonce' => 'key',
|
||||
);
|
||||
|
||||
$this->set_post_data( $key_rules );
|
||||
|
||||
$this->state_data['offset'] = (array) json_decode( $this->state_data['offset'] );
|
||||
|
||||
if ( 'pull' == $this->state_data['intent'] ) {
|
||||
// send batch of files to be compared on the remote
|
||||
// receive batch of files to be deleted
|
||||
$return = $this->remove_local_files_recursive( $this->state_data['url'], $this->state_data['key'], $this->state_data['compare'], $this->state_data['offset'] );
|
||||
} else {
|
||||
// request a batch from the remote
|
||||
// compare received batch of files with local filesystem
|
||||
// send files to be deleted to the remote for deletion
|
||||
$return = $this->remove_remote_files_recursive( $this->state_data['url'], $this->state_data['key'], $this->state_data['compare'], $this->state_data['offset'] );
|
||||
}
|
||||
|
||||
// persist the comparison flag across recursive requests
|
||||
$return['compare'] = $this->state_data['compare'];
|
||||
|
||||
$result = $this->end_ajax( json_encode( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove local media files in batches that can be called recursively
|
||||
*
|
||||
* Used in pull requests
|
||||
*
|
||||
* @see WPMDBPro_Media_Files_Remote::respond_to_compare_local_media_files
|
||||
*
|
||||
* @param string $remote_url The remote site URL
|
||||
* @param string $remote_key The remote site key
|
||||
* @param int $compare_with_remote 1 = Will compare files existence on remote, 0 = no comparison
|
||||
* @param array $offset Offset (blog id, post id) of last file in batch
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function remove_local_files_recursive( $remote_url, $remote_key, $compare_with_remote, $offset = null ) {
|
||||
if ( 1 === ( int ) $compare_with_remote ) {
|
||||
$local_media_files = $this->get_local_media_attachment_files_batch( $offset );
|
||||
|
||||
if ( empty( $local_media_files['files'] ) ) {
|
||||
return array( 'offset' => '', 'remove_files' => 0 );
|
||||
}
|
||||
|
||||
// send batch of files to be compared on the remote
|
||||
$data = array();
|
||||
$data['action'] = 'wpmdbmf_compare_local_media_files';
|
||||
$data['remote_state_id'] = $this->state_data['remote_state_id'];
|
||||
$data['files'] = serialize( $local_media_files['files'] );
|
||||
$data['sig'] = $this->create_signature( $data, $remote_key );
|
||||
$data['files'] = addslashes( $data['files'] ); // will be unslashed before sig is checked
|
||||
$ajax_url = trailingslashit( $remote_url ) . 'wp-admin/admin-ajax.php';
|
||||
$response = $this->remote_post( $ajax_url, $data, __FUNCTION__ );
|
||||
$response = $this->verify_remote_post_response( $response );
|
||||
if ( isset( $response['wpmdb_error'] ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
// files that don't exist returned as new batch to delete
|
||||
$files_to_remove = isset( $response['files_to_remove'] ) ? $response['files_to_remove'] : array();
|
||||
|
||||
$return_offset = array( $local_media_files['last_blog_id'], $local_media_files['last_attachment_id'] );
|
||||
} else {
|
||||
$local_media_files = $this->get_local_media_files_batch( array_pop( $offset ) );
|
||||
|
||||
if ( ! $local_media_files ) {
|
||||
return array( 'offset' => '', 'remove_files' => 0 );
|
||||
}
|
||||
|
||||
$files_to_remove = $local_media_files;
|
||||
|
||||
$return_offset = end( $local_media_files );
|
||||
}
|
||||
|
||||
$errors = $this->remove_local_media_files( $files_to_remove );
|
||||
|
||||
$return = array(
|
||||
'offset' => $return_offset,
|
||||
'remove_files' => 1,
|
||||
);
|
||||
|
||||
if ( ! empty( $errors ) ) {
|
||||
$return['wpmdb_non_fatal_error'] = 1;
|
||||
|
||||
$return['cli_body'] = $errors;
|
||||
$return['body'] = implode( '<br />', $errors ) . '<br />';
|
||||
$error_msg = __( 'There were errors when removing local media files', 'wp-migrate-db-pro-media-files' ) . ' (#123mf)';
|
||||
$this->log_error( $error_msg, $errors );
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove remote media files in batches that can be called recursively
|
||||
*
|
||||
* Used in push requests
|
||||
*
|
||||
* @see WPMDBPro_Media_Files_Remote::respond_to_get_local_media_files_batch
|
||||
* @see WPMDBPro_Media_Files_Remote::respond_to_remove_local_media_files
|
||||
*
|
||||
* @param string $remote_url The remote site URL
|
||||
* @param string $remote_key The remote site key
|
||||
* @param int $compare_with_remote 1 = Will compare files existence on remote, 0 = no comparison
|
||||
* @param array $offset Offset (blog_id, post_id) of last file in previous batch to start this batch from
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function remove_remote_files_recursive( $remote_url, $remote_key, $compare_with_remote, $offset = null ) {
|
||||
// request a batch from the remote
|
||||
$data = array();
|
||||
$data['action'] = 'wpmdbmf_get_local_media_files_batch';
|
||||
$data['remote_state_id'] = $this->state_data['remote_state_id'];
|
||||
$data['compare'] = $compare_with_remote;
|
||||
$data['offset'] = json_encode( $offset );
|
||||
$data['sig'] = $this->create_signature( $data, $remote_key );
|
||||
$ajax_url = trailingslashit( $remote_url ) . 'wp-admin/admin-ajax.php';
|
||||
$response = $this->remote_post( $ajax_url, $data, __FUNCTION__ );
|
||||
$response = $this->verify_remote_post_response( $response );
|
||||
|
||||
if ( isset( $response['wpmdb_error'] ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
if ( 1 === ( int ) $compare_with_remote ) {
|
||||
$remote_media_files = $response['local_media_attachment_files'];
|
||||
|
||||
if ( empty( $remote_media_files['files'] ) ) {
|
||||
return array( 'offset' => '', 'remove_files' => 0 );
|
||||
}
|
||||
|
||||
// compare received batch of files with local filesystem
|
||||
$files_to_remove = $this->get_files_not_on_local( $remote_media_files['files'], 'push' );
|
||||
$return_offset = array( $remote_media_files['last_blog_id'], $remote_media_files['last_attachment_id'] );
|
||||
} else {
|
||||
$remote_media_files = $response['local_media_files'];
|
||||
|
||||
if ( ! $remote_media_files ) {
|
||||
return array( 'offset' => '', 'remove_files' => 0 );
|
||||
}
|
||||
|
||||
$files_to_remove = $remote_media_files;
|
||||
$return_offset = end( $remote_media_files );
|
||||
}
|
||||
|
||||
// send files not found on local to the remote for deletion
|
||||
$data = array();
|
||||
$data['action'] = 'wpmdbmf_remove_local_media_files';
|
||||
$data['remote_state_id'] = $this->state_data['remote_state_id'];
|
||||
$data['files_to_remove'] = serialize( $files_to_remove );
|
||||
$data['sig'] = $this->create_signature( $data, $remote_key );
|
||||
$data['files_to_remove'] = addslashes( $data['files_to_remove'] ); // will be unslashed before sig is checked
|
||||
$ajax_url = trailingslashit( $remote_url ) . 'wp-admin/admin-ajax.php';
|
||||
$response = $this->remote_post( $ajax_url, $data, __FUNCTION__ );
|
||||
$response = $this->verify_remote_post_response( $response );
|
||||
if ( isset( $response['wpmdb_error'] ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$response['offset'] = $return_offset;
|
||||
$response['remove_files'] = 1;
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify a remote response is valid
|
||||
*
|
||||
* @param mixed $response Response
|
||||
*
|
||||
* @return mixed Response if valid, error otherwise
|
||||
*/
|
||||
function verify_remote_post_response( $response ) {
|
||||
if ( false === $response ) {
|
||||
$return = array( 'wpmdb_error' => 1, 'body' => $this->error );
|
||||
$error_msg = 'Failed attempting to verify remote post response (#114mf)';
|
||||
$this->log_error( $error_msg, $this->error );
|
||||
$result = $this->end_ajax( json_encode( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
if ( ! is_serialized( trim( $response ) ) ) {
|
||||
$return = array( 'wpmdb_error' => 1, 'body' => $response );
|
||||
$error_msg = 'Failed as the response is not serialized string (#115mf)';
|
||||
$this->log_error( $error_msg, $response );
|
||||
$result = $this->end_ajax( json_encode( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
$response = unserialize( trim( $response ) );
|
||||
|
||||
if ( isset( $response['wpmdb_error'] ) ) {
|
||||
$this->log_error( $response['wpmdb_error'], $response );
|
||||
$result = $this->end_ajax( json_encode( $response ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a remote media file
|
||||
*
|
||||
* @param string $url File to download
|
||||
* @param int $timeout Timeout limit
|
||||
*
|
||||
* @return array|string|WP_Error
|
||||
*/
|
||||
function download_url( $url, $timeout = 300 ) {
|
||||
// WARNING: The file is not automatically deleted, The script must unlink() the file.
|
||||
if ( ! $url ) {
|
||||
return new WP_Error( 'http_no_url', __( 'Invalid URL Provided.' ) );
|
||||
}
|
||||
|
||||
$tmpfname = wp_tempnam( $url );
|
||||
if ( ! $tmpfname ) {
|
||||
return new WP_Error( 'http_no_file', __( 'Could not create Temporary file.' ) );
|
||||
}
|
||||
|
||||
$sslverify = ( 1 == $this->settings['verify_ssl'] ) ? true : false;
|
||||
$args = array(
|
||||
'timeout' => $timeout,
|
||||
'stream' => true,
|
||||
'filename' => $tmpfname,
|
||||
'reject_unsafe_urls' => false,
|
||||
'sslverify' => $sslverify,
|
||||
);
|
||||
|
||||
$response = wp_remote_get( $url, $args );
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
$this->filesystem->unlink( $tmpfname );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
if ( 200 != wp_remote_retrieve_response_code( $response ) ) {
|
||||
$this->filesystem->unlink( $tmpfname );
|
||||
|
||||
return new WP_Error( 'http_404', trim( wp_remote_retrieve_response_message( $response ) ) );
|
||||
}
|
||||
|
||||
return $tmpfname;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,433 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class WPMDBPro_Media_Files_Remote
|
||||
*
|
||||
* Handles all functionality and AJAX requests that are only required on the "remote" site.
|
||||
*/
|
||||
class WPMDBPro_Media_Files_Remote extends WPMDBPro_Media_Files_Base {
|
||||
|
||||
public function __construct( $plugin_file_path ) {
|
||||
parent::__construct( $plugin_file_path );
|
||||
|
||||
// Remote AJAX handlers
|
||||
add_action( 'wp_ajax_nopriv_wpmdbmf_get_remote_media_info', array( $this, 'respond_to_get_remote_media_info' ) );
|
||||
add_action( 'wp_ajax_nopriv_wpmdbmf_get_remote_attachment_batch', array( $this, 'respond_to_get_remote_attachment_batch' ) );
|
||||
add_action( 'wp_ajax_nopriv_wpmdbmf_compare_remote_attachments', array( $this, 'respond_to_compare_remote_attachments' ) );
|
||||
add_action( 'wp_ajax_nopriv_wpmdbmf_push_request', array( $this, 'respond_to_push_request' ) );
|
||||
add_action( 'wp_ajax_nopriv_wpmdbmf_get_local_media_files_batch', array( $this, 'respond_to_get_local_media_files_batch' ) );
|
||||
add_action( 'wp_ajax_nopriv_wpmdbmf_compare_local_media_files', array( $this, 'respond_to_compare_local_media_files' ) );
|
||||
add_action( 'wp_ajax_nopriv_wpmdbmf_remove_local_media_files', array( $this, 'respond_to_remove_local_media_files' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return information about remote site for use in media migration
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function respond_to_get_remote_media_info() {
|
||||
add_filter( 'wpmdb_before_response', array( $this, 'scramble' ) );
|
||||
|
||||
$key_rules = array(
|
||||
'action' => 'key',
|
||||
'remote_state_id' => 'key',
|
||||
'intent' => 'key',
|
||||
'sig' => 'string',
|
||||
);
|
||||
|
||||
$this->set_post_data( $key_rules, 'remote_state_id' );
|
||||
|
||||
$filtered_post = $this->filter_post_elements( $this->state_data, array(
|
||||
'action',
|
||||
'remote_state_id',
|
||||
'intent',
|
||||
) );
|
||||
|
||||
if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) {
|
||||
$return = array(
|
||||
'wpmdb_error' => 1,
|
||||
'body' => $this->invalid_content_verification_error . ' (#100mf)',
|
||||
);
|
||||
$this->log_error( $return['body'], $filtered_post );
|
||||
$result = $this->end_ajax( serialize( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
if ( defined( 'UPLOADBLOGSDIR' ) ) {
|
||||
$upload_url = home_url( UPLOADBLOGSDIR );
|
||||
} else {
|
||||
$upload_dir = wp_upload_dir();
|
||||
$upload_url = $upload_dir['baseurl'];
|
||||
|
||||
if ( is_multisite() ) {
|
||||
// Remove multisite postfix
|
||||
$upload_url = preg_replace( '/\/sites\/(\d)+$/', '', $upload_url );
|
||||
}
|
||||
}
|
||||
|
||||
$return['remote_total_attachments'] = $this->get_local_attachments_count();
|
||||
$return['remote_uploads_url'] = $upload_url;
|
||||
$return['blogs'] = serialize( $this->get_blogs() );
|
||||
$return['remote_max_upload_size'] = $this->get_max_upload_size();
|
||||
|
||||
$result = $this->end_ajax( serialize( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a batch of attachments from the remote site
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function respond_to_get_remote_attachment_batch() {
|
||||
add_filter( 'wpmdb_before_response', array( $this, 'scramble' ) );
|
||||
|
||||
$key_rules = array(
|
||||
'action' => 'key',
|
||||
'remote_state_id' => 'key',
|
||||
'intent' => 'key',
|
||||
'blogs' => 'serialized',
|
||||
'attachment_batch_limit' => 'positive_int',
|
||||
'sig' => 'string',
|
||||
);
|
||||
|
||||
$this->set_post_data( $key_rules, 'remote_state_id' );
|
||||
|
||||
$filtered_post = $this->filter_post_elements( $this->state_data, array(
|
||||
'action',
|
||||
'remote_state_id',
|
||||
'intent',
|
||||
'blogs',
|
||||
'attachment_batch_limit',
|
||||
) );
|
||||
|
||||
$filtered_post['blogs'] = stripslashes( $filtered_post['blogs'] );
|
||||
|
||||
if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) {
|
||||
$return = array(
|
||||
'wpmdb_error' => 1,
|
||||
'body' => $this->invalid_content_verification_error . ' (#116mf)',
|
||||
);
|
||||
$this->log_error( $return['body'], $filtered_post );
|
||||
$result = $this->end_ajax( serialize( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
$batch = $this->get_local_attachments_batch( $filtered_post['blogs'], $filtered_post['attachment_batch_limit'] );
|
||||
$return['remote_attachments'] = addslashes( serialize( $batch['attachments'] ) );
|
||||
$return['blogs'] = addslashes( serialize( $batch['blogs'] ) );
|
||||
|
||||
$result = $this->end_ajax( serialize( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare posted local files with those on the remote server
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function respond_to_compare_remote_attachments() {
|
||||
add_filter( 'wpmdb_before_response', array( $this, 'scramble' ) );
|
||||
|
||||
$key_rules = array(
|
||||
'action' => 'key',
|
||||
'remote_state_id' => 'key',
|
||||
'intent' => 'key',
|
||||
'blogs' => 'serialized',
|
||||
'determine_progress' => 'positive_int',
|
||||
'remote_attachments' => 'serialized',
|
||||
'sig' => 'string',
|
||||
);
|
||||
|
||||
$this->set_post_data( $key_rules, 'remote_state_id' );
|
||||
|
||||
$filtered_post = $this->filter_post_elements( $this->state_data, array(
|
||||
'action',
|
||||
'remote_state_id',
|
||||
'intent',
|
||||
'blogs',
|
||||
'determine_progress',
|
||||
'remote_attachments',
|
||||
) );
|
||||
|
||||
$filtered_post['blogs'] = stripslashes( $filtered_post['blogs'] );
|
||||
$filtered_post['remote_attachments'] = stripslashes( $filtered_post['remote_attachments'] );
|
||||
|
||||
if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) {
|
||||
$return = array(
|
||||
'wpmdb_error' => 1,
|
||||
'body' => $this->invalid_content_verification_error . ' (#118mf)',
|
||||
);
|
||||
$this->log_error( $return['body'], $filtered_post );
|
||||
$result = $this->end_ajax( serialize( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
// compare_remote_attachments will unslash these values again
|
||||
$filtered_post['blogs'] = addslashes( $filtered_post['blogs'] );
|
||||
$filtered_post['remote_attachments'] = addslashes( $filtered_post['remote_attachments'] );
|
||||
|
||||
$return = $this->compare_remote_attachments( $filtered_post['blogs'], $filtered_post['remote_attachments'], $filtered_post['determine_progress'] );
|
||||
$result = $this->end_ajax( serialize( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move uploaded local site files from tmp to uploads directory
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function respond_to_push_request() {
|
||||
add_filter( 'wpmdb_before_response', array( $this, 'scramble' ) );
|
||||
|
||||
$key_rules = array(
|
||||
'action' => 'key',
|
||||
'remote_state_id' => 'key',
|
||||
'files' => 'serialized',
|
||||
'sig' => 'string',
|
||||
);
|
||||
|
||||
$this->set_post_data( $key_rules, 'remote_state_id' );
|
||||
|
||||
$filtered_post = $this->filter_post_elements( $this->state_data, array(
|
||||
'action',
|
||||
'remote_state_id',
|
||||
'files',
|
||||
) );
|
||||
|
||||
$filtered_post['files'] = stripslashes( $filtered_post['files'] );
|
||||
|
||||
if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) {
|
||||
$return = array(
|
||||
'wpmdb_error' => 1,
|
||||
'body' => $this->invalid_content_verification_error . ' (#111mf)',
|
||||
);
|
||||
$this->log_error( $return['body'], $filtered_post );
|
||||
$result = $this->end_ajax( serialize( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
if ( ! isset( $_FILES['media'] ) ) {
|
||||
$return = array(
|
||||
'wpmdb_error' => 1,
|
||||
'body' => __( '$_FILES is empty, the upload appears to have failed', 'wp-migrate-db-pro-media-files' ) . ' (#106mf)',
|
||||
);
|
||||
$this->log_error( $return['body'] );
|
||||
$result = $this->end_ajax( serialize( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
$upload_dir = $this->uploads_dir();
|
||||
|
||||
$files = $this->diverse_array( $_FILES['media'] );
|
||||
$file_paths = unserialize( $filtered_post['files'] );
|
||||
$i = 0;
|
||||
$errors = array();
|
||||
$transfers = array();
|
||||
foreach ( $files as &$file ) {
|
||||
$destination = $upload_dir . apply_filters( 'wpmdbmf_destination_file_path', $file_paths[ $i ], 'push', $this );
|
||||
$folder = dirname( $destination );
|
||||
$current_transfer = array( 'file' => $file_paths[ $i ], 'error' => false );
|
||||
|
||||
if ( false === $this->filesystem->file_exists( $folder ) && false === $this->filesystem->mkdir( $folder ) ) {
|
||||
$error_string = sprintf( __( 'Error attempting to create required directory: %s', 'wp-migrate-db-pro-media-files' ), $folder ) . ' (#108mf)';
|
||||
$errors[] = $error_string;
|
||||
$current_transfer['error'] = $error_string;
|
||||
++$i;
|
||||
$transfers[] = $current_transfer;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( false === $this->filesystem->move_uploaded_file( $file['tmp_name'], $destination ) ) {
|
||||
$error_string = sprintf( __( 'A problem occurred when attempting to move the temp file "%1$s" to "%2$s"', 'wp-migrate-db-pro-media-files' ), $file['tmp_name'], $destination ) . ' (#107mf)';
|
||||
$errors[] = $error_string;
|
||||
$current_transfer['error'] = $error_string;
|
||||
}
|
||||
$transfers[] = $current_transfer;
|
||||
++$i;
|
||||
}
|
||||
|
||||
$return = array( 'success' => 1, 'transfers' => $transfers );
|
||||
|
||||
if ( ! empty( $errors ) ) {
|
||||
$return['wpmdb_non_fatal_error'] = 1;
|
||||
|
||||
$return['cli_body'] = $errors;
|
||||
$return['body'] = implode( '<br />', $errors ) . '<br />';
|
||||
$error_msg = __( 'Failed attempting to respond to push request', 'wp-migrate-db-pro-media-files' ) . ' (#113mf)';
|
||||
$this->log_error( $error_msg, $errors );
|
||||
}
|
||||
|
||||
$result = $this->end_ajax( serialize( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX callback for returning a batch of local media files
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function respond_to_get_local_media_files_batch() {
|
||||
add_filter( 'wpmdb_before_response', array( $this, 'scramble' ) );
|
||||
|
||||
$key_rules = array(
|
||||
'action' => 'key',
|
||||
'remote_state_id' => 'key',
|
||||
'compare' => 'positive_int',
|
||||
'offset' => 'string',
|
||||
'sig' => 'string',
|
||||
);
|
||||
|
||||
$this->set_post_data( $key_rules, 'remote_state_id' );
|
||||
|
||||
$filtered_post = $this->filter_post_elements( $this->state_data, array(
|
||||
'action',
|
||||
'remote_state_id',
|
||||
'compare',
|
||||
'offset',
|
||||
) );
|
||||
|
||||
if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) {
|
||||
$return = array(
|
||||
'wpmdb_error' => 1,
|
||||
'body' => $this->invalid_content_verification_error . ' (#109mf)',
|
||||
);
|
||||
$this->log_error( $return['body'], $filtered_post );
|
||||
$result = $this->end_ajax( serialize( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
$offset = isset( $filtered_post['offset'] ) ? json_decode( $filtered_post['offset'] ) : '0';
|
||||
|
||||
$local_media_files = array();
|
||||
$local_media_attachment_files = array();
|
||||
if ( 1 === (int) $filtered_post['compare'] ) {
|
||||
$local_media_attachment_files = $this->get_local_media_attachment_files_batch( $offset );
|
||||
} else {
|
||||
$local_media_files = $this->get_local_media_files_batch( array_pop( $offset ) );
|
||||
}
|
||||
|
||||
$return = array(
|
||||
'success' => 1,
|
||||
'local_media_files' => $local_media_files,
|
||||
'local_media_attachment_files' => $local_media_attachment_files,
|
||||
);
|
||||
|
||||
$result = $this->end_ajax( serialize( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX callback to compare a posted batch of files with those on local site
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function respond_to_compare_local_media_files() {
|
||||
add_filter( 'wpmdb_before_response', array( $this, 'scramble' ) );
|
||||
|
||||
$key_rules = array(
|
||||
'action' => 'key',
|
||||
'remote_state_id' => 'key',
|
||||
'files' => 'serialized',
|
||||
'sig' => 'string',
|
||||
);
|
||||
|
||||
$this->set_post_data( $key_rules, 'remote_state_id' );
|
||||
|
||||
$filtered_post = $this->filter_post_elements( $this->state_data, array(
|
||||
'action',
|
||||
'remote_state_id',
|
||||
'files',
|
||||
) );
|
||||
|
||||
$filtered_post['files'] = stripslashes( $filtered_post['files'] );
|
||||
|
||||
if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) {
|
||||
$return = array(
|
||||
'wpmdb_error' => 1,
|
||||
'body' => $this->invalid_content_verification_error . ' (#117mf)',
|
||||
);
|
||||
$this->log_error( $return['body'], $filtered_post );
|
||||
$result = $this->end_ajax( serialize( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
// compare files to those on the local filesystem
|
||||
$files_to_remove = $this->get_files_not_on_local( $filtered_post['files'], 'pull' );
|
||||
|
||||
$return = array(
|
||||
'success' => 1,
|
||||
'files_to_remove' => $files_to_remove,
|
||||
);
|
||||
|
||||
$result = $this->end_ajax( serialize( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX callback to remove files for the local filesystem
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function respond_to_remove_local_media_files() {
|
||||
add_filter( 'wpmdb_before_response', array( $this, 'scramble' ) );
|
||||
|
||||
$key_rules = array(
|
||||
'action' => 'key',
|
||||
'remote_state_id' => 'key',
|
||||
'files_to_remove' => 'serialized',
|
||||
'sig' => 'string',
|
||||
);
|
||||
|
||||
$this->set_post_data( $key_rules, 'remote_state_id' );
|
||||
|
||||
$filtered_post = $this->filter_post_elements( $this->state_data, array(
|
||||
'action',
|
||||
'remote_state_id',
|
||||
'files_to_remove',
|
||||
) );
|
||||
|
||||
$filtered_post['files_to_remove'] = stripslashes( $filtered_post['files_to_remove'] );
|
||||
|
||||
if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) {
|
||||
$return = array(
|
||||
'wpmdb_error' => 1,
|
||||
'body' => $this->invalid_content_verification_error . ' (#119mf)',
|
||||
);
|
||||
$this->log_error( $return['body'], $filtered_post );
|
||||
$result = $this->end_ajax( serialize( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
$errors = $this->remove_local_media_files( $filtered_post['files_to_remove'] );
|
||||
|
||||
$return['success'] = 1;
|
||||
|
||||
if ( ! empty( $errors ) ) {
|
||||
$return['wpmdb_non_fatal_error'] = 1;
|
||||
|
||||
$return['cli_body'] = $errors;
|
||||
$return['body'] = implode( '<br />', $errors ) . '<br />';
|
||||
$error_msg = __( 'There were errors when removing local media files from the remote site', 'wp-migrate-db-pro-media-files' ) . ' (#121mf)';
|
||||
$this->log_error( $error_msg, $errors );
|
||||
}
|
||||
|
||||
$result = $this->end_ajax( serialize( $return ) );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class WPMDBPro_Media_Files
|
||||
*
|
||||
* Handles the addon setup and settings
|
||||
*/
|
||||
class WPMDBPro_Media_Files extends WPMDBPro_Addon {
|
||||
|
||||
/**
|
||||
* An array strings used for translations
|
||||
*
|
||||
* @var array $media_strings
|
||||
*/
|
||||
protected $media_strings;
|
||||
|
||||
/**
|
||||
* An instance of WPMDBPro_Media_Files_Local
|
||||
*
|
||||
* @var object $media_files_local
|
||||
*/
|
||||
public $media_files_local;
|
||||
|
||||
/**
|
||||
* An instance of WPMDBPro_Media_Files_Remote
|
||||
*
|
||||
* @var object $media_files_remote
|
||||
*/
|
||||
public $media_files_remote;
|
||||
|
||||
function __construct( $plugin_file_path ) {
|
||||
parent::__construct( $plugin_file_path );
|
||||
|
||||
$this->plugin_slug = 'wp-migrate-db-pro-media-files';
|
||||
$this->plugin_version = $GLOBALS['wpmdb_meta']['wp-migrate-db-pro-media-files']['version'];
|
||||
|
||||
if ( ! $this->meets_version_requirements( '1.7.1' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_action( 'wpmdb_after_advanced_options', array( $this, 'migration_form_controls' ) );
|
||||
add_action( 'wpmdb_load_assets', array( $this, 'load_assets' ) );
|
||||
add_action( 'wpmdb_diagnostic_info', array( $this, 'diagnostic_info' ) );
|
||||
add_action( 'wpmdbmf_after_migration_options', array( $this, 'after_migration_options_template' ) );
|
||||
add_filter( 'wpmdb_establish_remote_connection_data', array( $this, 'establish_remote_connection_data' ) );
|
||||
add_filter( 'wpmdb_nonces', array( $this, 'add_nonces' ) );
|
||||
add_filter( 'wpmdb_data', array( $this, 'js_variables' ) );
|
||||
|
||||
$this->media_files_local = new WPMDBPro_Media_Files_Local( $plugin_file_path );
|
||||
$this->media_files_remote = new WPMDBPro_Media_Files_Remote( $plugin_file_path );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the media settings to the migration setting page in core
|
||||
*/
|
||||
function migration_form_controls() {
|
||||
$this->template( 'migrate' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get translated strings for javascript and other functions
|
||||
*
|
||||
* @return array Array of translations
|
||||
*/
|
||||
function get_strings() {
|
||||
$strings = array(
|
||||
'removing_all_files_pull' => __( 'Removing all local files before download of remote media', 'wp-migrate-db-pro-media-files' ),
|
||||
'removing_all_files_push' => __( 'Removing all remote files before upload of local media', 'wp-migrate-db-pro-media-files' ),
|
||||
'removing_files_pull' => __( 'Removing local files that are not found on the remote site', 'wp-migrate-db-pro-media-files' ),
|
||||
'removing_files_push' => __( 'Removing remote files that are not found on the local site', 'wp-migrate-db-pro-media-files' ),
|
||||
'determining' => __( 'Determining media to migrate', 'wp-migrate-db-pro-media-files' ),
|
||||
'determining_progress' => __( 'Determining media to migrate - %1$d of %2$d attachments (%3$d%%)', 'wp-migrate-db-pro-media-files' ),
|
||||
'error_determining' => __( 'Error while attempting to determine which attachments to migrate.', 'wp-migrate-db-pro-media-files' ),
|
||||
'migration_failed' => __( 'Migration failed', 'wp-migrate-db-pro-media-files' ),
|
||||
'problem_migrating_media' => __( 'A problem occurred when migrating the media files.', 'wp-migrate-db-pro-media-files' ),
|
||||
'media_attachments' => __( 'Media Attachments', 'wp-migrate-db-pro-media-files' ),
|
||||
'media_files' => __( 'Files', 'wp-migrate-db-pro-media-files' ),
|
||||
'migrate_media_files_pull' => __( 'Downloading files', 'wp-migrate-db-pro-media-files' ),
|
||||
'migrate_media_files_push' => __( 'Uploading files', 'wp-migrate-db-pro-media-files' ),
|
||||
'migrate_media_files_cli_pull' => __( 'Downloading %d of %d files', 'wp-migrate-db-pro-media-files' ),
|
||||
'migrate_media_files_cli_push' => __( 'Uploading %d of %d files', 'wp-migrate-db-pro-media-files' ),
|
||||
'files_uploaded' => __( 'Files Uploaded', 'wp-migrate-db-pro-media-files' ),
|
||||
'files_downloaded' => __( 'Files Downloaded', 'wp-migrate-db-pro-media-files' ),
|
||||
'file_too_large' => __( 'The following file is too large to migrate:', 'wp-migrate-db-pro-media-files' ),
|
||||
'please_select_a_subsite' => __( 'Please select at least one subsite to transfer media files for.', 'wp-migrate-db-pro-media-files' ),
|
||||
);
|
||||
|
||||
if ( is_null( $this->media_strings ) ) {
|
||||
$this->media_strings = $strings;
|
||||
}
|
||||
|
||||
return $this->media_strings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a specific translated string
|
||||
*
|
||||
* @param string $key Array key
|
||||
*
|
||||
* @return string Translation
|
||||
*/
|
||||
function get_string( $key ) {
|
||||
$strings = $this->get_strings();
|
||||
|
||||
return ( isset( $strings[ $key ] ) ) ? $strings[ $key ] : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Load media related assets in core plugin
|
||||
*/
|
||||
function load_assets() {
|
||||
$plugins_url = trailingslashit( plugins_url( $this->plugin_folder_name ) );
|
||||
$version = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? time() : $this->plugin_version;
|
||||
$ver_string = '-' . str_replace( '.', '', $this->plugin_version );
|
||||
$min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
|
||||
|
||||
$src = $plugins_url . 'asset/dist/css/styles.css';
|
||||
wp_enqueue_style( 'wp-migrate-db-pro-media-files-styles', $src, array( 'wp-migrate-db-pro-styles' ), $version );
|
||||
|
||||
$src = $plugins_url . "asset/dist/js/script{$ver_string}{$min}.js";
|
||||
wp_enqueue_script( 'wp-migrate-db-pro-media-files-script', $src, array(
|
||||
'jquery',
|
||||
'wp-migrate-db-pro-common',
|
||||
'wp-migrate-db-pro-hook',
|
||||
'wp-migrate-db-pro-script',
|
||||
), $version, true );
|
||||
|
||||
wp_localize_script( 'wp-migrate-db-pro-media-files-script', 'wpmdbmf_strings', $this->get_strings() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the remote site has the media addon setup
|
||||
*
|
||||
* @param array $data Connection data
|
||||
*
|
||||
* @return array Updated connection data
|
||||
*/
|
||||
function establish_remote_connection_data( $data ) {
|
||||
$data['media_files_available'] = '1';
|
||||
$data['media_files_version'] = $this->plugin_version;
|
||||
if ( function_exists( 'ini_get' ) ) {
|
||||
$max_file_uploads = ini_get( 'max_file_uploads' );
|
||||
}
|
||||
$max_file_uploads = ( empty( $max_file_uploads ) ) ? 20 : $max_file_uploads;
|
||||
$data['media_files_max_file_uploads'] = apply_filters( 'wpmdbmf_max_file_uploads', $max_file_uploads );
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add media related javascript variables to the page
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function js_variables( $data ) {
|
||||
$data['media_files_version'] = $this->plugin_version;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds extra information to the core plugin's diagnostic info
|
||||
*/
|
||||
function diagnostic_info() {
|
||||
// store the count of local attachments in a transient
|
||||
// so not to impact performance with sites with large media libraries
|
||||
if ( false === ( $attachment_count = get_transient( 'wpmdb_local_attachment_count' ) ) ) {
|
||||
$attachment_count = $this->media_files_local->get_local_attachments_count();
|
||||
set_transient( 'wpmdb_local_attachment_count', $attachment_count, 2 * HOUR_IN_SECONDS );
|
||||
}
|
||||
|
||||
echo 'Media Files: ';
|
||||
echo number_format( $attachment_count );
|
||||
echo "\r\n";
|
||||
|
||||
echo 'Number of Image Sizes: ';
|
||||
$sizes = count( get_intermediate_image_sizes() );
|
||||
echo number_format( $sizes );
|
||||
echo "\r\n";
|
||||
echo "\r\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Media addon nonces for core javascript variables
|
||||
*
|
||||
* @param array $nonces Array of nonces
|
||||
*
|
||||
* @return array Updated array of nonces
|
||||
*/
|
||||
function add_nonces( $nonces ) {
|
||||
$nonces['migrate_media'] = wp_create_nonce( 'migrate-media' );
|
||||
$nonces['remove_files_recursive'] = wp_create_nonce( 'remove-files-recursive' );
|
||||
$nonces['prepare_determine_media'] = wp_create_nonce( 'prepare-determine-media' );
|
||||
$nonces['determine_media_to_migrate_recursive'] = wp_create_nonce( 'determine-media-to-migrate-recursive' );
|
||||
|
||||
return $nonces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for "wpmdbmf_after_migration_options" action to append subsite select UI.
|
||||
*/
|
||||
public function after_migration_options_template() {
|
||||
if ( is_multisite() ) {
|
||||
$this->template( 'select-subsites' );
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user