diff --git a/asset/css/styles.css b/asset/css/styles.css new file mode 100644 index 0000000..c63e0b6 --- /dev/null +++ b/asset/css/styles.css @@ -0,0 +1,3 @@ +.sub-option { + margin: 5px 0 0 25px; +} \ No newline at end of file diff --git a/asset/js/script.js b/asset/js/script.js index 9c28af4..775ab08 100644 --- a/asset/js/script.js +++ b/asset/js/script.js @@ -66,12 +66,7 @@ var media_successfully_determined; $.wpmdb.add_action( 'move_connection_info_box', function() { hide_show_options( remote_media_files_unavailable ); - $('.remove-scope-1').html('remote'); - $('.remove-scope-2').html('local'); - if( migration_type() == 'pull' ){ - $('.remove-scope-1').html('local'); - $('.remove-scope-2').html('remote'); - } + action_text_toggle(); }); $.wpmdb.add_action( 'verify_connection_to_remote_site', function( connection_data ) { @@ -88,12 +83,21 @@ var media_successfully_determined; determine_media_to_migrate = function() { connection_info = $.trim( $('.pull-push-connection-info').val() ).split("\n"); - $('.progress-text').html( wpmdbmf_strings.determining ); var remove_local_media = 0; + var copy_entire_media = 0; + + var media_type = $('input[name="media_migration_option"]:checked').val(); + + if ( 'compare' == media_type ) { + $('.progress-text').html( wpmdbmf_strings.determining ); - if( $('#remove-local-media').is(':checked') ) { - remove_local_media = 1; + if( $('#remove-local-media').is(':checked') ) { + remove_local_media = 1; + } + } else { + $('.progress-text').html( wpmdbmf_strings.migrating_media_files ); + copy_entire_media = 1; } $.ajax({ @@ -104,6 +108,7 @@ var media_successfully_determined; data: { action: 'wpmdbmf_determine_media_to_migrate', remove_local_media: remove_local_media, + copy_entire_media: copy_entire_media, intent: migration_type(), url: connection_info[0], key: connection_info[1], @@ -112,7 +117,7 @@ var media_successfully_determined; }, error: function(jqXHR, textStatus, errorThrown){ $('.progress-title').html( wpmdbmf_strings.migration_failed ); - $('.progress-text').html( wpmdbmf_strings.error_determining + ' (#101mf)' ); + $('.progress-text').html( wpmdbGetAjaxErrors( wpmdbmf_strings.error_determining, '(#101mf)', jqXHR.responseText, jqXHR ) ); $('.progress-text').addClass('migration-error'); console.log( jqXHR ); console.log( textStatus ); @@ -139,7 +144,7 @@ var media_successfully_determined; function migration_failed( data ) { $('.progress-title').html( wpmdbmf_strings.migration_failed ); - $('.progress-text').html(data); + $('.progress-text').html( wpmdbGetAjaxErrors( '', '', data ) ); $('.progress-text').addClass('migration-error'); migration_error = true; migration_complete_events(); @@ -225,7 +230,7 @@ var media_successfully_determined; }, error: function(jqXHR, textStatus, errorThrown){ $('.progress-title').html('Migration failed'); - $('.progress-text').html( wpmdbmf_strings.problem_migrating_media + ' (#102mf)'); + $('.progress-text').html( wpmdbGetAjaxErrors( wpmdbmf_strings.problem_migrating_media, '(#102mf)', jqXHR.responseText, jqXHR ) ); $('.progress-text').addClass('migration-error'); console.log( jqXHR ); console.log( textStatus ); @@ -271,6 +276,20 @@ var media_successfully_determined; return $('input[name=action]:checked').val(); } + function action_text_toggle() { + $('.action-text').hide(); + $('.action-text.' + migration_type() ).show(); + } + + $('input[name="media_migration_option"]').change(function () { + if ($(this).is(':checked') && $(this).val() == 'entire') { + $('#remove-local-media').prop("disabled", true); + $('#remove-local-media').prop("checked", false); + } else { + $('#remove-local-media').prop("disabled", false); + } + }); + }); })(jQuery); \ No newline at end of file diff --git a/class/wpmdbpro-media-files.php b/class/wpmdbpro-media-files.php index 46690c0..8214a7f 100644 --- a/class/wpmdbpro-media-files.php +++ b/class/wpmdbpro-media-files.php @@ -9,11 +9,12 @@ function __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.4' ) ) return; + if( ! $this->meets_version_requirements( '1.4.4' ) ) return; add_action( 'wpmdb_after_advanced_options', array( $this, 'migration_form_controls' ) ); add_action( 'wpmdb_load_assets', array( $this, 'load_assets' ) ); add_action( 'wpmdb_js_variables', array( $this, 'js_variables' ) ); + add_action( 'wpmdb_diagnostic_info', array( $this, 'diagnostic_info' ) ); add_filter( 'wpmdb_accepted_profile_fields', array( $this, 'accepted_profile_fields' ) ); add_filter( 'wpmdb_establish_remote_connection_data', array( $this, 'establish_remote_connection_data' ) ); add_filter( 'wpmdb_nonces', array( $this, 'add_nonces' ) ); @@ -34,18 +35,19 @@ function __construct( $plugin_file_path ) { function get_local_attachments() { global $wpdb; $prefix = $wpdb->prefix; - $temp_prefix = stripslashes( $_POST['temp_prefix'] ); + $temp_prefix = isset( $_POST['temp_prefix'] ) ? stripslashes( $_POST['temp_prefix'] ) : ''; + $intent = isset( $_POST['intent'] ) ? $_POST['intent'] : ''; /* * We determine which media files need migrating BEFORE the database migration is finalized. - * Because of this we need to scan the *_post & *_postmeta that are prefixed using the temporary prefix. + * Because of this we need to scan the *_post & *_postmeta that are prefixed using the temporary prefix. * Though this should only happen when we're responding to a get_remote_media_listing() call AND it's a push OR * we're scanning local files AND it's a pull. */ - if( - ( true == $this->responding_to_get_remote_media_listing && $_POST['intent'] == 'push' ) || - ( false == $this->responding_to_get_remote_media_listing && $_POST['intent'] == 'pull' ) + if( + ( true == $this->responding_to_get_remote_media_listing && 'push' == $intent ) || + ( false == $this->responding_to_get_remote_media_listing && 'pull' == $intent ) ) { $local_tables = array_flip( $this->get_tables() ); @@ -69,8 +71,9 @@ function get_local_attachments() { if( is_multisite() ) { $blogs = $this->get_blogs(); - $prefix = $wpdb->prefix; + $table_prefix = $wpdb->prefix; foreach( $blogs as $blog ) { + $prefix = $table_prefix; $posts_table_name = "{$temp_prefix}{$prefix}{$blog}_posts"; $postmeta_table_name = "{$temp_prefix}{$prefix}{$blog}_postmeta"; if( isset( $local_tables[$posts_table_name] ) && isset( $local_tables[$postmeta_table_name] ) ) { @@ -94,6 +97,49 @@ function get_local_attachments() { return $local_attachments; } + /** + * Return total number of local attachments + * + * @return int + */ + function get_local_attachments_count() { + global $wpdb; + $prefix = $wpdb->prefix; + $count = 0; + + $count += $this->get_attachments_count( $prefix ); + + if ( is_multisite() ) { + $blogs = $this->get_blogs(); + foreach ( $blogs as $blog ) { + $blog_prefix = $prefix . $blog . '_'; + $count += $this->get_attachments_count( $blog_prefix ); + } + } + + return $count; + } + + /** + * Retrieve the count of attachments + * + * @param $prefix + * + * @return null|string + */ + function get_attachments_count( $prefix ) { + global $wpdb; + $count = $wpdb->get_var( + "SELECT COUNT(*) + 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'" + ); + + return $count; + } + function get_flat_attachments( $attachments ) { $flat_attachments = array(); foreach( $attachments as $attachment ) { @@ -131,7 +177,7 @@ function process_attachment_data( $attachment ) { function uploads_dir() { if( defined( 'UPLOADBLOGSDIR' ) ) { $upload_dir = trailingslashit( ABSPATH ) . UPLOADBLOGSDIR; - } + } else { $upload_dir = wp_upload_dir(); $upload_dir = $upload_dir['basedir']; @@ -147,7 +193,7 @@ function get_local_media() { $local_media = array(); foreach( $files as $name => $object ){ - $name = str_replace( array( $upload_dir . DS, '\\' ), array( '', '/' ), $name ); + $name = str_replace( array( $upload_dir . DIRECTORY_SEPARATOR, '\\' ), array( '', '/' ), $name ); $local_media[$name] = $object->getSize(); } @@ -181,7 +227,7 @@ function process_pull_request() { $errors = array(); foreach( $files_to_download as $file_to_download ) { $temp_file_path = $this->download_url( $remote_uploads_url . $file_to_download ); - + if( is_wp_error( $temp_file_path ) ) { $download_error = $temp_file_path->get_error_message(); $errors[] = __( sprintf( 'Could not download file: %1$s - %2$s', $remote_uploads_url . $file_to_download, $download_error ), 'wp-migrate-db-pro-media-files' ); @@ -217,6 +263,8 @@ function process_pull_request() { 'wpmdb_error' => 1, 'body' => implode( '
', $errors ) . '
' ); + $error_msg = 'Failed attempting to process pull request (#112mf)'; + $this->log_error( $error_msg, $errors ); $result = $this->end_ajax( json_encode( $return ) ); return $result; } @@ -261,8 +309,9 @@ function respond_to_push_request() { if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { $return = array( 'wpmdb_error' => 1, - 'body' => $this->invalid_content_verification_error . ' (#101mf)', + 'body' => $this->invalid_content_verification_error . ' (#111mf)', ); + $this->log_error( $return['body'], $filtered_post ); $result = $this->end_ajax( serialize( $return ) ); return $result; } @@ -272,6 +321,7 @@ function respond_to_push_request() { '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; } @@ -304,6 +354,8 @@ function respond_to_push_request() { 'wpmdb_error' => 1, 'body' => implode( '
', $errors ) . '
' ); + $error_msg = 'Failed attempting to respond to push request (#113mf)'; + $this->log_error( $error_msg, $errors ); } $result = $this->end_ajax( serialize( $return ) ); return $result; @@ -332,11 +384,18 @@ function ajax_determine_media_to_migrate() { $this->files_to_migrate = array(); - if( $_POST['intent'] == 'pull' ) { - $this->media_diff( $local_attachments, $remote_attachments, $local_media, $remote_media ); - } - else { - $this->media_diff( $remote_attachments, $local_attachments, $remote_media, $local_media ); + if ( $_POST['copy_entire_media'] == '1' ) { + if ( $_POST['intent'] == 'pull' ) { + $this->add_all_files_to_migrate( $remote_attachments, $remote_media ); + } else { + $this->add_all_files_to_migrate( $local_attachments, $local_media ); + } + } else { + if ( $_POST['intent'] == 'pull' ) { + $this->media_diff( $local_attachments, $remote_attachments, $local_media, $remote_media ); + } else { + $this->media_diff( $remote_attachments, $local_attachments, $remote_media, $local_media ); + } } $return['files_to_migrate'] = $this->files_to_migrate; @@ -344,7 +403,13 @@ function ajax_determine_media_to_migrate() { $return['remote_uploads_url'] = $response['remote_uploads_url']; // remove local/remote media if it doesn't exist on the local/remote site - if( $_POST['remove_local_media'] == '1' ) { + if( $_POST['remove_local_media'] == '1' || $_POST['copy_entire_media'] == '1' ) { + + // if copy entire media then empty comparison arrays so all 'local' media will be removed + if ( $_POST['copy_entire_media'] == '1' ) { + $local_attachments = $remote_attachments = array(); + } + if( $_POST['intent'] == 'pull' ) { $this->remove_local_attachments( $remote_attachments ); } @@ -371,6 +436,7 @@ function respond_to_remove_local_attachments() { '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; } @@ -381,6 +447,7 @@ function respond_to_remove_local_attachments() { 'wpmdb_error' => 1, 'body' => __( 'Error attempting to unserialize the remote attachment data', 'wp-migrate-db-pro-media-files' ) . ' (#110mf)', ); + $this->log_error( $return['body'], $filtered_post['remote_attachments'] ); $result = $this->end_ajax( serialize( $return ) ); return $result; } @@ -388,9 +455,10 @@ function respond_to_remove_local_attachments() { $this->remove_local_attachments( $remote_attachments ); $return = array( - 'success' => 1, + 'success' => 1, ); - $result = $this->serialize( json_encode( $return ) ); + $result = $this->end_ajax( serialize( $return ) ); + return $result; } @@ -409,7 +477,7 @@ function remove_local_attachments( $remote_attachments ) { if( false === isset( $allowed_mime_types[$filetype['type']] ) ) continue; // don't remove files that exist on the remote site if( true === isset( $flat_remote_attachments[$local_media_file] ) ) continue; - + @unlink( $upload_dir . $local_media_file ); } } @@ -446,6 +514,12 @@ function add_files_to_migrate( $attachment, $remote_media ) { } } + function add_all_files_to_migrate( $attachments, $media ) { + foreach( $attachments as $attachment ) { + $this->add_files_to_migrate( $attachment, $media ); + } + } + function maybe_add_resized_images( $attachment, $site_b_media, $site_a_media ) { if( empty( $attachment['sizes'] ) || apply_filters( 'wpmdb_exclude_resized_media', false ) ) return; foreach( $attachment['sizes'] as $size ) { @@ -462,6 +536,7 @@ function respond_to_get_remote_media_listing() { '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; } @@ -491,15 +566,18 @@ function migration_form_controls() { function accepted_profile_fields( $profile_fields ) { $profile_fields[] = 'media_files'; $profile_fields[] = 'remove_local_media'; + $profile_fields[] = 'media_migration_option'; return $profile_fields; } function load_assets() { $plugins_url = trailingslashit( plugins_url() ) . trailingslashit( $this->plugin_folder_name ); - $src = $plugins_url . 'asset/js/script.js'; $version = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? time() : $this->plugin_version; + $src = $plugins_url . 'asset/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/js/script.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', array( 'determining' => __( "Determining which media files to migrate, please wait...", 'wp-migrate-db-pro-media-files' ), 'error_determining' => __( "Error while attempting to determine which media files to migrate.", 'wp-migrate-db-pro-media-files' ), @@ -535,7 +613,7 @@ function multidimensional_search( $needle, $haystack ) { return false; } - function get_blogs() { + function get_blogs() { global $wpdb; $blogs = $wpdb->get_results( @@ -567,7 +645,7 @@ function download_url( $url, $timeout = 300 ) { } $sslverify = ( 1 == $this->settings['verify_ssl'] ) ? true : false; - $args = array( + $args = array( 'timeout' => $timeout, 'stream' => true, 'filename' => $tmpfname, @@ -596,15 +674,41 @@ function js_variables() { 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"; + } + 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; } @@ -612,6 +716,7 @@ function verify_remote_post_response( $response ) { $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; } @@ -637,13 +742,15 @@ function cli_migration( $outcome, $profile, $verify_connection_response, $initia $this->set_time_limit(); $wpmdbpro->set_cli_migration(); $this->set_cli_migration(); - + $connection_info = explode( "\n", $profile['connection_info'] ); $_POST['intent'] = $profile['action']; $_POST['url'] = trim( $connection_info[0] ); $_POST['key'] = trim( $connection_info[1] ); $_POST['remove_local_media'] = ( isset( $profile['remove_local_media'] ) ) ? 1 : 0; + $media_type = ( isset( $profile['media_migration_option'] ) ) ? $profile['media_migration_option'] : 'compare'; + $_POST['copy_entire_media'] = ( 'compare' == $media_type ) ? 0 : 1; $_POST['temp_prefix'] = $verify_connection_response['temp_prefix']; do_action( 'wpmdb_cli_before_determine_media_to_migrate', $profile, $verify_connection_response, $initiate_migration_response ); diff --git a/template/migrate.php b/template/migrate.php index 171ee51..59690e8 100644 --- a/template/migrate.php +++ b/template/migrate.php @@ -7,12 +7,39 @@
- + diff --git a/version.php b/version.php index cc5b6a1..2f99892 100644 --- a/version.php +++ b/version.php @@ -1,2 +1,2 @@