From a6eacc76cf7690b95135da74c5681a396937b3eb Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Sun, 29 Dec 2013 03:17:37 -0600 Subject: [PATCH 01/52] major update --- asset/config.rb | 3 +- asset/css/styles.css | 945 ++++++++++++++++--- asset/js/plugin-update.js | 65 ++ asset/js/script.js | 1535 ++++++++++++++++++++++++++++-- asset/sass/styles.scss | 1101 +++++++++++++++++++--- class/wp-migrate-db.php | 1650 +++++++++++++++++++++++++++++++++ template/help.php | 62 ++ template/migrate-progress.php | 17 + template/migrate.php | 312 +++++++ template/profile.php | 9 + template/settings.php | 45 + wp-migrate-db-pro.php | 50 + wp-migrate-db.php | 810 ---------------- 13 files changed, 5472 insertions(+), 1132 deletions(-) create mode 100644 asset/js/plugin-update.js create mode 100644 class/wp-migrate-db.php create mode 100644 template/help.php create mode 100644 template/migrate-progress.php create mode 100644 template/migrate.php create mode 100644 template/profile.php create mode 100644 template/settings.php create mode 100644 wp-migrate-db-pro.php delete mode 100644 wp-migrate-db.php diff --git a/asset/config.rb b/asset/config.rb index f89f6ca..b582f88 100644 --- a/asset/config.rb +++ b/asset/config.rb @@ -9,12 +9,13 @@ # You can select your preferred output style here (can be overridden via the command line): # output_style = :expanded or :nested or :compact or :compressed +output_style = :expanded # To enable relative paths to assets via compass helper functions. Uncomment: # relative_assets = true # To disable debugging comments that display the original location of your selectors. Uncomment: -# line_comments = false +line_comments = false # If you prefer the indented syntax, you might want to regenerate this diff --git a/asset/css/styles.css b/asset/css/styles.css index 4fcc717..4301494 100644 --- a/asset/css/styles.css +++ b/asset/css/styles.css @@ -1,184 +1,861 @@ -/* line 1, ../sass/styles.scss */ -#migrate-form { - padding-top: 10px; +.wpmdb { + /* ============================================================================= + Common & Global + ========================================================================== */ + /* ============================================================================= + Migrate Tab + ========================================================================== */ + /* Misc */ + /* Tabs */ + /* Saved migration profile selection */ + /* Output Selection */ + /* Find and Replace */ + /* Select Tables */ + /* Advanced Options */ + /* Save migration profile */ + /* Action buttons */ + /* Import DB */ + /* ============================================================================= + Settings Tab + ========================================================================== */ + /* ============================================================================= + Settings Tab + ========================================================================== */ +} +.wpmdb a { + text-decoration: none; } - -/* line 9, ../sass/styles.scss */ -.form-table .row-new-url th, .form-table .row-new-url td, -.form-table .row-new-path th, -.form-table .row-new-path td, -.form-table .row-revisions th, -.form-table .row-revisions td { - padding-bottom: 20px; +.wpmdb li { + margin-bottom: 5px; + position: relative; +} +.wpmdb ul { + margin: 0; +} +.wpmdb input[type=checkbox], +.wpmdb input[type=radio] { + margin-right: 5px; + vertical-align: baseline; + margin-top: 0; +} +.wpmdb input[type=text] { + padding: 5px; +} +.wpmdb .option-section { border-bottom: 1px solid #ccc; + padding-bottom: 20px; + margin-bottom: 20px; } -/* line 18, ../sass/styles.scss */ -.form-table .row-old-path th, .form-table .row-old-path td, -.form-table .row-save-file th, -.form-table .row-save-file td, -.form-table .row-guids th, -.form-table .row-guids td { - padding-top: 20px; +.wpmdb .option-section h3 { + font-size: 18px; + font-weight: normal; } - -/* line 24, ../sass/styles.scss */ -p.submit { +.wpmdb p.migrate-db { overflow: hidden; - padding-top: 20px; - border-top: 1px solid #ccc; - margin-top: 20px; } -/* line 30, ../sass/styles.scss */ -p.submit input { +.wpmdb p.migrate-db input { float: left; } -/* line 34, ../sass/styles.scss */ -p.submit img { +.wpmdb p.migrate-db img { float: left; margin: 3px 0 0 5px; } - -/* line 40, ../sass/styles.scss */ -#wpmdb-container { - position: relative; +.wpmdb p.migrate-db .save-settings-button { + margin-left: 10px; + display: none; } - -/* line 44, ../sass/styles.scss */ -#wpmdb-main { - margin-right: 320px; - min-height: 1200px; +.wpmdb .indent-wrap { + margin-left: 25px; } - -/* line 49, ../sass/styles.scss */ -#wpmdb-sidebar { - position: absolute; - top: 0; - right: 0; - width: 250px; - border: 1px solid #ccc; - padding: 20px; +.wpmdb .expandable-content { + display: none; + margin-top: 10px; } -/* line 57, ../sass/styles.scss */ -#wpmdb-sidebar .author { - padding-bottom: 20px; - margin-bottom: 20px; - border-bottom: 1px solid #ccc; - overflow: hidden; +.wpmdb .expandable-content li:last-child { + margin-bottom: 0px; } -/* line 63, ../sass/styles.scss */ -#wpmdb-sidebar .author img { - float: left; - margin-right: 20px; +.wpmdb .header-wrapper { + margin-bottom: 10px; } -/* line 68, ../sass/styles.scss */ -#wpmdb-sidebar .author .desc { - float: left; +.wpmdb .header-expand-collapse { + cursor: pointer; + display: inline-block; } -/* line 72, ../sass/styles.scss */ -#wpmdb-sidebar .author h3 { +.wpmdb .option-description { font-size: 12px; - margin: 0; + color: #999; + margin-left: 8px; + font-weight: normal; } -/* line 77, ../sass/styles.scss */ -#wpmdb-sidebar .author h2 { - font-size: 18px; - margin: 0; - padding: 0; +.wpmdb .option-group li:last-child { + margin-bottom: 0; } -/* line 82, ../sass/styles.scss */ -#wpmdb-sidebar .author h2 a { - color: #464646; - text-decoration: none; +.wpmdb .connection-status { + display: none; +} +.wpmdb .connection-status.error { + color: #9D1818; +} +.wpmdb .ajax-spinner { + left: 6px; + position: relative; + top: 3px; +} +.wpmdb div.message { + margin: 15px 0 0; +} +.wpmdb .licence-wrap h3 { + margin: 0 0 10px 0; +} +.wpmdb .licence-input { + clear: both; + display: block; + font-family: "Courier New",Courier,monospace; + font-size: 14px; + margin-bottom: 7px; + padding: 10px; + width: 418px; } -/* line 86, ../sass/styles.scss */ -#wpmdb-sidebar .author h2 a:hover { - color: #000; +.wpmdb .register-licence { + float: left; } -/* line 92, ../sass/styles.scss */ -#wpmdb-sidebar .author p { +.wpmdb .licence-status { + color: #A21B1B; + font-weight: bold; + clear: both; + padding-top: 0.5em; margin: 0; } -/* line 97, ../sass/styles.scss */ -#wpmdb-sidebar .subscribe { - padding-bottom: 20px; +.wpmdb .licence-status.success { + color: #333; +} +.wpmdb .licence-information { + margin-bottom: 5px; +} +.wpmdb .register-licence-ajax-spinner { + margin: 4px 0 0 8px; +} +.wpmdb .return-to-profile-selection { + margin-bottom: 15px; + display: inline-block; +} +.wpmdb .return-to-profile-selection.bottom { + margin-top: 10px; +} +.wpmdb h2.nav-tab-wrapper { + margin-top: 10px; margin-bottom: 20px; - border-bottom: 1px solid #ccc; + padding-left: 10px; } -/* line 102, ../sass/styles.scss */ -#wpmdb-sidebar .subscribe h2 { - padding: 0; - margin: 0; - margin-bottom: 0.5em; - color: #666; - font-size: 20px; +.wpmdb h2.nav-tab-wrapper a { + margin-right: 4px; } -/* line 110, ../sass/styles.scss */ -#wpmdb-sidebar .subscribe ul { - list-style-type: disc; +.wpmdb h2.nav-tab-wrapper a.nav-tab-active { + color: #464646; + cursor: default; } -/* line 114, ../sass/styles.scss */ -#wpmdb-sidebar .subscribe li { - margin-left: 1.5em; - color: #666; +.wpmdb label { + display: inline-block; + clear: both; } -/* line 119, ../sass/styles.scss */ -#wpmdb-sidebar .subscribe p { - margin: 0; +.wpmdb .saved-migration-profile-label { + font-weight: bold; + font-size: 14px; +} +.wpmdb .migration-profile-options li { + position: relative; + width: 520px; +} +.wpmdb .migration-profile-options li a { + padding: 5px 10px; + width: 500px; + border: 1px solid #ddd; + margin: 0px 0px 7px; + display: block; + font-size: 14px; + color: #333; +} +.wpmdb .migration-profile-options li a:hover { + border-color: #bbb; +} +.wpmdb .main-list-delete-profile-link { + color: #999999; + font-family: "Times New Roman", serif; + font-size: 26px; + font-weight: 200; + position: absolute; + right: 7px; + top: 6px; + cursor: pointer; +} +.wpmdb .main-list-delete-profile-link:hover { + color: #444; +} +.wpmdb .option-group li { + margin-bottom: 5px; +} +.wpmdb .option-group > li { + margin-bottom: 8px; +} +.wpmdb .option-group li > label { + font-size: 14px; + font-weight: bold; +} +.wpmdb .option-group ul { + display: none; + margin: 10px 0px 10px 25px; +} +.wpmdb .option-group ul label { + font-size: 12px; + font-weight: normal; +} +.wpmdb .import-file label { + margin-right: 1em; } -/* line 123, ../sass/styles.scss */ -#wpmdb-sidebar .subscribe p.interesting { - margin-bottom: 1em; +.wpmdb .import-file .note { + display: block; + color: #999; + font-style: italic; } -/* line 127, ../sass/styles.scss */ -#wpmdb-sidebar .subscribe .error { - color: red; +.wpmdb .option-heading { + font-size: 14px; font-weight: bold; - margin-bottom: 1em; } -/* line 133, ../sass/styles.scss */ -#wpmdb-sidebar .subscribe .thanks { +.wpmdb .expand-collapse-arrow { + margin-right: 9px; +} +.wpmdb .migrate-connection-info { + min-width: 675px; + margin: 0; +} +.wpmdb .migrate-tab .pull-push-connection-info { + width: 418px; + height: 65px; color: #333; + font-family: "Courier New",Courier,monospace; + font-size: 15px; + line-height: 21px; + padding: 10px; +} +.wpmdb .connection-info-wrapper { + display: none; + width: 670px; +} +.wpmdb .connect-button { + margin-top: 2px; +} +.wpmdb .temp-disabled { + background-color: #EEEEEE; + color: #888888; + font-family: "Courier New",Courier,monospace; + text-shadow: 0 1px 0 #FFFFFF; +} +.wpmdb .push-list ul { + margin-bottom: 0px; +} +.wpmdb .find-heading, .wpmdb .replace-heading { + float: left; +} +.wpmdb .find-heading { + width: 400px; +} +.wpmdb .replace-fields { + border-collapse: collapse; + border-spacing: 0px; +} +.wpmdb .replace-fields input { + width: 295px; +} +.wpmdb .replace-fields tr td { + padding-bottom: 7px; +} +.wpmdb .replace-fields tr:last-child td { + padding-bottom: 0px; +} +.wpmdb .arrow-col { + width: 93px; + text-align: center; + vertical-align: middle; +} +.wpmdb .right-arrow { + font-size: 36px; + color: #aaa; + font-family: arial, sans-serif; +} +.wpmdb .replace-right-col span { + border-radius: 50%; + border: 1px solid #ccc; + background-color: #eee; + width: 16px; + height: 16px; + display: inline-block; + position: relative; + top: 4px; + cursor: pointer; +} +.wpmdb .replace-right-col span:hover { + border-color: #aaa; +} +.wpmdb .replace-remove-row { + margin: 0px 2px; +} +.wpmdb .replace-remove-row:after { + content: ''; + background-color: #aaa; + display: block; + height: 2px; + left: 5px; + position: absolute; + top: 7px; + width: 6px; +} +.wpmdb .replace-add-row:after { + content: ''; + background-color: #aaa; + display: block; + height: 2px; + left: 5px; + position: absolute; + top: 7px; + width: 6px; +} +.wpmdb .replace-add-row:before { + content: ''; + background-color: #aaa; + display: block; + height: 6px; + left: 7px; + position: absolute; + top: 5px; + width: 2px; +} +.wpmdb .original-repeatable-field { + display: none; +} +.wpmdb .no-replaces-message { + display: none; + margin-bottom: 0px; +} +.wpmdb .tables-header { + display: inline-block; +} +.wpmdb .expand-collapse-arrow { + display: inline-block; + position: relative; + top: -2px; + font-size: 11px; +} +.wpmdb .collapsed { + -moz-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); + -webkit-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); + -o-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); + -ms-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); + transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); +} +.wpmdb .select-deselect-divider { + margin: 0 6px; +} +.wpmdb .select-tables-wrap { + display: none; + margin-top: 12px; +} +.wpmdb #select-tables { + min-width: 420px; + min-height: 180px; + margin-bottom: 10px; +} +.wpmdb .table-migrate-options li label { + font-size: 12px; + font-weight: normal; +} +.wpmdb .table-migrate-options li { + margin-bottom: 5px; +} +.wpmdb .replace-guid-helper { + border-radius: 50%; + border: 1px solid #ccc; + background-color: #eee; + width: 15px; + height: 15px; + display: inline-block; + position: relative; + top: 4px; + cursor: pointer; + margin-left: 2px; +} +.wpmdb .replace-guid-helper:hover { + border-color: #aaa; +} +.wpmdb .replace-guid-helper:after { + content: "?"; + color: #999999; + font-size: 10px; font-weight: bold; + left: 4px; + position: absolute; + top: -1px; +} +.wpmdb .replace-guids-info { + padding: 10px; + border: 1px solid #ccc; + border-radius: 3px; + background-color: #fff; + position: absolute; + width: 500px; + left: 140px; + z-index: 100; + top: -7px; + display: none; + box-shadow: 0px 0px 5px #ccc; +} +.wpmdb .replace-guids-info:after { + content: ''; + border-bottom: 7px solid transparent; + border-right: 7px solid #fff; + border-top: 7px solid transparent; + display: block; + height: 0; + left: -7px; + position: absolute; + top: 11px; + width: 0; +} +.wpmdb .replace-guids-info:before { + content: ''; + border-bottom: 7px solid transparent; + border-right: 7px solid #aaa; + border-top: 7px solid transparent; + display: block; + height: 0; + left: -8px; + position: absolute; + top: 11px; + width: 0; +} +.wpmdb .label-disabled { + color: #888; +} +.wpmdb .save-migration-profile { font-size: 14px; + font-weight: bold; +} +.wpmdb .save-migration-profile-wrap li label { + font-size: 12px; + font-weight: normal; +} +.wpmdb .save-migration-profile-wrap li { + margin-bottom: 5px; + padding-left: 25px; +} +.wpmdb .save-migration-profile-wrap .indent-wrap { + margin-left: 0px; +} +.wpmdb .create-new-label { + margin-right: 8px; } -/* line 139, ../sass/styles.scss */ -#wpmdb-sidebar .subscribe .field { - margin-bottom: 1em; +.wpmdb .create-new-profile { + position: absolute; + top: -5px; +} +.wpmdb .delete-profile { + background-color: #eee; + border: 1px solid #ccc; + border-radius: 50% 50% 50% 50%; + cursor: pointer; + height: 11px; + left: 5px; + margin-left: 2px; + position: absolute; + margin-top: -6px; + top: 50%; + width: 11px; + display: none; + background-position: 50% 50%; + background-size: 6px 6px; + background-repeat: no-repeat; +} +.wpmdb .delete-profile:after { + content: "\00d7"; + left: 2px; + position: absolute; + top: -3px; + color: #aaa; + font-size: 12px; } -/* line 142, ../sass/styles.scss */ -#wpmdb-sidebar .subscribe .field p { - margin-bottom: 0.3em; +.wpmdb .delete-profile:hover { + border-color: #aaa; } -/* line 146, ../sass/styles.scss */ -#wpmdb-sidebar .subscribe .field .willing-copy { +.wpmdb .migrate-db .ajax-success-msg { font-weight: bold; + margin: 3px 0 0 9px; + display: inline-block; +} +.wpmdb p img.save-profile-ajax-spinner { + margin-left: 10px; +} +.wpmdb .import-button { + display: none; +} +.wpmdb .settings-tab { + display: none; +} +.wpmdb .settings-tab .option-section li label { + font-size: 12px; + font-weight: normal; + position: relative; +} +.wpmdb .settings-tab .option-section li { + margin-bottom: 5px; +} +.wpmdb .settings-tab .option-section li:last-child { + margin-bottom: 0px; +} +.wpmdb .settings-tab .option-section .ajax-spinner { + right: -23px; + left: inherit; + top: 0px; + position: absolute; +} +.wpmdb .settings-tab .option-section .ajax-success-msg { + right: -42px; + left: inherit; + top: 0px; + position: absolute; + font-weight: bold; +} +.wpmdb .allow-remote-reqeusts { font-size: 14px; - line-height: 1.4em; - margin-bottom: 1em; + font-weight: bold; +} +.wpmdb .connection-info-label { + margin-top: 15px; + margin-bottom: 5px; + display: block; +} +.wpmdb .connection-info { + clear: both; + background-color: #eee; + color: #888; + font-size: 15px; + line-height: 21px; + font-family: "Courier New", Courier, monospace; + padding: 10px 10px; + height: 67px; + text-shadow: 0px 1px 0px #fff; + display: block; + margin-bottom: 7px; + width: 418px; +} +.wpmdb .reset-button-wrap { + width: 418px; +} +.wpmdb .reset-api-key { + float: left; } -/* line 154, ../sass/styles.scss */ -#wpmdb-sidebar .subscribe .field.how-much input { - width: 50px; +.wpmdb .reset-api-key-ajax-spinner { + float: left; + margin: 4px 7px; +} +.wpmdb .help-tab { + display: none; +} +.wpmdb .help-tab h3 { + font-size: 18px; + font-weight: normal; } -/* line 160, ../sass/styles.scss */ -#wpmdb-sidebar .subscribe .field.notify-me input { +.wpmdb .help-tab .support { + border-bottom: 1px solid #ccc; + margin-bottom: 25px; + padding-bottom: 18px; +} +.wpmdb .help-tab .support p { + width: 640px; +} +.wpmdb .help-tab .support .email a { + font-size: 12px; +} +.wpmdb .help-tab .support .ajax-spinner { + top: 2px; +} +.wpmdb .help-tab .video-viewer { + margin-bottom: 30px; +} +.wpmdb .help-tab .videos { + width: 640px; + border-bottom: 1px solid #CCCCCC; + margin-bottom: 25px; + padding-bottom: 28px; +} +.wpmdb .help-tab .videos ul > li { + margin-bottom: 30px; + overflow: hidden; + position: relative; +} +.wpmdb .help-tab .videos ul > li a { + overflow: hidden; + display: block; + width: 320px; + height: 180px; + float: left; + margin-right: 15px; + position: relative; + z-index: 1; +} +.wpmdb .help-tab .videos ul > li a:before, .wpmdb .help-tab .videos ul > li a:after { + position: absolute; + content: " "; + margin: auto; + left: 0; + right: 0; + top: 0; + bottom: 0; +} +.wpmdb .help-tab .videos ul > li a:before { + width: 64px; + height: 64px; + -webkit-border-radius: 64px; + -moz-border-radius: 64px; + -ms-border-radius: 64px; + -o-border-radius: 64px; + border-radius: 64px; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); + opacity: 0.8; + border: 1px solid #ddd; + background-color: #fff; + z-index: 2; +} +.wpmdb .help-tab .videos ul > li a:after { + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); + opacity: 0.8; + border: 21.33333px solid transparent; + border-top-width: 12.8px; + border-bottom-width: 12.8px; + border-left-color: #333; + background: transparent; + display: block; + left: 25px; + width: 0px; + height: 0px; + z-index: 3; +} +.wpmdb .help-tab .videos .video:last-child { + margin-bottom: 0px; +} +.wpmdb .help-tab .videos img { + width: 320px; + height: 240px; + position: relative; + top: 50%; + margin-top: -120px; +} +.wpmdb .help-tab .debug { + width: 640px; +} +.wpmdb .help-tab .debug textarea { + width: 100%; + min-height: 200px; + font-family: "Courier New",Courier,monospace; + margin-bottom: 5px; +} +.wpmdb .help-tab h4 { + margin: 0 0 0.2em 0; +} +.wpmdb .help-tab p { + margin: 0 0 0.5em 0; +} +.wpmdb .help-tab iframe { + display: none; +} + +/* Progress Information */ +/* Contain floats: h5bp.com/q */ +.clearfix:before, .clearfix:after { + content: ""; + display: table; +} + +.clearfix:after { + clear: both; +} + +.clearfix { + zoom: 1; +} + +.general-spinner { + width: 16px; + height: 16px; +} + +.migration-error { + color: #A21B1B; + font-weight: bold; +} + +.progress-content { + display: none; + position: relative; + margin: 0 auto; + background-color: #fff; + padding: 50px; + box-shadow: 0 0 10px #ccc; + cursor: default; + width: 80%; + z-index: 99999; + position: fixed; + left: 50%; + margin-left: -40%; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +.progress-content .progress-bar { + height: 10px; + background-color: #8cc1e9; + margin-bottom: 5px; + background-image: -webkit-gradient(linear, 50% 100%, 50% 0%, color-stop(0%, #72a7cf), color-stop(100%, #8cc1e9)); + background-image: -webkit-linear-gradient(bottom, #72a7cf, #8cc1e9); + background-image: -moz-linear-gradient(bottom, #72a7cf, #8cc1e9); + background-image: -o-linear-gradient(bottom, #72a7cf, #8cc1e9); + background-image: linear-gradient(bottom, #72a7cf, #8cc1e9); +} +.progress-content .progress-title { + font-size: 18px; + font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", sans-serif; + font-weight: normal; + float: left; +} +.progress-content .progress-bar { + width: 0%; +} +.progress-content .progress-info-wrapper { + margin-bottom: 10px; +} +.progress-content .progress-text { + clear: left; + float: left; +} +.progress-content .timer { + float: right; +} +.progress-content .progress-tables { + overflow: hidden; + margin-bottom: 2px; + padding: 0 0 20px 0; +} +.progress-content .progress-bar-wrapper { + position: relative; +} +.progress-content .progress-bar-wrapper:before { + content: ''; + display: block; + height: 5px; + width: 1px; + background-color: #ccc; position: absolute; + top: 15px; + left: 0px; } -/* line 164, ../sass/styles.scss */ -#wpmdb-sidebar .subscribe .field.notify-me label { +.progress-content .progress-tables-hover-boxes { + position: absolute; + top: 0px; + left: 0px; display: block; - padding-left: 20px; + width: 100%; } -/* line 172, ../sass/styles.scss */ -#wpmdb-sidebar .subscribe .field.comments textarea { - width: 230px; - height: 3em; +.progress-content .progress-chunk-hover { + display: block; + float: left; + height: 35px; + position: relative; + top: -5px; + z-index: 1; } -/* line 177, ../sass/styles.scss */ -#wpmdb-sidebar .subscribe .field.comments textarea.has-content, #wpmdb-sidebar .subscribe .field.comments textarea:focus { - height: 5em; +.progress-content .progress-chunk { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + float: left; + display: block; + height: 6px; + border-right: 1px solid #ccc; + border-bottom: 1px solid #ccc; + color: #999; + position: relative; + text-align: center; } -/* line 183, ../sass/styles.scss */ -#wpmdb-sidebar .subscribe .field.submit-button { - margin-bottom: 0; +.progress-content .progress-chunk span { + padding: 0px 3px; + white-space: nowrap; + text-overflow: ellipsis; + margin-top: 10px; + display: inline-block; +} +.progress-content .progress-label { + padding: 5px 10px; + border: 1px solid #ccc; + border-radius: 3px; + background-color: #fff; + colour: #333; + font-family: "Courier New",Courier,monospace; + font-size: 12px; + display: inline-block; + top: -35px; + position: absolute; + opacity: 0; + -webkit-transition: opacity 200ms ease-in-out; + -moz-transition: opacity 200ms ease-in-out; + -ms-transition: opacity 200ms ease-in-out; + -o-transition: opacity 200ms ease-in-out; + transition: opacity 200ms ease-in-out; +} +.progress-content .label-visible { + opacity: 1; +} +.progress-content .progress-label:before { + content: ""; + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #ccc; + display: block; + position: absolute; + bottom: -5px; + left: 50%; + margin-left: -2px; +} +.progress-content .progress-label:after { + content: ""; + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #fff; + display: block; + position: absolute; + bottom: -4px; + left: 50%; + margin-left: -2px; +} +.progress-content .migration-progress-ajax-spinner { + left: 7px; + position: relative; + top: 15px; +} +.progress-content .close-progress-content { + color: #999999; + cursor: pointer; + font-family: "Times New Roman",serif; + font-size: 26px; + font-weight: 200; + position: absolute; + right: 20px; + top: 20px; + padding: 5px; + display: none; +} +.progress-content .close-progress-content:hover { + color: #666; + border-color: #aaa; } diff --git a/asset/js/plugin-update.js b/asset/js/plugin-update.js new file mode 100644 index 0000000..f0e60b8 --- /dev/null +++ b/asset/js/plugin-update.js @@ -0,0 +1,65 @@ +(function($) { + + var doing_check_licence = false; + var fade_duration = 650; + + var admin_url = ajaxurl.replace( '/admin-ajax.php', '' ), spinner_url = admin_url + '/images/wpspin_light'; + if( window.devicePixelRatio >= 2 ){ + spinner_url += '-2x'; + } + spinner_url += '.gif'; + + $(document).ready(function() { + + $('body').delegate('.check-my-licence-again', 'click', function(e){ + e.preventDefault(); + $(this).blur(); + + if( doing_check_licence ) { + return false; + } + + doing_check_licence = true; + + $('.check-my-licence-again').after( '' ); + + var check_again_link = ' Check my license again'; + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'json', + cache: false, + data: { + action : 'wpmdb_check_licence', + }, + error: function(jqXHR, textStatus, errorThrown){ + doing_check_licence = false; + var msg = 'A problem occured when trying to check the license, please try again.'; + $('.wpmdb-licence-error-notice').empty().html( msg + check_again_link ); + $('.wpmdb-licence-error-notice').fadeOut(fade_duration).fadeIn(fade_duration); + }, + success: function(data){ + doing_check_licence = false; + $('.check-licence-spinner').remove(); + if ( typeof data.errors !== 'undefined' ) { + var msg = ''; + for (var key in data.errors) { + msg += data.errors[key]; + } + $('.wpmdb-licence-error-notice').empty().html( msg + check_again_link ); + $('.wpmdb-licence-error-notice').fadeOut(fade_duration).fadeIn(fade_duration); + } + else { + // success + // fade out, empty wpmdb custom error content, swap back in the original wordpress upgrade message, fade in + $('.wpmdbpro-custom-visible').fadeOut(fade_duration).empty().html($('.wpmdb-original-update-row').html()).fadeIn(fade_duration); + } + } + }); + + }); + + }); + +})(jQuery); \ No newline at end of file diff --git a/asset/js/script.js b/asset/js/script.js index 47c6b64..e971e97 100644 --- a/asset/js/script.js +++ b/asset/js/script.js @@ -1,62 +1,1475 @@ (function($) { - $(document).ready(function() { - $('#replace-guids-info-link').click(function() { - var $div = $('#replace-guids-info'); - if ( 'none' == $div.css('display') ) { - $div.show(); - $(this).html('show less'); - return false; - } - else { - $div.hide(); - $(this).html('show more'); - return false; - } - }); - - $('#wpmdb-sidebar').each(function() { - var $sidebar = $(this); - - $('form', $sidebar).submit(function() { - var $form = $(this), - data = $(this).serializeArray(); - - $('.button', $form).attr('disabled', 'true'); - - data.push({name: 'action', value: 'subscribe_submission'}); - - $.post( ajaxurl, data, function(result) { - if (result) { - $('.error', $sidebar).remove(); - $('.field.submit-button', $sidebar).before(''); - $('.error', $sidebar).fadeIn(); - } - else { - $form.html('

Thanks for subscribing. We promise to protect your email from weasels.

').fadeIn(); - document.location.hash = '#top'; - } - }); - return false; - }); - - $('.field.comments textarea', $sidebar).blur(function() { - if ($(this).val()) { - $(this).addClass('has-content'); - } - else { - $(this).removeClass('has-content'); - } - }); - }); - }); - - var admin_url = ajaxurl.replace( '/admin-ajax.php', '' ), - spinner_url = admin_url + '/images/wpspin_light.gif'; - - var spinner = new Image(); - spinner.src = spinner_url; - - $('#migrate-form').submit(function() { - $('p.submit', this).append(''); - }); -})(jQuery); + + var connection_established = false; + var connection_data = ''; + var last_replace_switch = ''; + var doing_ajax = false; + var doing_licence_registration_ajax = false; + var doing_reset_api_key_ajax = false; + var doing_save_profile = false; + var form_data = ''; + var migration_completed = false; + var interval; + var currently_migrating = false; + var profile_name_edited = false; + var checked_licence = false; + + var admin_url = ajaxurl.replace( '/admin-ajax.php', '' ), spinner_url = admin_url + '/images/wpspin_light'; + + if( window.devicePixelRatio >= 2 ){ + spinner_url += '-2x'; + } + + spinner_url += '.gif'; + + window.onbeforeunload = function (e) { + if( currently_migrating ){ + e = e || window.event; + + // For IE and Firefox prior to version 4 + if (e) { + e.returnValue = 'Sure?'; + } + + // For Safari + return 'Sure?'; + } + }; + + function pad(n, width, z) { + z = z || '0'; + n = n + ''; + return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n; + } + + function setup_counter() { + var c = 0, + counter_display = $('.timer'), + label = 'Time Elapsed: '; + function display_count() { + hours = parseInt( c / 3600 ) % 24; + minutes = parseInt( c / 60 ) % 60; + seconds = c % 60; + var display = label + pad(hours,2,0) + ':' + pad(minutes,2,0) + ':' + pad(seconds,2,0); + counter_display.html(display); + } + + function count() { + c = c + 1; + display_count(); + } + + interval = setInterval(count,1000); + } + + function get_intersect(arr1, arr2) { + var r = [], o = {}, l = arr2.length, i, v; + for (i = 0; i < l; i++) { + o[arr2[i]] = true; + } + l = arr1.length; + for (i = 0; i < l; i++) { + v = arr1[i]; + if (v in o) { + r.push(v); + } + } + return r; + } + + function get_domain_name( url ){ + var temp_url = url; + var domain = temp_url.replace('http://','').replace('https://','').replace('www.','').split(/[/?#]/)[0]; + return domain; + } + + function get_default_profile_name( url, intent, ing_suffix ){ + var domain = get_domain_name(url); + var action = intent; + action = action.charAt(0).toUpperCase() + action.slice(1); + if( ing_suffix ){ + action += 'ing'; + } + var preposition = 'to'; + if( intent == 'pull' ){ + preposition = 'from'; + } + + return profile_name = action + ' ' + preposition + ' ' + domain; + } + + $(document).ready(function() { + + var progress_content_original = $('.progress-content').clone(); + $('.progress-content').remove(); + + var this_tables = $.parseJSON(wpmdb_this_tables); + var push_select = $('#select-tables').clone(); + var pull_select = $('#select-tables').clone(); + + $('.help-tab .video').each(function() { + var $container = $(this), + $viewer = $('.video-viewer'); + + $('a', this).click(function() { + $viewer.attr('src', 'http://www.youtube.com/embed/' + $container.data('video-id') + '?autoplay=1'); + $viewer.show(); + var offset = $viewer.offset(); + $(window).scrollTop(offset.top - 50); + return false; + }); + }); + + $('.backup-options').show(); + if( $('#savefile').is(':checked') ){ + $('.backup-options').hide(); + } + + $('.support-content p').append( '' ); + + function check_licence( licence ){ + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'json', + cache: false, + data: { + action : 'wpmdb_check_licence', + licence_key : licence, + }, + error: function(jqXHR, textStatus, errorThrown){ + console.log( 'A problem occured when trying to check the license, please try again.' ); + }, + success: function(data){ + if ( typeof data.errors !== 'undefined' ) { + var msg = ''; + for (var key in data.errors) { + msg += data.errors[key]; + } + $('.support-content').empty().html( msg ); + } + else { + $('.support-content').empty().html(data.message); + } + } + }); + } + + // automatically validate connnection info if we're loading a saved profile + establish_remote_connection_from_saved_profile(); + + function establish_remote_connection_from_saved_profile(){ + var action = $('input[name=action]:checked').val(); + var connection_info = $.trim( $('.pull-push-connection-info').val() ).split("\n"); + if( typeof wpmdb_default_profile == 'undefined' || wpmdb_default_profile == true || action == 'savefile' || doing_ajax ){ + return; + } + + doing_ajax = true; + + $('.connection-status').html( 'Establishing connection to remote server, please wait' ); + $('.connection-status').removeClass( 'migration-error' ); + $('.connection-status').append( '' ); + + var intent = $('input[name=action]:checked').val(); + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'json', + cache: false, + data: { + action: 'wpmdb_prepare_remote_connection', + url: connection_info[0], + key: connection_info[1], + intent: intent, + }, + error: function(jqXHR, textStatus, errorThrown){ + $('.connection-status').html( 'A problem occured when attempting to connect to the remote server, please check the details and try again. (#102)' ); + $('.connection-status').addClass( 'migration-error' ); + $('.ajax-spinner').remove(); + doing_ajax = false; + }, + success: function(data){ + $('.ajax-spinner').remove(); + doing_ajax = false; + + if( typeof data.wpmdb_error != 'undefined' && data.wpmdb_error == 1 ){ + $('.connection-status').html( data.body ); + $('.connection-status').addClass( 'migration-error' ); + return; + } + + var original_body = data; + data = $.parseJSON( data ); + + $('.pull-push-connection-info').addClass('temp-disabled'); + $('.pull-push-connection-info').attr('readonly','readonly'); + $('.connect-button').hide(); + + $('.connection-status').hide(); + $('.step-two').show(); + connection_established = true; + connection_data = data; + + $('.remote-json-data').val(original_body); + + var loaded_tables = ''; + if( wpmdb_default_profile == false && wpmdb_export_with_prefix == false ){ + loaded_tables = $.parseJSON( wpmdb_loaded_tables ); + } + + var table_select = document.createElement('select'); + $(table_select).attr('multiple', 'multiple').attr('name','select-tables[]').attr('id','select-tables'); + + $.each(connection_data.tables, function(index, value) { + var selected = $.inArray( value, loaded_tables ); + if( selected != -1 ){ + selected = ' selected="selected" '; + } + else{ + selected = ' '; + } + $(table_select).append('' + value + ''); + }); + + pull_select = table_select; + + if( $('#pull').is(':checked') ){ + $('#select-tables').remove(); + $('.select-tables-wrap').prepend(pull_select); + $('.table-prefix').html(data.prefix); + } + + } + + }); + + } + + // add to tags which act as JS event buttons, will not jump page to top and will deselect the button + $('.js-action-link').click(function(){ + $(this).blur(); + return false; + }); + + // registers your licence + $('.licence-form').submit(function(){ + if( doing_licence_registration_ajax ){ + return false; + } + + var licence_key = $.trim( $('.licence-input').val() ); + + if( licence_key == '' ){ + $('.licence-status').html( 'Please enter your license key.' ); + return false; + } + + $('.licence-status').empty().removeClass('success'); + doing_licence_registration_ajax = true; + $('.button.register-licence').after( '' ); + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'JSON', + cache: false, + data: { + action : 'wpmdb_activate_licence', + licence_key : licence_key + }, + error: function(jqXHR, textStatus, errorThrown){ + doing_licence_registration_ajax = false; + $('.register-licence-ajax-spinner').remove(); + $('.licence-status').html( 'A problem occured when trying to register the license, please try again.' ); + }, + success: function(data){ + doing_licence_registration_ajax = false; + $('.register-licence-ajax-spinner').remove(); + + if ( typeof data.errors !== 'undefined' ) { + var msg = ''; + for (var key in data.errors) { + msg += data.errors[key]; + } + $('.licence-status').html( msg ); + } + else { + $('.licence-information').html('Registered To: ' + data.email); + $('.licence-status').html( 'Your licence has been activated. You will now receive automatic updates and access to email support.'); + $('.licence-status').addClass('success'); + $('.support-content').empty().html('

Fetching licence details, please wait...

'); + check_licence( licence_key ); + } + } + }); + + return false; + }); + + // clears the debug log + $('.clear-log').click(function(){ + $('.debug-log-textarea').val(''); + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action : 'wpmdb_clear_log', + }, + error: function(jqXHR, textStatus, errorThrown){ + alert('An error occured when trying to clear the debug log. You can clear it manually by accessing the file system. (#132)'); + }, + success: function(data){ + } + }); + }); + + // updates the debug log when the user switches to the help tab + function refresh_debug_log(){ + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action : 'wpmdb_get_log', + }, + error: function(jqXHR, textStatus, errorThrown){ + alert('An error occured when trying to update the debug log. Please contact support. (#133)'); + }, + success: function(data){ + $('.debug-log-textarea').val(data); + } + }); + } + + // select all tables + $('.tables-select-all').click(function(){ + $('#select-tables').focus(); + $('#select-tables option').attr('selected',1); + }); + + // deselect all tables + $('.tables-deselect-all').click(function(){ + $('#select-tables').focus(); + $('#select-tables option').removeAttr('selected'); + }); + + // invert table selection + $('.tables-invert-selection').click(function(){ + $('#select-tables').focus(); + $('#select-tables option').each(function(){ + $(this).attr('selected', ! $(this).attr('selected')); + }); + }); + + // on option select hide all "advanced" option divs and show the correct div for the option selected + $('.option-group input[type=radio]').change(function() { + group = $(this).closest('.option-group'); + $('ul', group).hide(); + parent = $(this).closest('li'); + $('ul', parent).show(); + }); + + // on page load, expand hidden divs for selected options (browser form cache) + $('.option-group').each(function(){ + $('.option-group input[type=radio]').each(function(){ + if( $(this).is(':checked') ){ + parent = $(this).closest('li'); + $('ul', parent).show(); + } + }); + }); + + // expand and collapse content on click + $('.header-expand-collapse').click(function(){ + if( $('.expand-collapse-arrow', this).hasClass('collapsed') ){ + $('.expand-collapse-arrow', this).removeClass('collapsed'); + $(this).next().show(); + } + else{ + $('.expand-collapse-arrow', this).addClass('collapsed'); + $(this).next().hide(); + } + }); + + // special expand and collapse content on click for save migration profile + $('#save-migration-profile').change(function() { + if( $(this).is(':checked') ){ + $(this).parent().next().show(); + $('.save-settings-button').show(); + $('.migrate-db .button-primary').val('Migrate DB & Save'); + } + else{ + $(this).parent().next().hide(); + $('.save-settings-button').hide(); + $('.migrate-db .button-primary').val('Migrate DB'); + } + }); + + if( $('#save-migration-profile').is(':checked') ){ + $('#save-migration-profile').parent().next().show(); + $('.save-settings-button').show(); + $('.migrate-db .button-primary').val('Migrate DB & Save'); + }; + + // AJAX migrate button + $('.migrate-db-button').click(function(event){ + $(this).blur(); + event.preventDefault(); + + // check that they've select some tables to migrate + if( $('#migrate-selected').is(':checked') && $('#select-tables').val() == null ){ + alert( 'Please select at least one table to migrate.'); + return; + } + + // also save profile + if( $('#save-migration-profile').is(':checked') ){ + + if( $.trim( $('.create-new-profile').val() ) == '' && $('#create_new').is(':checked') ){ + alert('Please enter a name for your migration profile.'); + $('.create-new-profile').focus(); + return; + } + + var create_new_profile = false; + + if( $('#create_new').is(':checked') ){ + create_new_profile = true; + } + var profile_name = $('.create-new-profile').val(); + + profile = $('#migrate-form').serialize(); + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action: 'wpmdb_save_profile', + profile: profile, + }, + error: function(jqXHR, textStatus, errorThrown){ + alert('An error occured when attempting to save the migration profile. Please see the Help tab for details on how to request support. (#118)'); + }, + success: function(data){ + if(create_new_profile){ + var new_li = '
  • '; + $('#create_new').parents('li').before(new_li); + $('#profile-' + data).attr('checked','checked'); + $('.create-new-profile').val(''); + } + } + }); + } + + form_data = $('#migrate-form').serialize(); + + var doc_height = $(document).height(); + + $('body').append('
    '); + + $('#overlay') + .height(doc_height) + .css({ + 'position': 'fixed', + 'top': 0, + 'left': 0, + 'background-color': 'rgba(255,255,255,0.9)', + 'width': '100%', + 'z-index': 99999, + 'display': 'none', + }); + + $progress_content = progress_content_original.clone(); + var migration_intent = $('input[name=action]:checked').val(); + + var stage = 'backup'; + + if( migration_intent == 'savefile' ){ + stage = 'migrate'; + } + + if( $('#create-backup').is(':checked') == false ){ + stage = 'migrate'; + } + + var table_intent = $('input[name=table_migrate_option]:checked').val(); + var connection_info = $.trim( $('.pull-push-connection-info').val() ).split("\n"); + var remote_site = connection_info[0]; + var secret_key = connection_info[1]; + var tables_to_migrate = ''; + var table_sizes = ''; + + var static_migration_label = ''; + + $('#overlay').after($progress_content); + + var completed_msg = 'Exporting complete.'; + + if( migration_intent == 'savefile' ){ + static_migration_label = 'Exporting, please wait...'; + } + else{ + static_migration_label = get_default_profile_name(remote_site, migration_intent, true) + ', please wait...'; + completed_msg = get_default_profile_name(remote_site, migration_intent, true) + ' complete.'; + } + + $('.progress-title').html(static_migration_label); + + $('#overlay').show(); + + if( table_intent == 'migrate_select' ){ // user has elected to migrate only certain tables + // grab tables as per what the user has selected from the multiselect box + temp_tables_to_migrate = $('#select-tables').val(); + tables_to_migrate = temp_tables_to_migrate; + // user is pushing or exporting + if( migration_intent == 'push' || migration_intent == 'savefile' ){ + // default value, assuming we're not backing up + table_sizes = $.parseJSON(wpmdb_this_table_sizes); + // backing up, during a push, need to only grab the common tables + if( stage == 'backup' ){ + tables_to_migrate = get_intersect(connection_data.tables,temp_tables_to_migrate); + table_sizes = connection_data.table_sizes; + } + } + else{ + table_sizes = connection_data.table_sizes; + if( stage == 'backup' ){ + tables_to_migrate = get_intersect(temp_tables_to_migrate,this_tables); + table_sizes = $.parseJSON(wpmdb_this_table_sizes); + } + } + } + else{ + if( migration_intent == 'push' || migration_intent == 'savefile' ){ + tables_to_migrate = this_tables; + table_sizes = $.parseJSON(wpmdb_this_table_sizes); + if( stage == 'backup' ){ + tables_to_migrate = get_intersect(connection_data.tables,this_tables); + table_sizes = connection_data.table_sizes; + } + } + else{ + tables_to_migrate = connection_data.tables; + table_sizes = connection_data.table_sizes; + if( stage == 'backup' ){ + tables_to_migrate = get_intersect(connection_data.tables,this_tables); + table_sizes = $.parseJSON(wpmdb_this_table_sizes); + } + } + } + + function decide_tables_to_display( tables_to_migrate, table_sizes ){ + + var total_size = 0; + $.each(tables_to_migrate, function(index, value) { + total_size += parseInt(table_sizes[value]); + }); + + var last_element = ''; + $.each(tables_to_migrate, function(index, value) { + var percent = table_sizes[value] / total_size * 100; + var percent_rounded = Math.round(percent*1000)/1000; + $('.progress-tables').append('
    ' + value + '
    '); + $('.progress-tables-hover-boxes').append('
    '); + var label = $('.progress-tables .progress-chunk:last span'); + last_element = value; + }); + + $('.progress-chunk').each(function(index){ + if( $(this).width() < 1 && tables_to_migrate[index] != last_element ){ + $(this).hide(); + $('.progress-chunk-hover[data-table=' + tables_to_migrate[index] + ']').hide(); + table_sizes[last_element] = Number(table_sizes[last_element]); + table_sizes[last_element] += Number(table_sizes[tables_to_migrate[index]]); + table_sizes[tables_to_migrate[index]] = 0; + } + var element = this; + setTimeout(function(){ + hide_overflowing_elements(element); + }, 0); + + function hide_overflowing_elements(element){ + if( $('span', element).innerWidth() > $(element).width() ){ + $('span', element).hide(); + } + } + + }); + + percent_rounded = 0; + if( table_sizes[last_element] != 0 ){ + var percent = table_sizes[last_element] / total_size * 100; + var percent_rounded = Math.round(percent*1000)/1000; + } + $('.progress-tables .progress-chunk:last').css('width',percent_rounded + '%'); + $('.progress-chunk-hover:last').css('width',percent_rounded + '%'); + + var return_vals = [table_sizes,total_size]; + + return return_vals; + + } + + table_details = decide_tables_to_display( tables_to_migrate, table_sizes ); + table_sizes = table_details[0]; + total_size = table_details[1]; + + $('.progress-title').after( '' ); + + var height = $('.progress-content').outerHeight(); + $('.progress-content').css('top', '-' + height + 'px').show().animate({'top': '0px'}); + + setup_counter(); + currently_migrating = true; + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'json', + cache: false, + data: { + action : 'wpmdb_initiate_migration', + intent : migration_intent, + url : remote_site, + key : secret_key, + form_data : form_data, + stage : stage, + }, + error: function(jqXHR, textStatus, errorThrown){ + $('.progress-title').html('Migration failed'); + $('.progress-text').html( 'A problem occured when attempting to connect to the local server, please check the details and try again. (#112)' ); + $('.progress-text').addClass( 'migration-error' ); + }, + success: function(data){ + if( typeof data.wpmdb_error != 'undefined' && data.wpmdb_error == 1 ){ + migration_complete_events(); + $('.progress-title').html('Migration failed'); + $('.progress-text').addClass( 'migration-error' ); + $('.progress-text').html( data.body ); + return; + } + + var datetime = data.datetime; + + data = $.parseJSON( data ); + + var table_migration_error = false; + var i = 0; + var progress_size = 0; + var overall_percent = 0; + + function migrate_table_recursive(){ + + if( i >= tables_to_migrate.length ){ + if( stage == 'backup' ) { + stage = 'migrate'; + i = 0; + progress_size = 0; + $('.progress-bar').width('0px'); + + if( table_intent == 'migrate_select' ){ + tables_to_migrate = $('#select-tables').val(); + if( migration_intent == 'push' || migration_intent == 'savefile' ){ + table_sizes = $.parseJSON(wpmdb_this_table_sizes); + } + else{ + table_sizes = connection_data.table_sizes; + } + } + else{ + if( migration_intent == 'push' || migration_intent == 'savefile' ){ + tables_to_migrate = this_tables; + table_sizes = $.parseJSON(wpmdb_this_table_sizes); + } + else{ + tables_to_migrate = connection_data.tables; + table_sizes = connection_data.table_sizes; + } + } + + $('.progress-tables').empty(); + $('.progress-tables-hover-boxes').empty(); + + table_details = decide_tables_to_display( tables_to_migrate, table_sizes ); + table_sizes = table_details[0]; + total_size = table_details[1]; + + } + else { + stage == 'end'; + migration_complete(); + return; + } + } + + if( stage == 'backup'){ + $('.progress-text').html( overall_percent + '% - Backing up "' + tables_to_migrate[i] + '"' ); + } + else{ + $('.progress-text').html( overall_percent + '% - Migrating "' + tables_to_migrate[i] + '"'); + } + + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + timeout: 0, + data: { + action : 'wpmdb_prepare_table_migration', + intent : migration_intent, + url : remote_site, + key : secret_key, + table : tables_to_migrate[i], + form_data : form_data, + datetime : datetime, + stage : stage, + bottleneck : connection_data.bottleneck + }, + error: function(jqXHR, textStatus, errorThrown){ + $('.progress-title').html('Migration failed'); + $('.progress-text').html( 'A problem occured when processing the ' + tables_to_migrate[i] + ' table. (#113)' ); + $('.progress-text').addClass( 'migration-error' ); + console.log( jqXHR + ' : ' + textStatus + ' : ' + errorThrown ); + table_migration_error = true; + migration_complete_events(); + return; + }, + success: function(data){ + if( data != '' ){ + $('.progress-title').html('Migration failed'); + $('.progress-text').html(data); + $('.progress-text').addClass('migration-error'); + table_migration_error = true; + migration_complete_events(); + return; + } + progress_size += parseInt(table_sizes[tables_to_migrate[i]]); + var percent = 100 * progress_size / total_size; + $('.progress-bar').width(percent + '%'); + i++; + overall_percent = Math.floor(percent); + migrate_table_recursive(); + } + }); + + } + + function migration_complete(){ + if( migration_intent == 'savefile' ){ + currently_migrating = false; + var migrate_complete_text = 'Migration complete'; + if( $('#save_computer').is(':checked') ){ + var url = wpmdb_this_download_url + datetime; + + if( $('#gzip_file').is(':checked') ){ + url += '&gzip=1'; + } + + window.location = url; + + } + else{ + var download_url = wpmdb_this_upload_url + wpmdb_this_website_name + '-migrate-' + datetime + '.sql'; + if( $('#gzip_file').is(':checked') ){ + download_url += '.gz'; + } + migrate_complete_text = 'Migration complete, your backup is located at:
    ' + download_url + '.'; + } + + if( table_migration_error == false ){ + $('.progress-text').html(migrate_complete_text); + migration_complete_events(); + $('.progress-title').html(completed_msg); + } + + } + else{ // rename temp tables, delete old tables + $('.progress-text').html('Finalizing migration'); + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action : 'wpmdb_finalize_backup', + intent : migration_intent, + url : remote_site, + key : secret_key, + form_data : form_data, + datetime : datetime, + stage : stage, + }, + error: function(jqXHR, textStatus, errorThrown){ + $('.progress-title').html('Migration failed'); + $('.progress-text').html('A problem occured when finalizing the backup. (#132)'); + $('.progress-text').addClass('migration-error'); + console.log( jqXHR + ' : ' + textStatus + ' : ' + errorThrown ); + table_migration_error = true; + }, + success: function(data){ + $('.progress-text').html('Migration complete'); + $('.progress-title').html(completed_msg); + } + }); + migration_complete_events(); + } + } + + migrate_table_recursive(); + + } + + }); // end ajax + + }); + + function migration_complete_events(){ + migration_completed = true; + $('.progress-label').remove(); + $('.migration-progress-ajax-spinner').remove(); + $('.close-progress-content').show(); + $('#overlay').css('cursor','pointer'); + clearInterval( interval ); + currently_migrating = false; + } + + // close progress pop up once migration is completed + $('body').delegate('.close-progress-content-button', 'click', function(e){ + hide_overlay(); + }); + + $('body').delegate('#overlay', 'click', function(){ + if( migration_completed == true ){ + hide_overlay(); + } + }); + + function hide_overlay(){ + var height = $('.progress-content').outerHeight(); + $('.progress-content').animate({'top' : '-' + height + 'px'}, 400, 'swing', function(){ $('#overlay').remove(); $('.progress-content').remove(); } ); + migration_completed = false; + } + + // AJAX save button profile + $('.save-settings-button').click(function(event){ + var profile; + $(this).blur(); + event.preventDefault(); + + if( doing_save_profile ){ + return; + } + + if( $.trim( $('.create-new-profile').val() ) == '' && $('#create_new').is(':checked') ){ + alert('Please enter a name for your migration profile.'); + $('.create-new-profile').focus(); + return; + } + + var create_new_profile = false; + + if( $('#create_new').is(':checked') ){ + create_new_profile = true; + } + var profile_name = $('.create-new-profile').val(); + + doing_save_profile = true; + profile = $('#migrate-form').serialize(); + + $('.save-settings-button').after( '' ); + $(this).attr('disabled','disabled'); + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action: 'wpmdb_save_profile', + profile: profile, + }, + error: function(jqXHR, textStatus, errorThrown){ + alert('An error occured when attempting to save the migration profile. Please see the Help tab for details on how to request support. (#104)'); + $('.save-settings-button').removeAttr('disabled'); + $('.save-profile-ajax-spinner').remove(); + $('.save-settings-button').after('Saved'); + $('.ajax-success-msg').fadeOut(2000,function(){ + $(this).remove(); + }); + doing_save_profile = false; + }, + success: function(data){ + $('.save-settings-button').removeAttr('disabled'); + $('.save-profile-ajax-spinner').remove(); + $('.save-settings-button').after('Saved'); + $('.ajax-success-msg').fadeOut(2000,function(){ + $(this).remove(); + }); + doing_save_profile = false; + $('.create-new-profile').val(''); + + if(create_new_profile){ + var new_li = '
  • '; + $('#create_new').parents('li').before(new_li); + $('#profile-' + data).attr('checked','checked'); + } + + } + }); + + }); + + // progress label updating + $('body').delegate('.progress-chunk-hover', 'mousemove', function(e) { + mX = e.pageX; + offset = $('.progress-bar-wrapper').offset(); + label_offset = $('.progress-label').outerWidth() / 2; + mX = ( mX - offset.left ) - label_offset; + $('.progress-label').css('left', mX + 'px'); + $('.progress-label').html($(this).attr('data-table')); + }); + + // show / hide progress lavel on hover + $('body').delegate('.progress-chunk-hover', 'hover', function(event) { + if( event.type === 'mouseenter' ){ + $('.progress-label').addClass('label-visible'); + } + else{ + $('.progress-label').removeClass('label-visible'); + } + }); + + // move around textarea depending on whether or not the push/pull options are selected + connection_info_box = $('.connection-info-wrapper'); + move_connection_info_box(); + + $('.migrate-selection.option-group input[type=radio]').change(function() { + move_connection_info_box(); + + $('.backup-options').show(); + if( $('#savefile').is(':checked') ){ + $('.backup-options').hide(); + } + + if( connection_established ){ + change_replace_values(); + } + }); + + // save file (export) / import / push / pull special conditions + function move_connection_info_box(){ + $('.import-button').hide(); + $('.connection-status').hide(); + var connection_info = $.trim( $('.pull-push-connection-info').val() ).split("\n"); + if( $('#pull').is(':checked') ){ + $('.pull-list li').append( connection_info_box ); + connection_info_box.show(); + if( connection_established ){ + $('.connection-status').hide(); + $('.step-two').show(); + $('.table-prefix').html(connection_data.prefix); + if( profile_name_edited == false ){ + var profile_name = get_domain_name( connection_info[0] ); + $('.create-new-profile').val(profile_name); + } + } + else{ + $('.connection-status').show(); + $('.step-two').hide(); + } + } + else if( $('#push').is(':checked') ){ + $('.push-list li').append( connection_info_box ); + connection_info_box.show(); + if( connection_established ){ + $('.connection-status').hide(); + $('.step-two').show(); + $('.table-prefix').html(wpmdb_this_prefix); + if( profile_name_edited == false ){ + var profile_name = get_domain_name( connection_info[0] ); + $('.create-new-profile').val(profile_name); + } + } + else{ + $('.connection-status').show(); + $('.step-two').hide(); + } + } + else if( $('#savefile').is(':checked') ){ + $('.connection-status').hide(); + $('.step-two').show(); + $('.table-prefix').html(wpmdb_this_prefix); + if( profile_name_edited == false ){ + $('.create-new-profile').val(''); + } + } + } + + // replace tables and replaces depending on which option is selected + var intent = $('input[name=action]:checked').val(); + if( intent == 'pull' ){ + last_replace_switch = 'pull'; + } + else if( intent == 'savefile' || intent == 'push' ){ + last_replace_switch = 'push'; + } + + function change_replace_values(){ + if( $('#push').is(':checked') || $('#savefile').is(':checked') ){ + if( last_replace_switch == '' || last_replace_switch == 'pull' ){ + $('.replace-row').each(function(){ + var old_val = $('.old-replace-col input', this).val(); + $('.old-replace-col input', this).val( $('.replace-right-col input', this).val() ); + $('.replace-right-col input', this).val( old_val ); + }); + } + $('#select-tables').remove(); + $('.select-tables-wrap').prepend(push_select); + last_replace_switch = 'push'; + } + else if( $('#pull').is(':checked') ){ + if( last_replace_switch == '' || last_replace_switch == 'push' ){ + $('.replace-row').each(function(){ + var old_val = $('.old-replace-col input', this).val(); + $('.old-replace-col input', this).val( $('.replace-right-col input', this).val() ); + $('.replace-right-col input', this).val( old_val ); + }); + } + $('#select-tables').remove(); + $('.select-tables-wrap').prepend(pull_select); + last_replace_switch = 'pull'; + } + + } + + // keep a copy of the table select box when making changes + $('#select-tables').change(function(){ + if( $('#push').is(':checked') || $('#savefile').is(':checked') ){ + push_select = $('#select-tables').clone(); + } + else if( $('#pull').is(':checked') ){ + pull_select = $('#select-tables').clone(); + } + }); + + // hide second section if pull or push is selected with no connection established + if( ( $('#pull').is(':checked') || $('#push').is(':checked') ) && ! connection_established ){ + $('.step-two').hide(); + $('.connection-status').show(); + } + + // show / hide GUID helper description + $('.replace-guid-helper').click(function(){ + $('.replace-guids-info').toggle(); + }); + + $('body').click(function(){ + $('.replace-guids-info').hide(); + }); + + $('.replace-guids-info').click(function(e){ + e.stopPropagation(); + }); + + // migrate / settings tabs + $('.nav-tab').click(function(){ + $('.nav-tab').removeClass('nav-tab-active'); + $(this).addClass('nav-tab-active'); + $('.content-tab').hide(); + $('.' + $(this).attr('data-div-name')).show(); + + var hash = $(this).attr('data-div-name'); + hash = hash.replace('-tab',''); + window.location.hash = hash; + + if( $(this).hasClass('help') ) { + refresh_debug_log(); + if( wpmdb_licence != '0' && checked_licence == false ) { + check_licence( wpmdb_licence ); + checked_licence = true; + } + } + + }); + + // repeatable fields + $('body').delegate('.replace-add-row', 'click', function() { + $(this).parents('tr').after( $('.original-repeatable-field').clone().removeClass('original-repeatable-field') ); + }); + + // repeatable fields + $('body').delegate('.replace-remove-row', 'click', function() { + $(this).parents('tr').remove(); + if( $('.replace-row').length < 2 ){ + $('.no-replaces-message').show(); + } + }); + + $('.add-replace').click(function(){ + $('.replace-fields').append( $('.original-repeatable-field').clone().removeClass('original-repeatable-field') ); + $('.no-replaces-message').hide(); + }); + + // delete saved profiles + $('body').delegate('.save-migration-profile-wrap li', 'hover', function(event) { + if( event.type === 'mouseenter' ){ + $('.delete-profile', this).show(); + } + else{ + $('.delete-profile', this).hide(); + } + }); + + function validate_url( url ){ + return /^([a-z]([a-z]|\d|\+|-|\.)*):(\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?((\[(|(v[\da-f]{1,}\.(([a-z]|\d|-|\.|_|~)|[!\$&'\(\)\*\+,;=]|:)+))\])|((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=])*)(:\d*)?)(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*|(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)){0})(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(url); + } + + // check for hash in url (settings || migrate) switch tabs accordingly + if(window.location.hash) { + var hash = window.location.hash.substring(1); + if( hash == 'settings' || hash == 'help' ){ + $('.nav-tab').removeClass('nav-tab-active'); + $('.nav-tab.' + hash).addClass('nav-tab-active'); + $('.content-tab').hide(); + $('.' + hash + '-tab').show(); + } + + if ( hash == 'help' ) { + refresh_debug_log(); + if( wpmdb_licence != '0' ) { + check_licence( wpmdb_licence ); + checked_licence = true; + } + } + } + + // regenerates the saved secret key + $('.reset-api-key').click(function(){ + var answer = confirm('Any sites setup to use the current API key will no longer be able to connect. You will need to update those sites with the newly generated API key. Do you wish to continue?'); + + if( ! answer || doing_reset_api_key_ajax ){ + return; + } + + doing_reset_api_key_ajax = true; + $('.reset-api-key').after( '' ); + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action: 'wpmdb_reset_api_key', + }, + error: function(jqXHR, textStatus, errorThrown){ + alert('An error occured when trying to generate the API key. Please see the Help tab for details on how to request support. (#105)'); + $('.reset-api-key-ajax-spinner').remove(); + doing_reset_api_key_ajax = false; + }, + success: function(data){ + $('.reset-api-key-ajax-spinner').remove(); + doing_reset_api_key_ajax = false; + $('.connection-info').html(data); + } + }); + + }); + + var this_connection_info = $.parseJSON( wpmdb_connection_info ); + + // show / hide table select box when specific settings change + $('input[name=table_migrate_option]').change(function(){ + $('.select-tables-wrap').toggle(); + }); + + if( $('#migrate-selected').is(':checked') ){ + $('.select-tables-wrap').toggle(); + } + + // delete a profile from the migrate form area + $('body').delegate('.delete-profile', 'click', function(){ + var name = $(this).next().clone(); + $('input',name).remove(); + var name = $.trim($(name).html()); + var answer = confirm('You are removing the "' + name + '" migration profile. This cannot be undone. Do you wish to continue?'); + + if(!answer){ + return; + } + + $(this).parent().fadeOut(500); + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action : 'wpmdb_delete_migration_profile', + profile_id : $(this).attr('data-profile-id') + }, + error: function(jqXHR, textStatus, errorThrown){ + alert('An error occured when trying to delete the profile. Please see the Help tab for details on how to request support. (#106)'); + }, + success: function(data){ + if( data == '-1' ){ + alert('The selected migration profile could not be deleted because it was not found.\nPlease refresh this page to see an accurate list of the currently available migration profiles.'); + } + } + }); + + }); + + // deletes a profile from the main profile selection screen + $('.main-list-delete-profile-link').click(function(){ + var name = $(this).prev().html(); + var answer = confirm('You are removing the "' + name + '" migration profile. This cannot be undone. Do you wish to continue?'); + + if(!answer){ + return; + } + + $(this).parent().fadeOut(500); + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action : 'wpmdb_delete_migration_profile', + profile_id : $(this).attr('data-profile-id') + }, + error: function(jqXHR, textStatus, errorThrown){ + alert('An error occured when trying to delete the profile. Please see the Help tab for details on how to request support. (#107)'); + } + }); + + }); + + // warn the user when editing the connection info after a connection has been established + $('body').delegate('.temp-disabled', 'click', function() { + var answer = confirm('If you change the connection details, you will lose any replaces and table selections you have made below. Do you wish to continue?'); + + if( ! answer ){ + return; + } + else{ + $(this).removeClass('temp-disabled'); + $(this).removeAttr('readonly'); + $('.connect-button').show(); + $('.step-two').hide(); + $('.connection-status').show().html('Please enter the connection information above to continue.'); + connection_established = false; + } + }); + + // ajax request for settings page when checking/unchecking setting radio buttons + $('.settings-tab input[type=checkbox]').change(function(){ + var checked = $(this).is(':checked'); + var setting = $(this).attr('id'); + + $(this).parent().append( '' ); + var $label = $(this).parent(); + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action : 'wpmdb_save_setting', + checked : checked, + setting : setting + }, + error: function(jqXHR, textStatus, errorThrown){ + alert('An error occured when trying to save the settings. Please try again. If the problem persists, please see the Help tab for details on how to request support. (#108)'); + $('.ajax-spinner').remove(); + }, + success: function(data){ + $('.ajax-spinner').remove(); + $($label).append('Saved'); + $('.ajax-success-msg').fadeOut(2000,function(){ + $(this).remove(); + }); + } + }); + + }); + + // disable form submissions + $('.migrate-form').submit(function(){ + return false; + }); + + // fire connection_box_changed when the connect button is pressed + $('.connect-button').click(function(event){ + event.preventDefault(); + $(this).blur(); + connection_box_changed($('.pull-push-connection-info').val()); + }); + + // send paste even to connection_box_changed() function + $('.pull-push-connection-info').bind('paste', function(e) { + var $this = this; + setTimeout(function () { + connection_box_changed($($this).val()); + }, 0); + + }); + + $('body').delegate('.try-again','click',function(){ + connection_box_changed($('.pull-push-connection-info').val()); + }); + + $('.create-new-profile').change(function(){ + profile_name_edited = true; + }); + + // fired when the connection info box changes (e.g. gets pasted into) + function connection_box_changed(data){ + var $this = $('.pull-push-connection-info'); + + if( doing_ajax || $($this).hasClass('temp-disabled') ){ + return; + } + + var connection_info = $.trim(data).split("\n"); + var error = false; + var error_message = ''; + + if( connection_info == '' ){ + error = true; + error_message = 'The connection information appears to be missing, please enter it to continue.'; + } + + if( connection_info.length != 2 && ! error ){ + error = true; + error_message = 'The connection information appears to be incorrect, it should consist of two lines. The first being the remote server\'s URL and the second being the secret key.'; + } + + if( ! error && ! validate_url( connection_info[0] ) ){ + error = true; + error_message = 'The URL on the first line appears to be invalid, please check it and try again.'; + } + + if( ! error && connection_info[1].length != 32 ){ + error = true; + error_message = 'The secret key on the second line appears to be invalid. It should be a 32 character string that consists of letters, numbers and special characters only.'; + } + + if( ! error && connection_info[0] == this_connection_info[0] ){ + error = true; + error_message = 'It appears you\'ve entered the URL for this website, you need to provide the URL of the remote website instead.'; + } + + if( ! error && connection_info[1] == this_connection_info[1] ){ + error = true; + error_message = 'It appears you\'ve entered the secret key for this website, you need to provide the secret key for the remote website instead.'; + } + + if( error ){ + $('.connection-status').html( error_message ); + $('.connection-status').addClass( 'migration-error' ); + return; + } + + doing_ajax = true; + + $('.step-two').hide(); + $('.connection-status').show(); + + $('.connection-status').html( 'Establishing connection to remote server, please wait' ); + $('.connection-status').removeClass( 'migration-error' ); + $('.connection-status').append( '' ); + + var intent = $('input[name=action]:checked').val(); + + profile_name_edited = false; + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'json', + cache: false, + data: { + action: 'wpmdb_prepare_remote_connection', + url: connection_info[0], + key: connection_info[1], + intent: intent, + }, + error: function(jqXHR, textStatus, errorThrown){ + $('.connection-status').html( 'A problem occured when attempting to connect to the local server, please check the details and try again. (#100)' ); + $('.connection-status').addClass( 'migration-error' ); + $('.ajax-spinner').remove(); + doing_ajax = false; + }, + success: function(data){ + $('.ajax-spinner').remove(); + doing_ajax = false; + + if( typeof data.wpmdb_error != 'undefined' && data.wpmdb_error == 1 ){ + $('.connection-status').html( data.body ); + $('.connection-status').addClass( 'migration-error' ); + return; + } + + var profile_name = get_domain_name( connection_info[0] ); + $('.create-new-profile').val(profile_name); + + var original_body = data; + data = $.parseJSON( data ); + + $('.pull-push-connection-info').addClass('temp-disabled'); + $('.pull-push-connection-info').attr('readonly','readonly'); + $('.connect-button').hide(); + + $('.connection-status').hide(); + $('.step-two').show(); + connection_established = true; + connection_data = data; + + $('.remote-json-data').val(original_body); + + var table_select = document.createElement('select'); + $(table_select).attr('multiple', 'multiple').attr('name','select-tables[]').attr('id','select-tables'); + + $.each(connection_data.tables, function(index, value) { + $(table_select).append(''); + }); + + pull_select = table_select; + + if( $('#pull').is(':checked') ){ + $('#new-url').val( wpmdb_this_url ); + $('#new-path').val( wpmdb_this_path ); + $('#old-url').val( data.url ); + $('#old-path').val( data.path ); + $('#select-tables').remove(); + $('.select-tables-wrap').prepend(pull_select); + $('.table-prefix').html(data.prefix); + } + else{ + $('#new-url').val( data.url ); + $('#new-path').val( data.path ); + } + + } + + }); + + } + + }); + +})(jQuery); \ No newline at end of file diff --git a/asset/sass/styles.scss b/asset/sass/styles.scss index 1b97ccd..547efa9 100644 --- a/asset/sass/styles.scss +++ b/asset/sass/styles.scss @@ -1,188 +1,1037 @@ -#migrate-form { - padding-top: 10px; -} +@import "compass"; + +.wpmdb{ + + /* ============================================================================= + Common & Global + ========================================================================== */ + a { + text-decoration: none; + } + + li { + margin-bottom: 5px; + position: relative; + } + + ul { + margin: 0; + } + + input[type=checkbox], + input[type=radio]{ + margin-right: 5px; + vertical-align: baseline; + margin-top: 0; + } + + input[type=text] { + padding: 5px; + } -.form-table { - .row-new-url, - .row-new-path, - .row-revisions { - th, td { - padding-bottom: 20px; - border-bottom: 1px solid #ccc; + .option-section { + border-bottom: 1px solid #ccc; + padding-bottom: 20px; + margin-bottom: 20px; + h3 { + font-size: 18px; + font-weight: normal; } } - .row-old-path, - .row-save-file, - .row-guids { - th, td { - padding-top: 20px; + p.migrate-db { + overflow: hidden; + + input { + float: left; + } + + img { + float: left; + margin: 3px 0 0 5px; } + + .save-settings-button{ + margin-left: 10px; + display: none; + } + } + + .indent-wrap { + margin-left: 25px; + } + + .expandable-content{ + display: none; + margin-top: 10px; + } + + .expandable-content li:last-child{ + margin-bottom: 0px; + } + + .header-wrapper { + margin-bottom: 10px; + } + + .header-expand-collapse{ + cursor: pointer; + display: inline-block; + } + + .option-description{ + font-size: 12px; + color: #999; + margin-left: 8px; + font-weight: normal; + } + + .option-group li:last-child{ + margin-bottom: 0; + } + + .connection-status{ + display: none; + } + + .connection-status.error{ + color: #9D1818; + } + + .ajax-spinner{ + left: 6px; + position: relative; + top: 3px; + } + + div.message{ + margin: 15px 0 0; } -} -p.submit { - overflow: hidden; - padding-top: 20px; - border-top: 1px solid #ccc; - margin-top: 20px; + .licence-wrap h3 { + margin: 0 0 10px 0; + } - input { - float: left; + .licence-input { + clear: both; + display: block; + font-family: "Courier New",Courier,monospace; + font-size: 14px; + margin-bottom: 7px; + padding: 10px; + width: 418px; } - img { + .register-licence { float: left; - margin: 3px 0 0 5px; - } -} + } -#wpmdb-container { - position: relative; -} + .licence-status { + color: #A21B1B; + font-weight: bold; + clear: both; + padding-top: 0.5em; + margin: 0; + } -#wpmdb-main { - margin-right: 320px; - min-height: 1200px; -} + .licence-status.success { + color: #333; + } -#wpmdb-sidebar { - position: absolute; - top: 0; - right: 0; - width: 250px; - border: 1px solid #ccc; - padding: 20px; + .licence-information { + margin-bottom: 5px; + } - .author { - padding-bottom: 20px; - margin-bottom: 20px; - border-bottom: 1px solid #ccc; - overflow: hidden; + .register-licence-ajax-spinner { + margin: 4px 0 0 8px; + } - img { - float: left; - margin-right: 20px; - } + /* ============================================================================= + Migrate Tab + ========================================================================== */ - .desc { - float: left; - } + /* Misc */ + + .return-to-profile-selection{ + margin-bottom: 15px; + display: inline-block; + } - h3 { - font-size: 12px; - margin: 0; + .return-to-profile-selection.bottom{ + margin-top: 10px; + } + + /* Tabs */ + + h2.nav-tab-wrapper { + margin-top: 10px; + margin-bottom: 20px; + padding-left: 10px; + + a { + margin-right: 4px; } + + a.nav-tab-active { + color: #464646; + cursor: default; + } + } - h2 { - font-size: 18px; - margin: 0; - padding: 0; + label { + display: inline-block; + clear: both; + } - a { - color: #464646; - text-decoration: none; + /* Saved migration profile selection */ - &:hover { - color: #000; - } - } - } + .saved-migration-profile-label{ + font-weight: bold; + font-size: 14px; + } - p { - margin: 0; - } + .migration-profile-options li{ + position: relative; + width: 520px; } - .subscribe { - padding-bottom: 20px; - margin-bottom: 20px; - border-bottom: 1px solid #ccc; + .migration-profile-options li a{ + padding: 5px 10px; + width: 500px; + border: 1px solid #ddd; + margin: 0px 0px 7px; + display: block; + font-size: 14px; + color: #333; + } + + .migration-profile-options li a:hover{ + border-color: #bbb; + } + + .main-list-delete-profile-link{ + color: #999999; + font-family: "Times New Roman", serif; + font-size: 26px; + font-weight: 200; + position: absolute; + right: 7px; + top: 6px; + cursor: pointer; + } + + .main-list-delete-profile-link:hover{ + color: #444; + } + + /* Output Selection */ + + .option-group { + + li { + margin-bottom: 5px; + } + + > li { + margin-bottom: 8px; + } - h2 { - padding: 0; - margin: 0; - margin-bottom: 0.5em; - color: #666; - font-size: 20px; + li > label { + font-size: 14px; + font-weight: bold; } ul { - list-style-type: disc; + display: none; + margin: 10px 0px 10px 25px; + + label { + font-size: 12px; + font-weight: normal; + } } + + } - li { - margin-left: 1.5em; - color: #666; + .import-file { + label { + margin-right: 1em; } - p { - margin: 0; - } + input { - p.interesting { - margin-bottom: 1em; } - .error { - color: red; - font-weight: bold; - margin-bottom: 1em; + .note { + display: block; + color: #999; + font-style: italic; } + } - .thanks { - color: #333; - font-weight: bold; - font-size: 14px; + .option-heading { + font-size: 14px; + font-weight: bold; + } + + .expand-collapse-arrow { + margin-right: 9px; + } + + .migrate-connection-info{ + min-width: 675px; + margin: 0; + } + + .migrate-tab .pull-push-connection-info { + width: 418px; + height: 65px; + color: #333; + font-family: "Courier New",Courier,monospace; + font-size: 15px; + line-height: 21px; + padding: 10px; + } + + .connection-info-wrapper { + display: none; + width: 670px; + } + + .connect-button { + margin-top: 2px; + } + + .temp-disabled { + background-color: #EEEEEE; + color: #888888; + font-family: "Courier New",Courier,monospace; + text-shadow: 0 1px 0 #FFFFFF; + } + + .push-list ul{ + margin-bottom: 0px; + } + + /* Find and Replace */ + + .find-heading, .replace-heading { + float: left; + } + + .find-heading { + width: 400px; + } + + .replace-fields { + border-collapse: collapse; + border-spacing: 0px; + } + + .replace-fields input { + width: 295px; + } + + .replace-fields tr td{ + padding-bottom: 7px; + } + + .replace-fields tr:last-child td{ + padding-bottom: 0px; + } + + .arrow-col { + width: 93px; + text-align: center; + vertical-align: middle; + } + + .right-arrow { + font-size: 36px; + color: #aaa; + font-family: arial, sans-serif; + } + + .replace-right-col span { + border-radius: 50%; + border: 1px solid #ccc; + background-color: #eee; + width: 16px; + height: 16px; + display: inline-block; + position: relative; + top: 4px; + cursor: pointer; + } + + .replace-right-col span:hover { + border-color: #aaa; + } + + .replace-remove-row { + margin: 0px 2px; + } + + .replace-remove-row:after { + content: ''; + background-color: #aaa; + display: block; + height: 2px; + left: 5px; + position: absolute; + top: 7px; + width: 6px; + } + + .replace-add-row:after { + content: ''; + background-color: #aaa; + display: block; + height: 2px; + left: 5px; + position: absolute; + top: 7px; + width: 6px; + } + + .replace-add-row:before { + content: ''; + background-color: #aaa; + display: block; + height: 6px; + left: 7px; + position: absolute; + top: 5px; + width: 2px; + } + + .original-repeatable-field{ + display: none; + } + + .no-replaces-message{ + display: none; + margin-bottom: 0px; + } + + /* Select Tables */ + + .tables-header { + display: inline-block; + } + + .expand-collapse-arrow { + display: inline-block; + position: relative; + top: -2px; + font-size: 11px; + + } + + .collapsed { + -moz-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); + -webkit-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); + -o-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); + -ms-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); + transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); + } + + .select-deselect-divider { + margin: 0 6px; + } + + .select-tables-wrap{ + display: none; + margin-top: 12px; + } + + #select-tables { + min-width: 420px; + min-height: 180px; + margin-bottom: 10px; + } + + .table-migrate-options li label{ + font-size: 12px; + font-weight: normal; + } + + .table-migrate-options li{ + margin-bottom: 5px; + } + + /* Advanced Options */ + + .replace-guid-helper { + border-radius: 50%; + border: 1px solid #ccc; + background-color: #eee; + width: 15px; + height: 15px; + display: inline-block; + position: relative; + top: 4px; + cursor: pointer; + margin-left: 2px; + } + + .replace-guid-helper:hover { + border-color: #aaa; + } + + .replace-guid-helper:after { + content: "?"; + color: #999999; + font-size: 10px; + font-weight: bold; + left: 4px; + position: absolute; + top: -1px; + } + + .replace-guids-info { + padding: 10px; + border: 1px solid #ccc; + border-radius: 3px; + background-color: #fff; + position: absolute; + width: 500px; + left: 140px; + z-index: 100; + top: -7px; + display: none; + box-shadow: 0px 0px 5px #ccc; + } + + .replace-guids-info:after { + content: ''; + border-bottom: 7px solid transparent; + border-right: 7px solid #fff; + border-top: 7px solid transparent; + display: block; + height: 0; + left: -7px; + position: absolute; + top: 11px; + width: 0; + } + + .replace-guids-info:before { + content: ''; + border-bottom: 7px solid transparent; + border-right: 7px solid #aaa; + border-top: 7px solid transparent; + display: block; + height: 0; + left: -8px; + position: absolute; + top: 11px; + width: 0; + } + + .label-disabled { + color: #888; + } + + /* Save migration profile */ + + .save-migration-profile { + font-size: 14px; + font-weight: bold; + } + + .save-migration-profile-wrap { + + li label{ + font-size: 12px; + font-weight: normal; + } + + li{ + margin-bottom: 5px; + padding-left: 25px; } - .field { - margin-bottom: 1em; + } + + .save-migration-profile-wrap .indent-wrap { + margin-left: 0px; + } + + .create-new-label { + margin-right: 8px; + } + + .create-new-profile { + position: absolute; + top: -5px; + } + + .delete-profile { + background-color: #eee; + border: 1px solid #ccc; + border-radius: 50% 50% 50% 50%; + cursor: pointer; + height: 11px; + left: 5px; + margin-left: 2px; + position: absolute; + margin-top: -6px; + top: 50%; + width: 11px; + display: none; + background-position: 50% 50%; + background-size: 6px 6px; + background-repeat: no-repeat; + } - p { - margin-bottom: 0.3em; + .delete-profile:after { + content:"\00d7"; + left: 2px; + position: absolute; + top: -3px; + color: #aaa; + font-size: 12px; + } + + .delete-profile:hover { + border-color: #aaa; + } + + /* Action buttons */ + + .migrate-db .ajax-success-msg { + font-weight: bold; + margin: 3px 0 0 9px; + display: inline-block; + } + + p img.save-profile-ajax-spinner { + margin-left: 10px; + } + + /* Import DB */ + .import-button { + display: none; + } + + /* ============================================================================= + Settings Tab + ========================================================================== */ + + .settings-tab{ + display: none; + + .option-section{ + + li label{ + font-size: 12px; + font-weight: normal; + position: relative; + } + + li{ + margin-bottom: 5px; } - .willing-copy { + li:last-child{ + margin-bottom: 0px; + } + + .ajax-spinner{ + right: -23px; + left: inherit; + top: 0px; + position: absolute; + } + + .ajax-success-msg{ + right: -42px; + left: inherit; + top: 0px; + position: absolute; font-weight: bold; - font-size: 14px; - line-height: 1.4em; - margin-bottom: 1em; } - &.how-much { - input { - width: 50px; - } + } + } + + .allow-remote-reqeusts { + font-size: 14px; + font-weight: bold; + } + + .connection-info-label{ + margin-top: 15px; + margin-bottom: 5px; + display: block; + } + + .connection-info{ + clear: both; + background-color: #eee; + color: #888; + font-size: 15px; + line-height: 21px; + font-family: "Courier New", Courier, monospace; + padding: 10px 10px; + height: 67px; + text-shadow: 0px 1px 0px #fff; + display: block; + margin-bottom: 7px; + width: 418px; + } + + .reset-button-wrap{ + width: 418px; + } + + .reset-api-key{ + float: left; + } + + .reset-api-key-ajax-spinner{ + float: left; + margin: 4px 7px; + } + + /* ============================================================================= + Settings Tab + ========================================================================== */ + + .help-tab { + display: none; + + h3 { + font-size: 18px; + font-weight: normal; + } + + .support { + border-bottom: 1px solid #ccc; + margin-bottom: 25px; + padding-bottom: 18px; + + h3 { + + } + + p { + width: 640px; } - &.notify-me { - input { - position: absolute; + .email { + a { + font-size: 12px; } + } + + .ajax-spinner { + top: 2px; + } + } - label { + .video-viewer { + margin-bottom: 30px; + } + + .videos { + width: 640px; + border-bottom: 1px solid #CCCCCC; + margin-bottom: 25px; + padding-bottom: 28px; + + ul > li { + margin-bottom: 30px; + overflow: hidden; + position: relative; + + a { + overflow: hidden; display: block; - padding-left: 20px; + width: 320px; + height: 180px; + float: left; + margin-right: 15px; + position: relative; + z-index: 1; } - } + $size: 64px; - &.comments { - textarea { - width: 230px; - height: 3em; + a:before, a:after { + position: absolute; + content: " "; + margin: auto; + left: 0; + right: 0; + top: 0; + bottom: 0; + } + + a:before { + width: $size; + height: $size; + @include border-radius($size); + @include opacity(0.8); + border: 1px solid #ddd; + background-color: #fff; + z-index: 2; + } - &.has-content, - &:focus { - height: 5em; - } + a:after { + @include opacity(0.8); + border: $size/3 solid transparent; + border-top-width: $size/5; + border-bottom-width: $size/5; + border-left-color: #333; + background: transparent; + display: block; + left: 25px; + width: 0px; + height: 0px; + z-index: 3; } } - &.submit-button { - margin-bottom: 0; + .video:last-child { + margin-bottom: 0px; } + + img { + width: 320px; + height: 240px; + position: relative; + top: 50%; + margin-top: -120px; + } + } + + .debug { + width: 640px; + + textarea{ + width: 100%; + min-height: 200px; + font-family: "Courier New",Courier,monospace; + margin-bottom: 5px; + } + } + + h4 { + margin: 0 0 0.2em 0; + } + + p { + margin: 0 0 0.5em 0; + } + + iframe { + display: none; + } + } + +} + +/* Progress Information */ + +/* Contain floats: h5bp.com/q */ +.clearfix:before, .clearfix:after { content: ""; display: table; } +.clearfix:after { clear: both; } +.clearfix { zoom: 1; } + +.general-spinner{ + width: 16px; + height: 16px; +} + +.migration-error { + color: #A21B1B; + font-weight: bold; +} + +.progress-content{ + display: none; + position: relative; + margin: 0 auto; + background-color: #fff; + padding: 50px; + box-shadow: 0 0 10px #ccc; + cursor: default; + width: 80%; + z-index: 99999; + position: fixed; + left: 50%; + margin-left: -40%; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + + .progress-bar { + height: 10px; + background-color: #8cc1e9; + margin-bottom: 5px; + @include background-image(linear-gradient(bottom, #72a7cf, #8cc1e9)); + } + + .progress-title { + font-size: 18px; + font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", sans-serif; + font-weight: normal; + float: left; } + + .progress-bar { + width: 0%; + } + + .progress-info-wrapper { + margin-bottom: 10px; + } + + .progress-text { + clear: left; + float: left; + } + + .timer { + float: right; + } + + .progress-tables { + overflow: hidden; + margin-bottom: 2px; + padding: 0 0 20px 0; + } + + .progress-bar-wrapper { + position: relative; + } + + .progress-bar-wrapper:before{ + content: ''; + display: block; + height: 5px; + width: 1px; + background-color: #ccc; + position: absolute; + top: 15px; + left: 0px; + } + + .progress-tables-hover-boxes { + position: absolute; + top: 0px; + left: 0px; + display: block; + width: 100%; + } + + .progress-chunk-hover { + display: block; + float: left; + height: 35px; + position: relative; + top: -5px; + z-index: 1; + } + + .progress-chunk { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + float: left; + display: block; + height: 6px; + border-right: 1px solid #ccc; + border-bottom: 1px solid #ccc; + color: #999; + position: relative; + text-align: center; + + span { + padding: 0px 3px; + white-space: nowrap; + text-overflow: ellipsis; + margin-top: 10px; + display: inline-block; + } + } + + .progress-label { + padding: 5px 10px; + border: 1px solid #ccc; + border-radius: 3px; + background-color: #fff; + colour: #333; + font-family: "Courier New",Courier,monospace; + font-size: 12px; + display: inline-block; + top: -35px; + position: absolute; + opacity: 0; + -webkit-transition: opacity 200ms ease-in-out; + -moz-transition: opacity 200ms ease-in-out; + -ms-transition: opacity 200ms ease-in-out; + -o-transition: opacity 200ms ease-in-out; + transition: opacity 200ms ease-in-out; + } + + .label-visible { + opacity: 1; + } + + .progress-label:before { + content: ""; + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #ccc; + display: block; + position: absolute; + bottom: -5px; + left: 50%; + margin-left: -2px; + } + + .progress-label:after { + content: ""; + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #fff; + display: block; + position: absolute; + bottom: -4px; + left: 50%; + margin-left: -2px; + } + + .migration-progress-ajax-spinner { + left: 7px; + position: relative; + top: 15px; + } + + .close-progress-content { + color: #999999; + cursor: pointer; + font-family: "Times New Roman",serif; + font-size: 26px; + font-weight: 200; + position: absolute; + right: 20px; + top: 20px; + padding: 5px; + display: none; + } + + .close-progress-content:hover { + color: #666; + border-color: #aaa; + } + } \ No newline at end of file diff --git a/class/wp-migrate-db.php b/class/wp-migrate-db.php new file mode 100644 index 0000000..c749a65 --- /dev/null +++ b/class/wp-migrate-db.php @@ -0,0 +1,1650 @@ +plugin_file_path = $plugin_file_path; + $this->plugin_dir_path = plugin_dir_path( $plugin_file_path ); + $this->plugin_slug = basename( $this->plugin_dir_path ); + $this->plugin_basename = plugin_basename( $plugin_file_path ); + + $upload_dir = wp_upload_dir(); + $this->upload_dir = $upload_dir['basedir']; + $this->upload_url = $upload_dir['baseurl']; + + $this->replaced['serialized']['count'] = 0; + $this->replaced['serialized']['strings'] = ''; + $this->replaced['nonserialized']['count'] = 0; + + if ( defined( 'DBRAINS_API_BASE' ) ) { + $this->dbrains_api_base = DBRAINS_API_BASE; + } + + $this->transient_timeout = 60 * 60 * 12; + $this->transient_retry_timeout = 60 * 60 * 2; + + $this->dbrains_api_url = $this->dbrains_api_base . '/?wc-api=delicious-brains'; + + $this->settings = get_site_option( 'wpmdb_settings' ); + + $this->max_insert_string_len = 50000; // 50000 is the default as defined by phphmyadmin + + // if no settings exist then this is a fresh install, set up some default settings + if ( empty( $this->settings ) ) { + $this->settings = array( + 'key' => $this->generate_key(), + 'allow_pull' => false, + 'allow_push' => false, + 'profiles' => array(), + 'licence' => '', + 'licence_email' => '' + ); + update_site_option( 'wpmdb_settings', $this->settings ); + } + + add_filter( 'plugin_action_links_' . $this->plugin_basename, array( $this, 'plugin_action_links' ) ); + + add_action( 'admin_menu', array( $this, 'admin_menu' ) ); + add_action( 'admin_head-tools_page_wp-migrate-db-pro', array( $this, 'admin_head_connection_info' ) ); + + // internal AJAX handlers + add_action( 'wp_ajax_wpmdb_prepare_remote_connection', array( $this, 'ajax_prepare_remote_connection' ) ); + add_action( 'wp_ajax_wpmdb_reset_api_key', array( $this, 'ajax_reset_api_key' ) ); + add_action( 'wp_ajax_wpmdb_delete_migration_profile', array( $this, 'ajax_delete_migration_profile' ) ); + add_action( 'wp_ajax_wpmdb_save_setting', array( $this, 'ajax_save_setting' ) ); + add_action( 'wp_ajax_wpmdb_save_profile', array( $this, 'ajax_save_profile' ) ); + add_action( 'wp_ajax_wpmdb_initiate_migration', array( $this, 'ajax_initiate_migration' ) ); + add_action( 'wp_ajax_wpmdb_prepare_table_migration', array( $this, 'ajax_prepare_table_migration' ) ); + add_action( 'wp_ajax_wpmdb_finalize_backup', array( $this, 'ajax_finalize_backup' ) ); + add_action( 'wp_ajax_wpmdb_clear_log', array( $this, 'ajax_clear_log' ) ); + add_action( 'wp_ajax_wpmdb_get_log', array( $this, 'ajax_get_log' ) ); + add_action( 'wp_ajax_wpmdb_activate_licence', array( $this, 'ajax_activate_licence' ) ); + add_action( 'wp_ajax_wpmdb_check_licence', array( $this, 'ajax_check_licence' ) ); + + // external AJAX handlers + add_action( 'wp_ajax_nopriv_wpmdb_establish_remote_connection', array( $this, 'ajax_establish_remote_connection' ) ); + add_action( 'wp_ajax_nopriv_wpmdb_respond_initiate_migration', array( $this, 'ajax_respond_initiate_migration' ) ); + add_action( 'wp_ajax_nopriv_wpmdb_process_chunk', array( $this, 'ajax_process_chunk' ) ); + add_action( 'wp_ajax_nopriv_wpmdb_prepare_table_migration', array( $this, 'ajax_prepare_table_migration' ) ); + add_action( 'wp_ajax_nopriv_wpmdb_finalize_backup', array( $this, 'ajax_finalize_backup' ) ); + add_action( 'wp_ajax_nopriv_wpmdb_process_pull_request', array( $this, 'ajax_process_pull_request' ) ); + + // Take over the update check + add_filter( 'site_transient_update_plugins', array( $this, 'site_transient_update_plugins' ) ); + + // Add an extra row to the plugin screen + add_action( 'after_plugin_row_' . $this->plugin_basename, array( $this, 'plugin_row' ), 11 ); + + // Seen when the user clicks "view details" on the plugin listing page + add_action( 'install_plugins_pre_plugin-information', array( $this, 'plugin_update_popup' ) ); + + // Adds a custom error message to the plugin install page if required (licence expired / invalid) + add_filter( 'http_response', array( $this, 'verify_download' ), 10, 3 ); + + // Add some custom JS into the WP admin pages + add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_plugin_update_script' ) ); + + // Add some custom CSS into the WP admin pages + add_action( 'admin_head-plugins.php', array( $this, 'add_plugin_update_styles' ) ); + + $this->template_dir = $this->plugin_dir_path . 'template' . DS; + + $absolute_path = rtrim( ABSPATH, '\\/' ); + $site_url = rtrim( site_url( '', 'http' ), '\\/' ); + $home_url = rtrim( home_url( '', 'http' ), '\\/' ); + if ( $site_url != $home_url ) { + $difference = str_replace( $home_url, '', $site_url ); + $absolute_path = rtrim( substr( ABSPATH, 0, -strlen( $difference ) ), '\\/' ); + } + $this->absolute_root_file_path = $absolute_path; + + $this->accepted_fields = array( + 'action', + 'save_computer', + 'gzip_file', + 'connection_info', + 'replace_old', + 'replace_new', + 'table_migrate_option', + 'select_tables', + 'replace_guids', + 'exclude_spam', + 'exclude_revisions', + 'save_migration_profile', + 'save_migration_profile_option', + 'create_new_profile', + 'create_backup', + 'remove_backup', + ); + + $this->default_profile = array( + 'action' => 'savefile', + 'save_computer' => '1', + 'gzip_file' => '1', + 'table_migrate_option' => 'migrate_only_with_prefix', + 'replace_guids' => '1', + 'default_profile' => true, + 'name' => '', + 'select_tables' => array(), + ); + + $this->plugin_base = 'tools.php?page=wp-migrate-db-pro'; + + // this is how many DB rows are processed at a time, allow devs to change this value + $this->rows_per_segment = apply_filters( 'wpmdb_rows_per_segment', $this->rows_per_segment ); + + // testing only - if uncommented, will always check for plugin updates + //delete_site_transient( 'update_plugins' ); + //delete_site_transient( 'wpmdb_upgrade_data' ); + //delete_site_transient( 'wpmdb_licence_response' ); + } + + function verify_download( $response, $args, $url ) { + $download_url = $this->get_plugin_update_download_url(); + + if ( $url != $download_url || 402 != $response['response']['code'] ) { + return $response; + } + + // The $response['body'] is blank but output is actually saved to a file in this case + $data = @file_get_contents( $response['filename'] ); + + if ( !$data ) { + return new WP_Error( 'wpmdbpro_download_error_empty', 'Error retrieving download from deliciousbrain.com. Please try again or download manually from My Account.' ); + } + + $decoded_data = json_decode( $data, true ); + + // Can't decode the JSON errors, so just barf it all out + if ( !isset( $decoded_data['errors'] ) || !$decoded_data['errors'] ) { + return new WP_Error( 'wpmdbpro_download_error_raw', $data ); + } + + foreach ( $decoded_data['errors'] as $key => $msg ) { + return new WP_Error( 'wpmdbpro_' . $key, $msg ); + } + } + + function check_licence( $licence_key ) { + // testing only 1st line = valid licence 2nd line = not valid licence + // return json_encode( array( 'ok' => 'ok' ) ); + // return json_encode( array( 'errors' => array( 'standard' => 'oh no! licence is not working.') ) ); + if( empty( $licence_key ) ) { + return false; + } + $args = array( + 'licence_key' => $licence_key, + 'site_url' => site_url( '', 'http' ), + ); + + $response = $this->dbrains_api_request( 'check_support_access', $args ); + set_site_transient( 'wpmdb_licence_response', $response, $this->transient_timeout ); + return $response; + } + + function ajax_check_licence() { + $licence = ( empty( $_POST['licence_key'] ) ? $this->settings['licence'] : $_POST['licence_key'] ); + $response = $this->check_licence( $licence ); + echo $response; + exit; + } + + function ajax_activate_licence() { + $args = array( + 'licence_key' => $_POST['licence_key'], + 'site_url' => site_url( '', 'http' ) + ); + + $response = $this->dbrains_api_request( 'activate_licence', $args ); + + echo $response; + + $response = json_decode( $response, true ); + + if ( $response && !isset( $response['errors'] ) ) { + $this->settings['licence'] = $_POST['licence_key']; + $this->settings['licence_email'] = $response['email']; + update_site_option( 'wpmdb_settings', $this->settings ); + } + + exit; + } + + function get_dbrains_api_url( $request, $args = array() ) { + $url = $this->dbrains_api_url; + $args['request'] = $request; + $url = add_query_arg( $args, $url ); + return $url; + } + + function dbrains_api_request( $request, $args = array() ) { + $url = $this->get_dbrains_api_url( $request, $args ); + $response = wp_remote_get( $url, array( + 'timeout' => 30, + 'blocking' => true + ) ); + + if ( is_wp_error( $response ) || (int) $response['response']['code'] < 200 || (int) $response['response']['code'] > 399 ) { + return json_encode( array( 'errors' => array( 'connection_failed' => $url . 'Could not connect to deliciousbrains.com.' ) ) ); + } + + return $response['body']; + } + + function display_errors() { + if ( ! empty( $this->error ) ) { + echo $this->error; + $this->error = ''; + return true; + } + return false; + } + + function get_db_object(){ + $db = new mysqli( DB_HOST, DB_USER, DB_PASSWORD, DB_NAME ); + $db->set_charset( DB_CHARSET ); + return $db; + } + + function remote_post( $url, $data, $scope, $args = array() ) { + set_time_limit( 0 ); + + $args = wp_parse_args( $args, array( + 'timeout' => 60 * 20, + 'blocking' => true + ) ); + + $args['method'] = 'POST'; + $args['body'] = $data; + + $response = wp_remote_post( $url, $args ); + + if ( is_wp_error( $response ) ) { + if( isset( $response->errors['http_request_failed'][0] ) && strstr( $response->errors['http_request_failed'][0], 'timed out' ) ) { + $this->error = 'The connection to the remote server has timed out, the changes have been successfully rolled back. (#134 - scope: ' . $scope . ')'; + } + else { + $this->error = 'The connection failed, please try connecting over http instead of https. (#121 - scope: ' . $scope . ')'; + } + $this->log_error( $this->error, $response ); + return false; + } + elseif ( (int) $response['response']['code'] < 200 || (int) $response['response']['code'] > 399 ) { + $this->error = 'Unable to connect to the remote server, please check the connection details (#129 - scope: ' . $scope . ')'; + $this->log_error( $this->error, $response ); + return false; + } + elseif ( $response['body'] === '0' ) { + $this->error = 'WP Migrate DB Pro does not seem to be installed or active on the remote site. (#131 - scope: ' . $scope . ')'; + $this->log_error( $this->error, $response ); + return false; + } + + return $response['body']; + } + + function log_error( $wpmdb_error, $additional_error_var = false ){ + $error_header = "********************************************\n****** Log date: " . date( 'Y/m/d H:i:s' ) . " ******\n********************************************\n\n"; + $error = $error_header . "WPMDB Error: " . $wpmdb_error . "\n\n"; + if( $additional_error_var !== false ){ + $error .= print_r( $additional_error_var, true ) . "\n\n"; + } + file_put_contents( $this->plugin_dir_path . 'debug.log', $error, FILE_APPEND ); + } + + function get_sql_dump_file_name( $type = 'migrate' ) { + return $this->upload_dir . DS . sanitize_title_with_dashes( DB_NAME ) . '-' . $type . '-' . $_POST['datetime'] . '.sql'; + } + + function parse_migration_form_data( $data ) { + parse_str( $data, $form_data ); + $form_data = array_intersect_key( $form_data, array_flip( $this->accepted_fields ) ); + unset( $form_data['replace_old'][0] ); + unset( $form_data['replace_new'][0] ); + return $form_data; + } + + function plugin_action_links( $links ) { + $link = sprintf( '%s', $this->plugin_base, __( 'Settings', 'wp-migrate-db-pro' ) ); + array_unshift( $links, $link ); + return $links; + } + + function ajax_clear_log() { + if( file_exists( $this->plugin_dir_path . 'debug.log' ) ) { + file_put_contents( $this->plugin_dir_path . 'debug.log', '' ); + } + exit; + } + + function ajax_get_log() { + $this->output_diagnostic_info(); + $this->output_log_file(); + exit; + } + + function output_log_file() { + if( file_exists( $this->plugin_dir_path . 'debug.log' ) ) { + echo file_get_contents( $this->plugin_dir_path . 'debug.log' ); + } + } + + function output_diagnostic_info() { + _e( 'WordPress', 'wp-app-store' ); echo ': '; + if ( is_multisite() ) echo 'WPMU'; else echo 'WP'; echo bloginfo('version'); + echo "\r\n"; + + _e( 'Web Server', 'wp-app-store' ); echo ': '; + echo $_SERVER['SERVER_SOFTWARE']; + echo "\r\n"; + + _e( 'PHP', 'wp-app-store' ); echo ': '; + if ( function_exists( 'phpversion' ) ) echo esc_html( phpversion() ); + echo "\r\n"; + + _e( 'MySQL', 'wp-app-store' ); echo ': '; + if ( function_exists( 'mysql_get_server_info' ) ) echo esc_html( mysql_get_server_info() ); + echo "\r\n"; + + _e( 'max_allowed_packet_size', 'wp-app-store' ); echo ': '; + echo $this->get_max_allowed_packet_size(); + echo "\r\n"; + + _e( 'WP Memory Limit', 'wp-app-store' ); echo ': '; + echo WP_MEMORY_LIMIT; + echo "\r\n"; + + _e( 'WPMDB Bottleneck', 'wp-app-store' ); echo ': '; + echo $this->get_bottleneck(); + echo "\r\n"; + + _e( 'Debug Mode', 'wp-app-store' ); echo ': '; + if ( defined('WP_DEBUG') && WP_DEBUG ) { echo 'Yes'; } else { echo 'No'; } + echo "\r\n"; + + _e( 'WP Max Upload Size', 'wp-app-store' ); echo ': '; + echo wp_convert_bytes_to_hr( wp_max_upload_size() ); + echo "\r\n"; + + _e( 'PHP Post Max Size', 'wp-app-store' ); echo ': '; + if ( function_exists( 'ini_get' ) ) echo ini_get('post_max_size'); + echo "\r\n"; + + _e( 'PHP Time Limit', 'wp-app-store' ); echo ': '; + if ( function_exists( 'ini_get' ) ) echo ini_get('max_execution_time'); + echo "\r\n"; + + _e( 'fsockopen', 'wp-app-store' ); echo ': '; + if ( function_exists( 'fsockopen' ) ) { + _e('Enabled', 'wp-app-store' ); + } else { + _e( 'Disabled', 'wp-app-store' ); + } + echo "\r\n"; + + _e( 'cURL', 'wp-app-store' ); echo ': '; + if ( function_exists( 'curl_init' ) ) { + _e('Enabled', 'wp-app-store' ); + } else { + _e( 'Disabled', 'wp-app-store' ); + } + echo "\r\n"; + echo "\r\n"; + + _e( 'Active Plugins', 'wp-app-store' ); echo ":\r\n"; + + $active_plugins = (array) get_option( 'active_plugins', array() ); + + if ( is_multisite() ) + $active_plugins = array_merge( $active_plugins, get_site_option( 'active_sitewide_plugins', array() ) ); + + foreach ( $active_plugins as $plugin ) { + $plugin_data = @get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ); + if ( empty( $plugin_data['Name'] ) ) continue; + echo $plugin_data['Name'] . ' (v' . $plugin_data['Version'] . ') ' . __( 'by', 'wp-app-store' ) . ' ' . $plugin_data['AuthorName'] . "\r\n"; + } + + echo "\r\n"; + } + + // After table migration, delete old tables and rename new tables removing the temporarily prefix + function ajax_finalize_backup() { + global $wpdb; + // This particular function can be accessed by non logged in users AND logged in users + if ( ! current_user_can( 'manage_options' ) ) { + if ( ! $this->verify_signature( $_POST, $this->settings['key'] ) ) { + echo $this->invalid_content_verification_error . ' (#123)'; + exit; + } + } + + if ( $_POST['intent'] == 'pull' ) { + $temp_tables = $this->get_tables( 'temp' ); + $sql = ''; + foreach ( $temp_tables as $table ) { + $sql .= 'DROP TABLE IF EXISTS ' . $this->backquote( substr( $table, strlen( $this->temp_prefix ) ) ) . ';'; + $sql .= "\n"; + $sql .= 'RENAME TABLE ' . $this->backquote( $table ) . ' TO ' . $this->backquote( substr( $table, strlen( $this->temp_prefix ) ) ) . ';'; + $sql .= "\n"; + } + // reset the wpmdb options after everything has migrated + $sql .= 'UPDATE `' . $wpdb->prefix . 'options` SET `option_value` =\'' . serialize( $this->settings ) . '\' WHERE `option_name` = \'wpmdb_settings\';'; + $this->process_chunk( $sql ); + } + else { + $data = $_POST; + $data['intent'] = 'pull'; + $data['sig'] = $this->create_signature( $data, $data['key'] ); + $ajax_url = trailingslashit( $_POST['url'] ) . 'wp-admin/admin-ajax.php'; + $this->remote_post( $ajax_url, $data, __FUNCTION__ ); + $this->display_errors(); + } + exit; + } + + function ajax_process_chunk() { + // We need to strip before signature verification, otherwise verification will fail + $_POST['chunk'] = stripslashes( $_POST['chunk'] ); + + if ( !$this->verify_signature( $_POST, $this->settings['key'] ) ) { + echo $this->invalid_content_verification_error . ' (#130)'; + exit; + } + + $this->process_chunk( $_POST['chunk'] ); + exit; + } + + function process_chunk( $chunk ) { + // prepare db + set_time_limit( 0 ); + $db = $this->get_db_object(); + $i = 1; + if ( $db->multi_query( $chunk ) ) { + do { + $i++; + } while ( $db->next_result() ); + } + if ( $db->errno ) { + echo "Error executing statement $i in the following batch of queries.\n"; + echo $chunk . "\n"; + echo $db->error; + } + $db->close(); + } + + function create_signature( $data, $key ) { + if ( isset( $data['sig'] ) ) { + unset( $data['sig'] ); + } + $flat_data = implode( '', $data ); + return base64_encode( hash_hmac( 'sha1', $flat_data, $key, true ) ); + } + + function verify_signature( $data, $key ) { + $temp = $data; + $computed_signature = $this->create_signature( $temp, $key ); + return $computed_signature === $data['sig']; + } + + // This the first AJAX end point when a table is about to be migrated / backed up + function ajax_prepare_table_migration() { + // Check that the user is valid and is allowed to perform a table migration + if ( ! current_user_can( 'manage_options' ) ) { + if ( ! $this->verify_signature( $_POST, $this->settings['key'] ) ) { + echo $this->invalid_content_verification_error . ' (#119)'; + exit; + } + } + + $this->form_data = $this->parse_migration_form_data( $_POST['form_data'] ); + // checks if we're performing a backup, if so, continue with the backup and exit immediately after + if ( $_POST['stage'] == 'backup' && $_POST['intent'] != 'savefile' ) { + // if performing a push we need to backup the REMOTE machine's DB + if ( $_POST['intent'] == 'push' ) { + $data = $_POST; + // flip the intent so we can trigger the else statement below + $data['intent'] = 'pull'; + $ajax_url = trailingslashit( $_POST['url'] ) . 'wp-admin/admin-ajax.php'; + $data['sig'] = $this->create_signature( $data, $data['key'] ); + $this->remote_post( $ajax_url, $data, __FUNCTION__ ); + $this->display_errors(); + } + else { + $sql_dump_file_name = $this->get_sql_dump_file_name( 'backup' ); + if ( isset( $this->form_data['gzip_file'] ) ) { + unset( $this->form_data['gzip_file'] ); + } + $file_created = file_exists( $sql_dump_file_name ); + $this->fp = $this->open( $sql_dump_file_name ); + if ( $file_created == false ) { + $this->db_backup_header(); + } + $this->backup_table( $_POST['table'] ); + $this->display_errors(); + $this->close( $this->fp ); + } + exit; + } + + // Pull and push need to be handled differently for obvious reason, trigger different code depending on the migration intent (push or pull) + if ( $_POST['intent'] == 'push' || $_POST['intent'] == 'savefile' ) { + if ( isset( $_POST['bottleneck'] ) ) { + $this->maximum_chunk_number = floor( $_POST['bottleneck'] / $this->max_insert_string_len ); + } + if ( $_POST['intent'] == 'push' ) { + $this->remote_key = $_POST['key']; + $this->remote_url = $_POST['url']; + } + $sql_dump_file_name = $this->get_sql_dump_file_name(); + + if ( $this->gzip() && isset( $this->form_data['gzip_file'] ) ) { + $sql_dump_file_name .= '.gz'; + } + + if ( $_POST['intent'] == 'savefile' ) { + $this->fp = $this->open( $sql_dump_file_name ); + } + $this->backup_table( $_POST['table'] ); + $this->display_errors(); + if ( $_POST['intent'] == 'savefile' ) { + $this->close( $this->fp ); + } + } + else { + $data = $_POST; + $data['action'] = 'wpmdb_process_pull_request'; + $data['pull_limit'] = $this->get_max_allowed_packet_size(); + if ( isset( $data['sig'] ) ) { + unset( $data['sig'] ); + } + $ajax_url = trailingslashit( $data['url'] ) . 'wp-admin/admin-ajax.php'; + $row_tracker = ''; + $data['sig'] = $this->create_signature( $data, $data['key'] ); + + while ( $row_tracker != -1 ) { + $response = $this->remote_post( $ajax_url, $data, __FUNCTION__ ); + $this->display_errors(); + if ( is_serialized( $response ) ) { + $response = unserialize( $response ); + } + else { + echo $response; + break; + } + $row_tracker = $response['row_tracker']; + $chunk = $response['chunk']; + if ( ! empty( $chunk ) ) { + $this->process_chunk( $chunk ); + } + $data['current_row'] = ( empty( $response['row_tracker'] ) ? 0 : $response['row_tracker'] ); + $data['sig'] = $this->create_signature( $data, $data['key'] ); + } + } + exit; + } + + // Occurs right before the first table is migrated / backed up during the migration process + // Does a quick check to make sure the verification string is valid and also opens / creates files for writing to (if required) + function ajax_initiate_migration() { + $datetime = date('YmdHis'); + if ( $_POST['intent'] == 'savefile' ) { + + $this->form_data = $this->parse_migration_form_data( $_POST['form_data'] ); + + $return = array( + 'code' => 200, + 'message' => 'OK', + 'body' => json_encode( array( 'error' => 0 ) ), + ); + + $_POST['datetime'] = $datetime; + $sql_dump_file_name = $this->get_sql_dump_file_name(); + + if ( $this->gzip() && isset( $this->form_data['gzip_file'] ) ) { + $sql_dump_file_name .= '.gz'; + } + $this->fp = $this->open( $sql_dump_file_name ); + $this->db_backup_header(); + $this->close( $this->fp ); + } + else { // does one last check that our verification string is valid + + $data = array( + 'action' => 'wpmdb_respond_initiate_migration', + 'intent' => $_POST['intent'], + 'form_data' => $_POST['form_data'], + ); + + $data['sig'] = $this->create_signature( $data, $_POST['key'] ); + $ajax_url = trailingslashit( $_POST['url'] ) . 'wp-admin/admin-ajax.php'; + $response = $this->remote_post( $ajax_url, $data, __FUNCTION__ ); + + if ( false === $response ) { + $return = array( 'wpmdb_error' => 1, 'body' => $this->error ); + } + else{ + $return = array( + 'body' => $response + ); + } + + } + + $return['datetime'] = $datetime; + echo json_encode( $return ); + + exit; + } + + // End point for the above AJAX call, ensures that the verification string is valid before continuing with the migration + function ajax_respond_initiate_migration() { + $return = array(); + if ( $this->verify_signature( $_POST, $this->settings['key'] ) ) { + if ( isset( $this->settings['allow_' . $_POST['intent']] ) && $this->settings['allow_' . $_POST['intent']] == true ) { + $return['error'] = 0; + } + else { + $return['error'] = 1; + $return['message'] = 'The connection succeeded but the remote site is configured to reject ' . $_POST['intent'] . ' connections. You can change this in the "settings" tab on the remote site. (#110)'; + } + } + else { + $return['error'] = 1; + $return['message'] = $this->invalid_content_verification_error . ' (#111)'; + } + echo json_encode( $return ); + + exit; + } + + function ajax_save_profile() { + $profile = $this->parse_migration_form_data( $_POST['profile'] ); + if ( isset( $profile['save_migration_profile_option'] ) && $profile['save_migration_profile_option'] == 'new' ) { + $profile['name'] = $profile['create_new_profile']; + $this->settings['profiles'][] = $profile; + } + else { + $key = $profile['save_migration_profile_option']; + $name = $this->settings['profiles'][$key]['name']; + $this->settings['profiles'][$key] = $profile; + $this->settings['profiles'][$key]['name'] = $name; + } + update_site_option( 'wpmdb_settings', $this->settings ); + echo count( $this->settings['profiles'] ) - 1; + exit; + } + + function ajax_save_setting() { + $this->settings[$_POST['setting']] = ( $_POST['checked'] == 'false' ? false : true ); + update_site_option( 'wpmdb_settings', $this->settings ); + exit; + } + + function ajax_delete_migration_profile() { + $key = $_POST['profile_id']; + if ( isset( $this->settings['profiles'][$key] ) ) { + unset( $this->settings['profiles'][$key] ); + update_site_option( 'wpmdb_settings', $this->settings ); + } + else { + echo '-1'; + } + exit; + } + + function ajax_reset_api_key() { + $this->settings['key'] = $this->generate_key(); + update_site_option( 'wpmdb_settings', $this->settings ); + printf( "%s\n%s", site_url( '', 'https' ), $this->settings['key'] ); + exit; + } + + // AJAX endpoint for when the user pastes into the connection info box (or when they click "connect") + // Responsible for contacting the remote website and retrieving info and testing the verification string + function ajax_prepare_remote_connection() { + $data = array( + 'action' => 'wpmdb_establish_remote_connection', + 'intent' => $_POST['intent'] + ); + + $data['sig'] = $this->create_signature( $data, $_POST['key'] ); + $ajax_url = trailingslashit( $_POST['url'] ) . 'wp-admin/admin-ajax.php'; + $response = $this->remote_post( $ajax_url, $data, __FUNCTION__, array( 'timeout' => 5 ) ); + + $return = $response; + if ( false === $response ) { + $return = array( 'wpmdb_error' => 1, 'body' => $this->error . ' Try again?' ); + } + + $response = json_decode( $response, true ); + + if ( isset( $response['error'] ) && $response['error'] == 1 ) { + $return = array( 'wpmdb_error' => 1, 'body' => $response['message'] ); + } + + echo json_encode( $return ); + + exit; + } + + // AJAX end point for the above AJAX call, returns table information, absolute file path, table prefix, etc + function ajax_establish_remote_connection() { + global $wpdb; + $return = array(); + if ( $this->verify_signature( $_POST, $this->settings['key'] ) ) { + if ( isset( $this->settings['allow_' . $_POST['intent']] ) && $this->settings['allow_' . $_POST['intent']] == true ) { + $return['tables'] = $this->get_tables(); + $return['table_sizes'] = $this->get_table_sizes(); + $return['path'] = $this->absolute_root_file_path; + $return['url'] = home_url(); + $return['prefix'] = $wpdb->prefix; + $return['bottleneck'] = $this->get_bottleneck(); + $return['error'] = 0; + } + else { + $return['error'] = 1; + $return['message'] = 'The connection succeeded but the remote site is configured to reject ' . $_POST['intent'] . ' connections. You can change this in the "settings" tab on the remote site. (#122) Try again?'; + } + } + else { + $return['error'] = 1; + $return['message'] = $this->invalid_content_verification_error . ' (#120) Try again?'; + } + echo json_encode( $return ); + + exit; + } + + // Utility debugging function + function printer( $debug ) { + echo '
    ' . print_r( $debug, true ) . '
    '; + } + + // Generates our secret key + function generate_key() { + $keyset = 'abcdefghijklmnopqrstuvqxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/'; + $key = ''; + for ( $i = 0; $i < 32; $i++ ) { + $key .= substr( $keyset, rand( 0, strlen( $keyset ) -1 ), 1 ); + } + return $key; + } + + // Get only the table beginning with our DB prefix or emporary prefix, also skip views + function get_tables( $scope = 'regular' ) { + global $wpdb; + $prefix = ( $scope == 'temp' ? $this->temp_prefix : $wpdb->prefix ); + $tables = $wpdb->get_results( 'SHOW FULL TABLES', ARRAY_N ); + foreach ( $tables as $table ) { + if ( 0 !== strpos( $table[0], $prefix ) || $table[1] == 'VIEW' ) { + continue; + } + $clean_tables[] = $table[0]; + } + return $clean_tables; + } + + // Retrieves the specified profile, if -1, returns the default profile + function get_profile( $profile_id ) { + if ( $profile_id == '-1' || ! isset( $this->settings['profiles'][$profile_id] ) ) { + return $this->default_profile; + } + return $this->settings['profiles'][$profile_id]; + } + + function get_table_sizes() { + global $wpdb; + $results = $wpdb->get_results( $wpdb->prepare( + 'SELECT TABLE_NAME AS "table", + ROUND((data_length + index_length)/1024,0) AS "size" + FROM information_schema.TABLES + WHERE information_schema.TABLES.table_schema="%s"', DB_NAME + ), ARRAY_A + ); + + $return = array(); + + foreach ( $results as $result ) { + $return[$result['table']] = $result['size']; + } + + return $return; + } + + function template( $template ) { + include $this->template_dir . $template . '.php'; + } + + function get_post_max_size() { + $val = trim( ini_get( 'post_max_size' ) ); + $last = strtolower( $val[ strlen( $val ) - 1 ] ); + switch ( $last ) { + case 'g': + $val *= 1024; + case 'm': + $val *= 1024; + case 'k': + $val *= 1024; + } + return $val; + } + + function get_max_allowed_packet_size() { + global $wpdb; + $size = $wpdb->get_var( 'select VARIABLE_VALUE from information_schema.GLOBAL_VARIABLES where VARIABLE_NAME = \'max_allowed_packet\'' ); + return $size; + } + + function get_bottleneck() { + return min( $this->get_post_max_size(), $this->get_max_allowed_packet_size() ); + } + + function ajax_process_pull_request() { + if ( ! $this->verify_signature( $_POST, $this->settings['key'] ) ) { + echo $this->invalid_content_verification_error . ' (#124)'; + exit; + } + $this->maximum_chunk_number = floor( $_POST['pull_limit'] / $this->max_insert_string_len ); + $this->backup_table( $_POST['table'] ); + $this->display_errors(); + exit; + } + + function options_page() { + ?> + +
    + +

    Migrate DB Pro

    + + get_new_beta_version_msg() ) { + echo '

    ', $msg, '

    '; + } + ?> + +
    + + + + 1 profile saved + if ( ! empty( $this->settings['profiles'] ) && ! isset( $_GET['wpmdb-profile'] ) ) { + $this->template( 'profile' ); + } + else { + if ( isset( $_POST['import-db'] ) ) { + $this->import_db(); + } + $this->template( 'migrate' ); + } + + $this->template( 'settings' ); + + $this->template( 'help' ); + ?> + +
    + +
    + form_data['replace_old']; + $replace = $this->form_data['replace_new']; + $new = str_replace( $search, $replace, $subject, $count ); + return $new; + } + + /** + * Taken partially from phpMyAdmin and partially from + * Alain Wolf, Zurich - Switzerland + * Website: http://restkultur.ch/personal/wolf/scripts/db_backup/ + * Modified by Scott Merrill (http://www.skippy.net/) + * to use the WordPress $wpdb object + * + * @param string $table + * @return void + */ + function backup_table( $table ) { + global $wpdb; + set_time_limit( 0 ); + + if ( empty( $this->form_data ) ) { + $this->form_data = $this->parse_migration_form_data( $_POST['form_data'] ); + } + + $temp_prefix = $this->temp_prefix; + + $table_structure = $wpdb->get_results( "DESCRIBE $table" ); + if ( ! $table_structure ) { + $this->error = 'Failed to retrieve table structure, please ensure your database is online. (#125)'; + return false; + } + + $current_row = -1; + if ( isset( $_POST['current_row'] ) ) { + $current_row = $_POST['current_row']; + } + + if ( $current_row == -1 ) { + // Add SQL statement to drop existing table + if ( $this->form_data['action'] == 'savefile' || $_POST['stage'] == 'backup' ) { + $this->stow( "\n\n" ); + $this->stow( "#\n" ); + $this->stow( "# " . sprintf( __( 'Delete any existing table %s', 'wp-migrate-db-pro' ), $this->backquote( $table ) ) . "\n" ); + $this->stow( "#\n" ); + $this->stow( "\n" ); + $this->stow( "DROP TABLE IF EXISTS " . $this->backquote( $table ) . ";\n" ); + } + else { + $this->stow( "DROP TABLE IF EXISTS " . $this->backquote( $temp_prefix . $table ) . ";\n" ); + } + + // Table structure + // Comment in SQL-file + if ( $this->form_data['action'] == 'savefile' || $_POST['stage'] == 'backup' ) { + $this->stow( "\n\n" ); + $this->stow( "#\n" ); + $this->stow( "# " . sprintf( __( 'Table structure of table %s', 'wp-migrate-db-pro' ), $this->backquote( $table ) ) . "\n" ); + $this->stow( "#\n" ); + $this->stow( "\n" ); + } + + $create_table = $wpdb->get_results( "SHOW CREATE TABLE $table", ARRAY_N ); + if ( false === $create_table ) { + $this->error = 'Failed to generate the create table query, please ensure your database is online. (#126)'; + return false; + } + + if ( $this->form_data['action'] != 'savefile' && $_POST['stage'] != 'backup' ) { + $create_table[0][1] = str_replace( 'CREATE TABLE `', 'CREATE TABLE `' . $temp_prefix, $create_table[0][1] ); + } + + $this->stow( $create_table[0][1] . ' ;' ); + + // Comment in SQL-file + if ( $this->form_data['action'] == 'savefile' || $_POST['stage'] == 'backup' ) { + $this->stow( "\n\n" ); + $this->stow( "#\n" ); + $this->stow( '# ' . sprintf( __( 'Data contents of table %s', 'wp-migrate-db-pro' ), $this->backquote( $table ) ) . "\n" ); + $this->stow( "#\n" ); + } + } + + // $defs = mysql defaults, looks up the default for that paricular column, used later on to prevent empty inserts values for that column + // $ints = holds a list of the possible integar types so as to not wrap them in quotation marks later in the insert statements + $defs = array(); + $ints = array(); + foreach ( $table_structure as $struct ) { + if ( ( 0 === strpos( $struct->Type, 'tinyint' ) ) || + ( 0 === strpos( strtolower( $struct->Type ), 'smallint' ) ) || + ( 0 === strpos( strtolower( $struct->Type ), 'mediumint' ) ) || + ( 0 === strpos( strtolower( $struct->Type ), 'int' ) ) || + ( 0 === strpos( strtolower( $struct->Type ), 'bigint' ) ) ) { + $defs[strtolower( $struct->Field )] = ( null === $struct->Default ) ? 'NULL' : $struct->Default; + $ints[strtolower( $struct->Field )] = "1"; + } + } + + // Batch by $row_inc + + $row_inc = $this->rows_per_segment; + $row_start = 0; + if ( $current_row != -1 ) { + $row_start = $current_row; + } + + $this->row_tracker = $row_start; + + // \x08\\x09, not required + $search = array( "\x00", "\x0a", "\x0d", "\x1a" ); + $replace = array( '\0', '\n', '\r', '\Z' ); + + $query_size = 0; + + $table_name = $table; + + if ( $this->form_data['action'] != 'savefile' && $_POST['stage'] != 'backup' ) { + $table_name = $temp_prefix . $table; + } + + foreach( $table_structure as $col ){ + $field_set[] = $this->backquote( $col->Field ); + } + + $fields = implode( ', ', $field_set ); + + $insert_buffer = $insert_query_template = "INSERT INTO " . $this->backquote( $table_name ) . " ( " . $fields . ") VALUES\n"; + + do { + $where = ''; + if ( isset( $this->form_data['exclude_spam'] ) && $wpdb->comments == $table ) { + $where = ' WHERE comment_approved != "spam"'; + } elseif ( isset( $this->form_data['exclude_revisions'] ) && $wpdb->posts == $table ) { + $where = ' WHERE post_type != "revision"'; + } + + $table_data = $wpdb->get_results( "SELECT * FROM $table $where LIMIT {$row_start}, {$row_inc}" ); + + if ( $table_data ) { + foreach ( $table_data as $row ) { + ++$this->row_tracker; + $values = array(); + foreach ( $row as $key => $value ) { + if ( isset( $ints[strtolower( $key )] ) && $ints[strtolower( $key )] ) { + // make sure there are no blank spots in the insert syntax, + // yet try to avoid quotation marks around integers + $value = ( null === $value || '' === $value ) ? $defs[strtolower( $key )] : $value; + $values[] = ( '' === $value ) ? "''" : $value; + } else { + if ( null === $value ) { + $values[] = 'NULL'; + } + else { + if ( is_serialized( $value ) && false !== ( $data = @unserialize( $value ) ) ) { + if ( is_array( $data ) ) { + if ( $_POST['stage'] != 'backup' ) { + array_walk_recursive( $data, array( $this, 'replace_array_values' ) ); + } + } + elseif ( is_string( $data ) ) { + if ( $_POST['stage'] != 'backup' ) { + $data = $this->apply_replaces( $data, true ); + } + } + + $value = serialize( $data ); + } + // Skip replacing GUID if the option is set + elseif ( 'guid' != $key || ( isset( $this->form_data['replace_guids'] ) && $wpdb->posts == $table ) ) { + if ( $_POST['stage'] != 'backup' ) { + $value = $this->apply_replaces( $value ); + } + } + + $values[] = "'" . str_replace( $search, $replace, $this->sql_addslashes( $value ) ) . "'"; + } + } + } + + $insert_line = '(' . implode( ', ', $values ) . '),'; + $insert_line .= "\n"; + + if ( ( $query_size + strlen( $insert_line ) ) > $this->max_insert_string_len && $insert_buffer != $insert_query_template ) { + $insert_buffer = rtrim( $insert_buffer, "\n," ); + $insert_buffer .= " ;\n"; + $this->buffer_full = true; + $this->stow( $insert_buffer ); + $insert_buffer = $insert_query_template; + $query_size = 0; + } + + $this->buffer_full = false; + + $insert_buffer .= $insert_line; + $query_size += strlen( $insert_line ); + + } + $row_start += $row_inc; + + if ( $insert_buffer != $insert_query_template ) { + $insert_buffer = rtrim( $insert_buffer, "\n," ); + $insert_buffer .= " ;\n"; + $this->stow( $insert_buffer ); + $insert_buffer = $insert_query_template; + $query_size = 0; + } + + } + } while ( count( $table_data ) > 0 ); + + // Create footer/closing comment in SQL-file + if ( $this->form_data['action'] == 'savefile' || $_POST['stage'] == 'backup' ) { + $this->stow( "\n" ); + $this->stow( "#\n" ); + $this->stow( "# " . sprintf( __( 'End of data contents of table %s', 'wp-migrate-db-pro' ), $this->backquote( $table ) ) . "\n" ); + $this->stow( "# --------------------------------------------------------\n" ); + $this->stow( "\n" ); + } + + // required for pull, tells the remote machine to stop sending pull requests + if ( isset( $_POST['intent'] ) && $_POST['intent'] == 'pull' && $_POST['stage'] != 'backup' ) { + $this->row_tracker = -1; + $this->transfer_chunk(); + } + + // required for push, sends any remaining data left over in the current_chunk buffer to the remote machine + if ( $this->form_data['action'] != 'savefile' && ! empty( $this->current_chunk ) && $_POST['stage'] != 'backup' ) { + $this->transfer_chunk(); + } + + } // end backup_table() + + function replace_array_values( &$value, $key ) { + if ( !is_string( $value ) ) return; + $value = $this->apply_replaces( $value, true ); + } + + function db_backup_header() { + $this->stow( "# " . __( 'WordPress MySQL database migration', 'wp-migrate-db-pro' ) . "\n", false ); + $this->stow( "#\n", false ); + $this->stow( "# " . sprintf( __( 'Generated: %s', 'wp-migrate-db-pro' ), date( "l j. F Y H:i T" ) ) . "\n", false ); + $this->stow( "# " . sprintf( __( 'Hostname: %s', 'wp-migrate-db-pro' ), DB_HOST ) . "\n", false ); + $this->stow( "# " . sprintf( __( 'Database: %s', 'wp-migrate-db-pro' ), $this->backquote( DB_NAME ) ) . "\n", false ); + $this->stow( "# --------------------------------------------------------\n\n", false ); + } + + function gzip() { + return function_exists( 'gzopen' ); + } + + function open( $filename = '', $mode = 'a' ) { + if ( '' == $filename ) return false; + if ( $this->gzip() && isset( $this->form_data['gzip_file'] ) ) + $fp = gzopen( $filename, $mode ); + else + $fp = fopen( $filename, $mode ); + return $fp; + } + + function close( $fp ) { + if ( $this->gzip() && isset( $this->form_data['gzip_file'] ) ) gzclose( $fp ); + else fclose( $fp ); + } + + function stow( $query_line, $replace = true ) { + if ( $this->form_data['action'] == 'savefile' || $_POST['stage'] == 'backup' ) { + if ( $this->gzip() && isset( $this->form_data['gzip_file'] ) ) { + if ( ! @gzwrite( $this->fp, $query_line ) ) { + $this->error = 'Failed to write the gzipped SQL data to the file. (#127)'; + return false; + } + } + else { + if ( false === @fwrite( $this->fp, $query_line ) ) { + $this->error = 'Failed to write the SQL data to the file. (#128)'; + return false; + } + } + } + else { + $this->current_chunk .= $query_line; + ++$this->current_chunk_number; + if ( $this->current_chunk_number == $this->maximum_chunk_number ) { + $this->transfer_chunk(); + } + } + } + + // Called in the $this->stow function once our chunk buffer is full, will transfer the SQL to the remote server for importing + function transfer_chunk() { + if ( $_POST['intent'] == 'pull' ) { + if ( $this->buffer_full === true ) { + --$this->row_tracker; + } + $return = array( + 'row_tracker' => $this->row_tracker, + 'chunk' => $this->current_chunk, + ); + echo serialize( $return ); + exit; + } + + $data = array( + 'action' => 'wpmdb_process_chunk', + 'chunk' => $this->current_chunk, + 'table' => $_POST['table'] + ); + + $data['sig'] = $this->create_signature( $data, $_POST['key'] ); + + $ajax_url = trailingslashit( $this->remote_url ) . 'wp-admin/admin-ajax.php'; + $this->remote_post( $ajax_url, $data, __FUNCTION__ ); + $this->display_errors(); + + // reset our chunk values back to the default + $this->current_chunk_number = 0; + $this->current_chunk = ''; + } + + /** + * Add backquotes to tables and db-names in + * SQL queries. Taken from phpMyAdmin. + */ + function backquote( $a_name ) { + if ( !empty( $a_name ) && $a_name != '*' ) { + if ( is_array( $a_name ) ) { + $result = array(); + reset( $a_name ); + while ( list( $key, $val ) = each( $a_name ) ) + $result[$key] = '`' . $val . '`'; + return $result; + } else { + return '`' . $a_name . '`'; + } + } else { + return $a_name; + } + } + + /** + * Better addslashes for SQL queries. + * Taken from phpMyAdmin. + */ + function sql_addslashes( $a_string = '', $is_like = false ) { + if ( $is_like ) $a_string = str_replace( '\\', '\\\\\\\\', $a_string ); + else $a_string = str_replace( '\\', '\\\\', $a_string ); + return str_replace( '\'', '\\\'', $a_string ); + } + + function admin_menu() { + if ( function_exists( 'add_management_page' ) ) { + $hook_suffix = add_management_page( 'Migrate DB Pro', 'Migrate DB Pro', 'update_core', 'wp-migrate-db-pro', array( $this, 'options_page' ) ); + } + + add_action( 'load-' . $hook_suffix , array( $this, 'load_assets' ) ); + } + + function load_assets() { + if ( isset( $_GET['download'] ) && $_GET['download'] ) { + $this->download_file(); + } + + $src = plugins_url( 'asset/css/styles.css', dirname( __FILE__ ) ); + wp_enqueue_style( 'wp-migrate-db-pro-styles', $src ); + $src = plugins_url( 'asset/js/script.js', dirname( __FILE__ ) ); + wp_enqueue_script( 'wp-migrate-db-pro-script', $src, array( 'jquery' ), false, true ); + + // PressTrends + $this->presstrends(); + } + + function download_file() { + // dont need to check for user permissions as our 'add_management_page' already takes care of this + set_time_limit( 0 ); + + if ( ! is_numeric( $_GET['download'] ) ){ + exit; + } + + $filename = sanitize_title_with_dashes( DB_NAME ) . '-migrate-' . $_GET['download'] . '.sql'; + $diskfile = $this->upload_dir . DS . $filename ; + + if ( isset( $_GET['gzip'] ) ) { + $diskfile .= '.gz'; + $filename .= '.gz'; + } + + if ( file_exists( $diskfile ) ) { + header( 'Content-Description: File Transfer' ); + header( 'Content-Type: application/octet-stream' ); + header( 'Content-Length: ' . filesize( $diskfile ) ); + header( 'Content-Disposition: attachment; filename=' . $filename ); + $success = readfile( $diskfile ); + unlink( $diskfile ); + exit; + } + else { + wp_die( "Could not find the file to download:
    $diskfile." ); + } + } + + function admin_head_connection_info() { + global $table_prefix; + ?> + + Name ); + } else { + $theme_data = get_theme_data( get_stylesheet_directory() . '/style.css' ); + $theme_name = $theme_data['Name']; + } + + $plugin_name = '&'; + foreach ( get_plugins() as $plugin_info ) { + $plugin_name .= $plugin_info['Name'] . '&'; + } + // CHANGE __FILE__ PATH IF LOCATED OUTSIDE MAIN PLUGIN FILE + $plugin_data = get_plugin_data( $this->plugin_file_path ); + $posts_with_comments = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->posts WHERE post_type='post' AND comment_count > 0" ); + $data = array( + 'url' => stripslashes( str_replace( array( 'http://', '/', ':' ), '', site_url() ) ), + 'posts' => $count_posts->publish, + 'pages' => $count_pages->publish, + 'comments' => $comments_count->total_comments, + 'approved' => $comments_count->approved, + 'spam' => $comments_count->spam, + 'pingbacks' => $wpdb->get_var( "SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_type = 'pingback'" ), + 'post_conversion' => ( $count_posts->publish > 0 && $posts_with_comments > 0 ) ? number_format( ( $posts_with_comments / $count_posts->publish ) * 100, 0, '.', '' ) : 0, + 'theme_version' => $plugin_data['Version'], + 'theme_name' => $theme_name, + 'site_name' => str_replace( ' ', '', get_bloginfo( 'name' ) ), + 'plugins' => count( get_option( 'active_plugins' ) ), + 'plugin' => urlencode( $plugin_name ), + 'wpversion' => get_bloginfo( 'version' ), + ); + + foreach ( $data as $k => $v ) { + $url .= $k . '/' . $v . '/'; + } + wp_remote_get( $url ); + set_transient( 'presstrends_cache_data', $data, $this->transient_timeout ); + } + } + + function get_new_beta_version_msg() { + $latest = $this->get_beta_version_data(); + if ( !isset( $latest['version'] ) || !isset( $latest['msg'] ) ) return false; + + $plugin = get_plugin_data( $this->plugin_file_path, false, false ); + + if ( !isset( $plugin['Version'] ) ) return false; + + if ( version_compare( $plugin['Version'], $latest['version'], '>=' ) ) { + return false; + } + + return $latest['msg']; + } + + function get_beta_version_data() { + $key = 'wpmdb_beta_notice'; + $info = get_site_transient( $key ); + if ( $info ) return $info; + + $url = 'http://cdn.deliciousbrains.com/beta/data.json'; + $data = wp_remote_get( $url, array( 'timeout' => 30 ) ); + + if ( !is_wp_error( $data ) && 200 == $data['response']['code'] ) { + if ( $info = json_decode( $data['body'], true ) ) { + set_site_transient( $key, $info, $this->transient_timeout ); + return $info; + } + } + + return false; + } + + function get_installed_version() { + if ( !is_admin() ) return false; // get_themes & get_plugins throw an error on the frontend + + $plugins = get_plugins(); + + if ( !isset( $plugins[$this->plugin_basename]['Version'] ) ) { + return false; + } + + return $plugins[$this->plugin_basename]['Version']; + } + + function get_latest_version() { + $data = $this->get_upgrade_data(); + return $data['version']; + } + + function is_licence_expired( $skip_transient_check = false ) { + if( empty( $this->settings['licence'] ) ) { + $settings_link = sprintf( '%s', $this->plugin_base . '#settings', __( 'Settings', 'wp-migrate-db-pro' ) ); + $message = 'To finish activating WP Migrate DB Pro, please go to ' . $settings_link . ' and enter your licence key. + If you don\'t have a licence key, you may + purchase one.'; + return array( 'errors' => array( 'no_licence' => $message ) ); + } + + if( ! $skip_transient_check ) { + $trans = get_site_transient( 'wpmdb_licence_response' ); + if ( false !== $trans ) return json_decode( $trans, true ); + } + + return json_decode( $this->check_licence( $this->settings['licence'] ), true ); + } + + /* + * Shows a message below the plugin on the plugins page when: + * 1. the license hasn't been activated + * 2. when there's an update available but the license is expired + * + * TODO: Implement "Check my license again" link + */ + function plugin_row() { + $licence_response = $this->is_licence_expired(); + $licence_problem = isset( $licence_response['errors'] ); + + $installed_version = $this->get_installed_version(); + $latest_version = $this->get_latest_version(); + + $new_version = ''; + if ( version_compare( $installed_version, $latest_version, '<' ) ) { + $new_version = __( 'There is a new version of WP Migrate DB Pro available.', 'wp-migrate-db-pro' ); + $new_version .= ' '; + $new_version .= sprintf( __( 'View version %s details', 'wp-migrate-db-pro' ), $latest_version ) . '.'; + } + + if ( !$new_version && !empty( $this->settings['licence'] ) ) { + return; + } + + if( empty( $this->settings['licence'] ) ) { + $settings_link = sprintf( '%s', $this->plugin_base . '#settings', __( 'Settings', 'wp-migrate-db-pro' ) ); + if ( $new_version ) { + $message = 'To update, '; + } + else { + $message = 'To finish activating WP Migrate DB Pro, please '; + } + + $message .= 'go to ' . $settings_link . ' and enter your licence key. + If you don\'t have a licence key, you may + purchase one.'; + } + elseif ( $licence_problem ) { + $message = array_shift( $licence_response['errors'] ) . ' Check my license again'; + } + else { + return; + } + ?> + + + +
    +
    +
    +
    + + + + + + + + plugin_slug != $_GET['plugin'] ) return; + + $url = $this->dbrains_api_base . '/content/themes/delicious-brains/update-popup/wp-migrate-db-pro.html'; + $data = wp_remote_get( $url, array( 'timeout' => 30 ) ); + + if ( is_wp_error( $data ) || 200 != $data['response']['code'] ) { + echo '

    Could not retrieve version details. Please try again.

    '; + } + else { + echo $data['body']; + } + + exit; + } + + function get_upgrade_data() { + $info = get_site_transient( 'wpmdb_upgrade_data' ); + if ( $info ) return $info; + + $data = $this->dbrains_api_request( 'upgrade_data', array( 'product_id' => '21') ); + + $data = json_decode( $data, true ); + + /* + We need to set the transient even when there's an error, + otherwise we'll end up making API requests over and over again + and slowing things down big time. + */ + $default_upgrade_data = array( 'version' => $this->get_installed_version() ); + + if ( !$data ) { + set_site_transient( 'wpmdb_upgrade_data', $default_upgrade_data, $this->transient_retry_timeout ); + $this->log_error( 'Error trying to decode JSON upgrade data.' ); + return false; + } + + if ( isset( $data['errors'] ) ) { + set_site_transient( 'wpmdb_upgrade_data', $default_upgrade_data, $this->transient_retry_timeout ); + $this->log_error( 'Error trying to get upgrade data.', $data['errors'] ); + return false; + } + + set_site_transient( 'wpmdb_upgrade_data', $data, $this->transient_timeout ); + return $info; + } + + function site_transient_update_plugins( $trans ) { + if ( !is_admin() ) return $trans; // only need to run this when in the dashboard + + $latest_version = $this->get_latest_version(); + if ( !$latest_version ) return $trans; + + $ut = $this->plugin_basename; + $installed_version = $this->get_installed_version(); + + if ( version_compare( $installed_version, $latest_version, '<' ) ) { + $trans->response[$ut] = new stdClass(); + $trans->response[$ut]->url = $this->dbrains_api_base; + $trans->response[$ut]->slug = $this->plugin_slug; + $trans->response[$ut]->package = $this->get_plugin_update_download_url(); + $trans->response[$ut]->new_version = $latest_version; + $trans->response[$ut]->id = '0'; + } + + return $trans; + } + + function get_plugin_update_download_url() { + $query_args = array( + 'request' => 'download', + 'licence_key' => $this->settings['licence'], + 'site_url' => home_url( '', 'http') + ); + return add_query_arg( $query_args, $this->dbrains_api_url ); + } + + function enqueue_plugin_update_script( $hook ) { + if( 'plugins.php' != $hook ) { + return; + } + + $src = plugins_url( 'asset/js/plugin-update.js', dirname( __FILE__ ) ); + wp_enqueue_script( 'wp-migrate-db-pro-plugin-update-script', $src, array( 'jquery' ), false, true ); + } + + function add_plugin_update_styles() { + ?> + + + +
    +

    Email Support

    +
    + settings['licence'] ) && ! empty( $this->settings['licence'] ) ) : ?> +

    Fetching licence details, please wait...

    + +

    We couldn't find your licence information. Please switch to the settings tab and enter your licence.

    +

    Once completed, you may visit this tab to view your support details.

    + +
    +
    + + array( + 'title' => 'Feature Walkthrough', + 'desc' => 'A brief walkthrough of the WP Migrate DB plugin + showing all of the different options and explaining them.' + ), + 'IFdHIpf6jjc' => array( + 'title' => 'Pulling Live Data Into Your Local Development Environment', + 'desc' => 'This screencast demonstrates how you can pull data from a remote, live + WordPress install and update the data in your local development + environment.' + ), + 'FjTzNqAlQE0' => array( + 'title' => 'Pushing Local Development Data to a Staging Environment', + 'desc' => 'This screencast demonstrates how you can push a local WordPress database + you\'ve been using for development to a staging environment.' + ) + ); + ?> + +
    +

    Videos

    + + + +
      + $video ) : ?> +
    • + + +

      + +

      + +

      +
    • + +
    +
    + +
    +

    Diagnostic Info & Error Log

    + + Clear Error Log +
    + + \ No newline at end of file diff --git a/template/migrate-progress.php b/template/migrate-progress.php new file mode 100644 index 0000000..7cbe394 --- /dev/null +++ b/template/migrate-progress.php @@ -0,0 +1,17 @@ +
    + × +
    +

    Please wait while migration is running...

    +
    +
    +
    Establishing Connection
    + Time Elapsed: 00:00:00 +
    +
    +
    +
    +
    wp_options
    +
    +
    +
    +
    \ No newline at end of file diff --git a/template/migrate.php b/template/migrate.php new file mode 100644 index 0000000..43b415d --- /dev/null +++ b/template/migrate.php @@ -0,0 +1,312 @@ +get_profile( $_GET['wpmdb-profile'] ); +} +else{ + $loaded_profile = $this->default_profile; +} + +$is_default_profile = isset( $loaded_profile['default_profile'] ); +?> + + +
    + +
    + + settings['profiles'] ) > 0 ){ ?> + ← Back to select a saved profile + + +
    + +
      +
    • + +
        +
      • + +
      • + gzip() ) : ?> +
      • + +
      • + +
      +
    • +
    • + +
        +
      • +
      +
    • +
    • + +
        +
      • +
      +
    • +
    + +
    + +
    + +
    + +
    + +
    + +
    + +

    Please enter the connection information above to continue.

    + +
    + +
    +
    +
    Find
    +
    Replace
    +
    + +

    Doesn't look we have any replaces yet, add one?

    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + +
    + + + + + + + +
    + + + + + + + +
    + + + + + + + +
    + +
    + +
    + get_tables(); ?> +
    + +
    +
    Tables
    +
    + +
    + +
      +
    • + +
    • +
    • + +
    • +
    + +
    + +
    + Select All + / + Deselect All + / + Invert Selection +
    +
    +
    + +
    +
    + +
    Advanced Options
    +
    + +
    + +
      +
    • + + + + +
      + Although the WordPress Codex emphasizes + that GUIDs should not be changed, this is limited to sites that are already live. + If the site has never been live, I recommend replacing the GUIDs. For example, you may be + developing a new site locally at dev.somedomain.com and want to + migrate the site live to somedomain.com. +
      +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    + +
    +
    + +
    + + +
    +
      + settings['profiles'] as $key => $profile ){ ?> +
    • + + +
    • + +
    • + + +
    • +
    +
    +
    + +

    + + + +

    + +
    + + settings['profiles'] ) > 0 ){ ?> + ← Back to select a saved profile + + +
    + template( 'migrate-progress' ); + ?> + +
    \ No newline at end of file diff --git a/template/profile.php b/template/profile.php new file mode 100644 index 0000000..f54401a --- /dev/null +++ b/template/profile.php @@ -0,0 +1,9 @@ +
    +

    Would you like to use a saved migration profile?

    + +
    \ No newline at end of file diff --git a/template/settings.php b/template/settings.php new file mode 100644 index 0000000..eeef804 --- /dev/null +++ b/template/settings.php @@ -0,0 +1,45 @@ +
    + + settings['key'] ); + $pull_checked = ( $this->settings['allow_pull'] ? ' checked="checked"' : '' ); + $push_checked = ( $this->settings['allow_push'] ? ' checked="checked"' : '' ); + + $licence_email = ( isset( $this->settings['licence_email'] ) && ! empty( $this->settings['licence_email'] ) ? 'Registered To: ' . $this->settings['licence_email'] : '' ); + $licence = ( isset( $this->settings['licence'] ) && ! empty( $this->settings['licence'] ) ? $this->settings['licence'] : '' ); + ?> + +
    + +
    +
      +
    • + +
    • +
    • + +
    • +
    + + + + +
    + +
    + +
    +

    Your License

    +
    + + +

    +
    + +
    \ No newline at end of file diff --git a/wp-migrate-db-pro.php b/wp-migrate-db-pro.php new file mode 100644 index 0000000..18654ea --- /dev/null +++ b/wp-migrate-db-pro.php @@ -0,0 +1,50 @@ +errors = array(); - $this->upload_dir = ( defined('WP_CONTENT_DIR') ) ? WP_CONTENT_DIR . '/uploads' : ABSPATH . 'wp-content' . DS . 'uploads'; - $this->upload_url = ( defined('WP_CONTENT_URL') ) ? WP_CONTENT_URL . '/uploads' : get_option('siteurl') . '/wp-content/uploads'; - - $this->datetime = date('YmdHis'); - - $this->replaced['serialized']['count'] = 0; - $this->replaced['serialized']['strings'] = ''; - $this->replaced['nonserialized']['count'] = 0; - - add_action( 'admin_menu', array( $this, 'admin_menu' ) ); - add_action( 'wp_ajax_subscribe_submission', array( $this, 'subscribe_submission' ) ); - - $this->handle_request(); - } - - function subscribe_submission() { - $response = wp_remote_post( 'http://bradt.ca/wpmdb-subscribe.php', array( - 'timeout' => 60, - 'body' => $_POST - )); - - if ( is_wp_error( $response ) ) { - echo "Error attempting to save your submission."; - } - else { - echo $response['body']; - } - - die(); // this is required to return a proper result - } - - function handle_request() { - if ( !isset( $_GET['page'] ) || 'wp-migrate-db' != $_GET['page'] ) - return; - - if (isset($_POST['Submit'])) { - $this->options_validate(); - } - - if ( empty( $this->errors ) && isset( $_POST['savefile'] ) && $_POST['savefile'] ) { - add_action( 'admin_head-tools_page_wp-migrate-db', array( $this, 'admin_head' ) ); - } - - if ( isset( $_GET['download'] ) && $_GET['download']) { - add_action( 'admin_init', array( $this, 'download_file' ) ); - } - } - - function get_filename( $datetime, $gzip ) { - $hash = substr( sha1( DB_PASSWORD . AUTH_SALT ), -5 ); - $filename = DB_NAME . '-migrate-' . $datetime . '-' . $hash . '.sql'; - if ( $gzip ) $filename .= '.gz'; - return $filename; - } - - function get_nicename( $datetime, $gzip ) { - $name = DB_NAME . '-migrate-' . $datetime . '.sql'; - if ( $gzip ) $name .= '.gz'; - return $name; - } - - function options_validate() { - if (!isset($_POST['old_url']) || !$_POST['old_url']) { - $this->errors['old_url'] = __('Please enter the current URL.', 'wp-migrate-db'); - } - - if (!isset($_POST['new_url']) || !$_POST['new_url']) { - $this->errors['new_url'] = __('Please enter a new URL.', 'wp-migrate-db'); - } - - if (!isset($_POST['old_path']) || !$_POST['old_path']) { - $this->errors['old_path'] = __('Please enter the current file path.', 'wp-migrate-db'); - } - - if (!isset($_POST['new_path']) || !$_POST['new_path']) { - $this->errors['new_path'] = __('Please enter a new file path.', 'wp-migrate-db'); - } - } - - function show_error($key) { - if (isset($this->errors[$key])) { - echo '
    ', $this->errors[$key], ''; - } - } - - function options_page() { - ?> - -
    -

    WP Migrate DB

    - -
    - -
    - - errors)) { - $this->fp = $this->open($this->upload_dir . DS . $this->get_filename( $this->datetime, isset( $_POST['gzipfile'] ) ) ); - $this->db_backup_header(); - $this->db_backup(); - $this->close($this->fp); - } - - if (empty($this->errors)) { - ?> - -
    - - -

    - Your database (SQL) file has been successfully generated. - Your download should begin any second. -

    - -

    - Your database (SQL) file has been successfully generated and - saved to
    upload_dir . DS . $this->get_filename( $this->datetime, isset( $_POST['gzipfile'] ) ); ?>. - Click - here to download. -

    - - -
    - -

    - Non-Serialized Strings Replaced: replaced['nonserialized']['count']; ?>
    - Serialized Strings Replaced: replaced['serialized']['count']; ?>
    - -

    - errors))) { - if (!is_writable($this->upload_dir)) { - ?> - -
    -

    - The directory upload_dir; ?> needs - to be writable. -

    -
    - - errors)) { - ?> - -
    -

    - Sorry, there were errors with your form submission. - Please correct them below and try again. -

    -
    - - - -

    - WP Migrate DB exports your database as a MySQL data dump (much like phpMyAdmin), - does a find and replace on URLs and file paths, then allows you to save - it to your computer. It even takes into account serialized data and updates the - string length values. -

    -

    - Example: s:5:"hello" becomes s:11:"hello world" -

    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - gzip() ) : ?> - - - - - - -
    - - - - show_error('old_url'); ?> -
    - - - - show_error('new_url'); ?> -
    - - - - show_error('old_path'); ?> -
    - - - - show_error('new_path'); ?> -
    Data Options - - - show more - - -
      - -
      - -
    File Options - -
      - -
    - -

    - -

    -
    - - -
    - -
    - -
    - -
    -

    Created & maintained by

    -

    Brad Touesnard

    -

    - Profile -    - Donate -

    -
    -
    - - - - -
    - WP App Store -

    - Purchase & install themes and plugins from top brands directly from your WordPress dashboard. - Check it out » -

    -
    - -
    - -
    -
    - replaced['serialized']['strings'] .= $old_line . "\n"; - $this->replaced['serialized']['strings'] .= $new_line . "\n\n"; - - $this->replaced['serialized']['count'] += $count; - } - } - } - } - } - - $subject = str_replace($search_esc, $replace_esc, $subject, $count); - - $this->replaced['nonserialized']['count'] += $count; - - return $subject; - } - - function apply_replaces( $subject, $is_serialized = false ) { - $search = array( $_POST['old_path'], $_POST['old_url'] ); - $replace = array( $_POST['new_path'], $_POST['new_url'] ); - $new = str_replace( $search, $replace, $subject, $count ); - - if ( $count ) { - if ( $is_serialized ) { - $this->replaced['serialized']['strings'] .= $subject . "\n"; - $this->replaced['serialized']['strings'] .= $new . "\n\n"; - $this->replaced['serialized']['count'] += $count; - } - else { - $this->replaced['nonserialized']['count'] += $count; - } - } - - return $new; - } - - /** - * Taken partially from phpMyAdmin and partially from - * Alain Wolf, Zurich - Switzerland - * Website: http://restkultur.ch/personal/wolf/scripts/db_backup/ - - * Modified by Scott Merrill (http://www.skippy.net/) - * to use the WordPress $wpdb object - * @param string $table - * @param string $segment - * @return void - */ - function backup_table($table, $segment = 'none') { - global $wpdb; - - $table_structure = $wpdb->get_results("DESCRIBE $table"); - if (! $table_structure) { - $this->error(__('Error getting table details','wp-migrate-db') . ": $table"); - return false; - } - - if(($segment == 'none') || ($segment == 0)) { - // Add SQL statement to drop existing table - $this->stow("\n\n"); - $this->stow("#\n"); - $this->stow("# " . sprintf(__('Delete any existing table %s','wp-migrate-db'),$this->backquote($table)) . "\n"); - $this->stow("#\n"); - $this->stow("\n"); - $this->stow("DROP TABLE IF EXISTS " . $this->backquote($table) . ";\n"); - - // Table structure - // Comment in SQL-file - $this->stow("\n\n"); - $this->stow("#\n"); - $this->stow("# " . sprintf(__('Table structure of table %s','wp-migrate-db'),$this->backquote($table)) . "\n"); - $this->stow("#\n"); - $this->stow("\n"); - - $create_table = $wpdb->get_results("SHOW CREATE TABLE $table", ARRAY_N); - if (false === $create_table) { - $err_msg = sprintf(__('Error with SHOW CREATE TABLE for %s.','wp-migrate-db'), $table); - $this->error($err_msg); - $this->stow("#\n# $err_msg\n#\n"); - } - $this->stow($create_table[0][1] . ' ;'); - - if (false === $table_structure) { - $err_msg = sprintf(__('Error getting table structure of %s','wp-migrate-db'), $table); - $this->error($err_msg); - $this->stow("#\n# $err_msg\n#\n"); - } - - // Comment in SQL-file - $this->stow("\n\n"); - $this->stow("#\n"); - $this->stow('# ' . sprintf(__('Data contents of table %s','wp-migrate-db'),$this->backquote($table)) . "\n"); - $this->stow("#\n"); - } - - if(($segment == 'none') || ($segment >= 0)) { - $defs = array(); - $ints = array(); - foreach ($table_structure as $struct) { - if ( (0 === strpos($struct->Type, 'tinyint')) || - (0 === strpos(strtolower($struct->Type), 'smallint')) || - (0 === strpos(strtolower($struct->Type), 'mediumint')) || - (0 === strpos(strtolower($struct->Type), 'int')) || - (0 === strpos(strtolower($struct->Type), 'bigint')) ) { - $defs[strtolower($struct->Field)] = ( null === $struct->Default ) ? 'NULL' : $struct->Default; - $ints[strtolower($struct->Field)] = "1"; - } - } - - - // Batch by $row_inc - - if($segment == 'none') { - $row_start = 0; - $row_inc = ROWS_PER_SEGMENT; - } else { - $row_start = $segment * ROWS_PER_SEGMENT; - $row_inc = ROWS_PER_SEGMENT; - } - - do { - $where = ''; - if ( isset( $_POST['exclude-spam'] ) && $wpdb->comments == $table ) { - $where = ' WHERE comment_approved != "spam"'; - } elseif ( isset( $_POST['exclude-revisions'] ) && $wpdb->posts == $table ) { - $where = ' WHERE post_type != "revision"'; - } - - if ( !ini_get('safe_mode')) @set_time_limit(15*60); - $table_data = $wpdb->get_results("SELECT * FROM $table $where LIMIT {$row_start}, {$row_inc}", ARRAY_A); - - $entries = 'INSERT INTO ' . $this->backquote($table) . ' VALUES ('; - // \x08\\x09, not required - $search = array("\x00", "\x0a", "\x0d", "\x1a"); - $replace = array('\0', '\n', '\r', '\Z'); - if($table_data) { - foreach ($table_data as $row) { - $values = array(); - foreach ($row as $key => $value) { - if (isset( $ints[strtolower($key)] ) && $ints[strtolower($key)]) { - // make sure there are no blank spots in the insert syntax, - // yet try to avoid quotation marks around integers - $value = ( null === $value || '' === $value) ? $defs[strtolower($key)] : $value; - $values[] = ( '' === $value ) ? "''" : $value; - } else { - if (null === $value) { - $values[] = 'NULL'; - } - else { - if ( is_serialized( $value ) && false !== ( $data = @unserialize( $value ) ) ) { - if ( is_array( $data ) ) { - array_walk_recursive( $data, array( $this, 'replace_array_values' ) ); - } - elseif ( is_string( $data ) ) { - $data = $this->apply_replaces( $data, true ); - } - - $value = serialize( $data ); - } - // Skip replacing GUID if the option is set - elseif ( 'guid' != $key || isset( $_POST['replaceguids'] ) ) { - $value = $this->apply_replaces( $value ); - } - - $values[] = "'" . str_replace( $search, $replace, $this->sql_addslashes( $value ) ) . "'"; - } - } - } - $this->stow(" \n" . $entries . implode(', ', $values) . ') ;'); - } - $row_start += $row_inc; - } - } while((count($table_data) > 0) and ($segment=='none')); - } - - if(($segment == 'none') || ($segment < 0)) { - // Create footer/closing comment in SQL-file - $this->stow("\n"); - $this->stow("#\n"); - $this->stow("# " . sprintf(__('End of data contents of table %s','wp-migrate-db'),$this->backquote($table)) . "\n"); - $this->stow("# --------------------------------------------------------\n"); - $this->stow("\n"); - } - } // end backup_table() - - function replace_array_values( &$value, $key ) { - if ( !is_string( $value ) ) return; - $value = $this->apply_replaces( $value, true ); - } - - function db_backup() { - global $table_prefix, $wpdb; - - $tables = $wpdb->get_results("SHOW FULL TABLES", ARRAY_N); - - /* - if (is_writable($this->backup_dir)) { - $this->fp = $this->open($this->backup_dir . $this->backup_filename); - if(!$this->fp) { - $this->error(__('Could not open the backup file for writing!','wp-migrate-db')); - return false; - } - } else { - $this->error(__('The backup directory is not writeable!','wp-migrate-db')); - return false; - }*/ - - foreach ($tables as $table) { - if ( 'VIEW' == $table[1] ) continue; - $table = $table[0]; - // Increase script execution time-limit to 15 min for every table. - if ( !ini_get('safe_mode')) @set_time_limit(15*60); - // Create the SQL statements - $this->stow("# --------------------------------------------------------\n"); - $this->stow("# " . sprintf(__('Table: %s','wp-migrate-db'),$this->backquote($table)) . "\n"); - $this->stow("# --------------------------------------------------------\n"); - $this->backup_table($table); - } - - //$this->close($this->fp); - - if (count($this->errors)) { - return false; - } else { - //return $this->backup_filename; - return true; - } - - } //wp_db_backup - - function db_backup_header() { - $this->stow("# " . __('WordPress MySQL database migration','wp-migrate-db') . "\n", false); - $this->stow("# " . sprintf(__('From %s to %s','wp-migrate-db'), $_POST['old_url'], $_POST['new_url']) . "\n", false); - $this->stow("#\n", false); - $this->stow("# " . sprintf(__('Generated: %s','wp-migrate-db'),date("l j. F Y H:i T")) . "\n", false); - $this->stow("# " . sprintf(__('Hostname: %s','wp-migrate-db'),DB_HOST) . "\n", false); - $this->stow("# " . sprintf(__('Database: %s','wp-migrate-db'),$this->backquote(DB_NAME)) . "\n", false); - $this->stow("# --------------------------------------------------------\n\n", false); - } - - function gzip() { - return function_exists('gzopen'); - } - - function open($filename = '', $mode = 'w') { - if ('' == $filename) return false; - if ($this->gzip() && isset( $_POST['gzipfile'] )) - $fp = gzopen($filename, $mode); - else - $fp = fopen($filename, $mode); - return $fp; - } - - function close($fp) { - if ($this->gzip() && isset( $_POST['gzipfile'] )) gzclose($fp); - else fclose($fp); - } - - function stow($query_line, $replace = true) { - if ($this->gzip() && isset( $_POST['gzipfile'] )) { - if(! @gzwrite($this->fp, $query_line)) - $this->errors['file_write'] = __('There was an error writing a line to the backup script:','wp-db-backup') . ' ' . $query_line . ' ' . $php_errormsg; - } else { - if(false === @fwrite($this->fp, $query_line)) - $this->error['file_write'] = __('There was an error writing a line to the backup script:','wp-db-backup') . ' ' . $query_line . ' ' . $php_errormsg; - } - } - - /** - * Add backquotes to tables and db-names in - * SQL queries. Taken from phpMyAdmin. - */ - function backquote($a_name) { - if (!empty($a_name) && $a_name != '*') { - if (is_array($a_name)) { - $result = array(); - reset($a_name); - while(list($key, $val) = each($a_name)) - $result[$key] = '`' . $val . '`'; - return $result; - } else { - return '`' . $a_name . '`'; - } - } else { - return $a_name; - } - } - - /** - * Better addslashes for SQL queries. - * Taken from phpMyAdmin. - */ - function sql_addslashes($a_string = '', $is_like = false) { - if ($is_like) $a_string = str_replace('\\', '\\\\\\\\', $a_string); - else $a_string = str_replace('\\', '\\\\', $a_string); - return str_replace('\'', '\\\'', $a_string); - } - - function download_file() { - set_time_limit(0); - $datetime = preg_replace( '@[^0-9]@', '', $_GET['download'] ); - $diskfile = $this->upload_dir . DS . $this->get_filename( $datetime, isset( $_GET['gz'] ) ); - if (file_exists($diskfile)) { - header('Content-Description: File Transfer'); - header('Content-Type: application/octet-stream'); - header('Content-Length: ' . filesize($diskfile)); - header('Content-Disposition: attachment; filename=' . $this->get_nicename( $datetime, isset( $_GET['gz'] ) ) ); - $success = readfile($diskfile); - unlink($diskfile); - exit; - } - else { - wp_die("Could not find the file to download:
    $diskfile."); - } - } - - function admin_menu() { - if (function_exists('add_management_page')) { - add_management_page('WP Migrate DB','WP Migrate DB','update_core','wp-migrate-db',array($this, 'options_page')); - } - - $src = plugins_url( 'asset/css/styles.css', __FILE__ ); - wp_enqueue_style( 'wp-migrate-db-styles', $src ); - $src = plugins_url( 'asset/js/script.js', __FILE__ ); - wp_enqueue_script( 'wp-migrate-db-script', $src, array( 'jquery' ), false, true ); - } - - function admin_head() { - $url = admin_url('tools.php?page=wp-migrate-db&download=' . urlencode( $this->datetime ) ); - if ( isset( $_POST['gzipfile'] ) ) $url .= '&gz=1'; - ?> - - Date: Sun, 29 Dec 2013 10:46:25 -0600 Subject: [PATCH 02/52] update again --- asset/css/styles.css | 150 +++- asset/img/wpappstore-logo.png | Bin 30847 -> 0 bytes asset/js/script.js | 465 ++++++++--- asset/sass/styles.scss | 177 ++++- class/wp-migrate-db.php | 1390 ++++++++++++++++++++++++++------- template/help.php | 55 +- template/migrate.php | 73 +- template/settings.php | 35 +- wp-migrate-db-pro.php | 4 +- 9 files changed, 1865 insertions(+), 484 deletions(-) delete mode 100644 asset/img/wpappstore-logo.png diff --git a/asset/css/styles.css b/asset/css/styles.css index 4301494..be1b9c5 100644 --- a/asset/css/styles.css +++ b/asset/css/styles.css @@ -19,9 +19,12 @@ Settings Tab ========================================================================== */ /* ============================================================================= - Settings Tab + Help Tab ========================================================================== */ } +.wpmdb > .warning { + max-width: 750px; +} .wpmdb a { text-decoration: none; } @@ -38,7 +41,8 @@ vertical-align: baseline; margin-top: 0; } -.wpmdb input[type=text] { +.wpmdb input[type=text], +.wpmdb input[type=password] { padding: 5px; } .wpmdb .option-section { @@ -92,6 +96,7 @@ } .wpmdb .connection-status { display: none; + overflow: auto; } .wpmdb .connection-status.error { color: #9D1818; @@ -237,6 +242,17 @@ line-height: 21px; padding: 10px; } +.wpmdb .basic-access-auth-wrapper { + display: none; + margin-bottom: 5px; +} +.wpmdb .auth-username, .wpmdb .auth-password { + width: 206px; + margin-top: 3px; +} +.wpmdb .auth-password { + width: 207px; +} .wpmdb .connection-info-wrapper { display: none; width: 670px; @@ -371,7 +387,7 @@ .wpmdb .table-migrate-options li { margin-bottom: 5px; } -.wpmdb .replace-guid-helper { +.wpmdb .general-helper { border-radius: 50%; border: 1px solid #ccc; background-color: #eee; @@ -380,13 +396,14 @@ display: inline-block; position: relative; top: 4px; + margin-top: -4px; cursor: pointer; margin-left: 2px; } -.wpmdb .replace-guid-helper:hover { +.wpmdb .general-helper:hover { border-color: #aaa; } -.wpmdb .replace-guid-helper:after { +.wpmdb .general-helper:after { content: "?"; color: #999999; font-size: 10px; @@ -395,20 +412,26 @@ position: absolute; top: -1px; } -.wpmdb .replace-guids-info { +.wpmdb .helper-message { padding: 10px; border: 1px solid #ccc; border-radius: 3px; background-color: #fff; position: absolute; width: 500px; - left: 140px; z-index: 100; - top: -7px; display: none; box-shadow: 0px 0px 5px #ccc; } -.wpmdb .replace-guids-info:after { +.wpmdb .ssl-verify-message { + left: 182px; + top: -10px; +} +.wpmdb .replace-guids-info { + left: 140px; + top: -10px; +} +.wpmdb .helper-message:after { content: ''; border-bottom: 7px solid transparent; border-right: 7px solid #fff; @@ -420,7 +443,7 @@ top: 11px; width: 0; } -.wpmdb .replace-guids-info:before { +.wpmdb .helper-message:before { content: ''; border-bottom: 7px solid transparent; border-right: 7px solid #aaa; @@ -435,6 +458,36 @@ .wpmdb .label-disabled { color: #888; } +.wpmdb .prefix-notice, .wpmdb .ssl-notice, .wpmdb .different-plugin-version-notice, .wpmdb .mysqli-notice { + background-color: #FFFFE0; + border: 1px solid #E6DB55; + padding: 15px; + border-radius: 3px; + margin-bottom: 15px; + display: none; + width: 710px; +} +.wpmdb .prefix-notice p, .wpmdb .ssl-notice p, .wpmdb .different-plugin-version-notice p, .wpmdb .mysqli-notice p { + margin-top: 0px; +} +.wpmdb .prefix-notice p:last-child, .wpmdb .ssl-notice p:last-child, .wpmdb .different-plugin-version-notice p:last-child, .wpmdb .mysqli-notice p:last-child { + margin: 0px; +} +.wpmdb .different-plugin-version-notice, .wpmdb .mysqli-notice { + background-color: #FFEBE8; + border-color: #CC0000; +} +.wpmdb .different-plugin-version-notice a, .wpmdb .mysqli-notice a { + color: #CC0000; + text-decoration: underline; +} +.wpmdb .mysqli-notice { + display: block; +} +.wpmdb .ssl-notice { + margin-bottom: 0; + margin-top: 15px; +} .wpmdb .save-migration-profile { font-size: 14px; font-weight: bold; @@ -499,6 +552,65 @@ .wpmdb .settings-tab { display: none; } +.wpmdb .settings-tab .slider { + max-width: 416px; +} +.wpmdb .settings-tab .slider-label { + display: block; + margin-bottom: 10px; + float: left; + width: 50%; +} +.wpmdb .settings-tab .slider-label-wrapper { + max-width: 416px; + width: 100%; + position: relative; +} +.wpmdb .settings-tab .amount { + width: 50%; + text-align: right; + display: block; + text-align: right; + float: left; +} +.wpmdb .settings-tab .slider-message { + top: -11px; + left: 164px; +} +.wpmdb .settings-tab .slider-spinner { + position: absolute; + right: -35px; + bottom: -13px; +} +.wpmdb .settings-tab .slider-success-msg { + display: none; + right: -53px; + bottom: -13px; + position: absolute; + font-weight: bold; +} +.wpmdb .settings-tab .ui-slider { + border: 1px solid #dfdfdf; + height: 10px; + border-radius: 2px; + position: relative; +} +.wpmdb .settings-tab .ui-slider-handle { + width: 7px; + height: 20px; + background-color: #aaa; + display: block; + position: absolute; + top: -5px; + outline: none; +} +.wpmdb .settings-tab .ui-slider-handle:active { + background-color: #999; +} +.wpmdb .settings-tab .ui-slider-range { + background-color: #eee; + height: 100%; +} .wpmdb .settings-tab .option-section li label { font-size: 12px; font-weight: normal; @@ -523,6 +635,12 @@ position: absolute; font-weight: bold; } +.wpmdb .settings-tab .option-section .verify-ssl .ajax-spinner { + right: -45px; +} +.wpmdb .settings-tab .option-section .verify-ssl .ajax-success-msg { + right: -65px; +} .wpmdb .allow-remote-reqeusts { font-size: 14px; font-weight: bold; @@ -582,9 +700,6 @@ } .wpmdb .help-tab .videos { width: 640px; - border-bottom: 1px solid #CCCCCC; - margin-bottom: 25px; - padding-bottom: 28px; } .wpmdb .help-tab .videos ul > li { margin-bottom: 30px; @@ -650,6 +765,9 @@ } .wpmdb .help-tab .debug { width: 640px; + border-bottom: 1px solid #CCCCCC; + margin-bottom: 25px; + padding-bottom: 28px; } .wpmdb .help-tab .debug textarea { width: 100%; @@ -689,7 +807,12 @@ .migration-error { color: #A21B1B; + display: block; font-weight: bold; + max-height: 400px; + max-width: 100%; + overflow: scroll; + word-wrap: break-word; } .progress-content { @@ -796,7 +919,6 @@ border: 1px solid #ccc; border-radius: 3px; background-color: #fff; - colour: #333; font-family: "Courier New",Courier,monospace; font-size: 12px; display: inline-block; diff --git a/asset/img/wpappstore-logo.png b/asset/img/wpappstore-logo.png deleted file mode 100644 index df44985ec6322a7bafa2f319a30b72a7302463bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30847 zcmafaWmKD6(dwm$DQ)s+Zvsc}(IPzaP?%4?&bpi4fMKVbtNzjsWh z10H{gcDjZhhH9_GEu0}d z=6~VvKp`%V)F>z*X{d|2g@cs`<2x%GJ10rz!{&BoMmtMMW`h@Md}=OWD_gslzHU}J zzUsObz77^*mdw&pj3B7^BLj$)hdCn@;^^cq4wYp74`1=e@?X`w%#8m*@oGdCMcMol=|BCT{#dg>Aak1jnwsLp&bhCK0hc(MT#E*UV|8D3XL`#c*@mxIJ z9RH)Ir3J5*qZP!;$;16oDE|LQ^eDNwhMV1^0nHudoh>~7`d3+AlG)SK&Qe_Xg@Ul4 z7@x4HFj$eFUtUgDSV2HuR8$14APbfg;uHC+vA-DnZ^FkK9?M5sQDH?nML9kpu;>eU zetrdhF#%aYQP~%YVj_ZkkL05N&?-B*dzd>}SpC)LU$l1rr4{^t(u#xKtjs-}-E^Iu z9sh9^Wk*L(cMrF}su{sLFL?O>vf$q`TDjSISy?K&IYSu#V*+uz|4Yk?q9Tu)iahEj z@TfLFzo;l!SXMz8EGVp~$S1@n%ltR3<^Srce>DF8((*nEV`(AoVdvp!^|x=zI(qzF za@1v}K)ioBpQGI)#eYiwL(KcXSpKK_ ze|hUan2#awSMlH2dwlpedaaxuL)PsvHseEf8GcsunSO8mJ-2jJVf@|I8@%9@D2;B-SE!3mFJe~AnF3;MuNd4 zzrKG2axtMW>B~5|MQkfAyF1F#XO8St1DAt1Cni&p?|xHQN~r$Bh@fWDsl3<-l0N2H zYq?GRr4Y5yN|x0E%#$4QYC7^258j+3x!cuV10)UJy2)+Bwz0DFkq318nIn8SK9eCc zp`7X2Kaf+Tc8z#AYKn+l%hcB;6H-IR>+Jjf^Tnk(N;o2ZXvLu-j$zRB(%bp2Tj!Xl z_H7P>WN-(1#g=Mi!sow%8tTd2!aXhVu>GsL(cj5r$}?MFI$?oCkx9NR)i^k^0V{J? z>kG}~E&+S80|i~5#C27*GtWTx6n(&T%mvp}S0xcUZn%oa%(s>YhwmN@|5#?SLuLOQ zH#tc^7GRDo?&DA7&ozYdOGsA4L-=(eCe;Gk5GzmH9CNTF_m7V((V$o2KZ1T9`=y?7RX)Rmkr|Waefgy2rRAwxfl`RYlp*cB@og-hWpZFX7qF6@iSioEEf502D z#V{mL85nTcRCS^x!x6xNqDhmkKtdd!{u3D`A=A~k zR4tn;)xRPu)HrZy@5Y*ci~ib4Y(KnB9{p12lMWJFU((Wx2srR{tkg!n0fI(t)-E)) z(1oY|AR5g}RvJhcB-~9{5qJSBo+SACWSY@XdElxs2G|PJBZ3-;sOCURj#j{65;aGm z@6;g847?nD*i3Mg{jUVD%sgi?5hu#|vI-6v1_doBcBf5F-k9J?L1?L6GS>o+rf6EJ zz04wbLB5g%9lmvqz(tnmIUt0#TMfDnS*5P->-VUTSGT*SCLPmMeXN|TT1_<4)H<%Y zhh0%D8uA;+9tTp6j%=*{W-v0W63hg_mQY7j8{F>oEZiR-jtr{Gs{9T1ngxB%_+V-4 zZCv)~!E6?M7V3s$TQ-CH&5|3{!;Gs5oX6nxqzh5{;Tbmg(~ICCmVG62&}dh8#t3~m zTMmmA!?t08ik&^$Z6(q9@~&CxDg=gAmwr}c>OJ};x8rH}{U<(T^rYw{02iGGjf$|G z=_a|oXpMrOD7ptk3)Oe`fldkE(z~+b7u3J{SE%gT)L-C8&+teOd+^CYqiMo zM-~+Yd~+SJ(;b0k8h_L!5c(BL&pq)2}RZs>kv`*?6-?)kvRWq4T2+BtUILVSrKxe@HspN@pGKZq)L6+V`P*@7cjIMLymJ?aM+?WQv?YBKBOx1uls7q0L?MTa2YkCd*udnlV-qSq11)1`8@8RMZySR zVY{KGCqzY|KUbbUl-5+h7=@VsOIHZnlW)|JtTrPk5B*xv1Ar^Q*LQEQzD>}0R$6yb zjYO;mbE!^N@D=?a3<>_7s@U4;1{I1AqKEP%l2XLv9e1-sKY_$dTSJGAUGMSJL}XC3 zhq;W&<#oB3J1#J!#?xCc^8bNz>{IrFD7~}jFEkM-Q7B=i1mL2b^=7Hlt15Lz6uA*s zy(!%FopD{yCGW0Z-S-Ga(wks*jx4$6S>Y$A>;V8t4GoG4|C@=3#cfU3)vbqTi}&fE z?G&!(zfpdM6;xIVje2$tT6b1*VcR;=)pxoD^!uTAoshxMuhr>p73qYYl?wKXhNI>r4^;H3OaLY&q0KJ@sGX4TZP#OJhX~ zt;ZLc4{pTCejk&*+0sIx1NISfM^$}nfun9l%u>KICpMAmnImmD`e+uJ%8c_*>&R*a z9k`4E2s-dJ2shCG7RDrDDTr`=1Jg69KJhuPhX?%%q@JU#OJsG+fa*2#A-{OTj=fG_ z#oi4E_x-H2piD;F(&=xJY$z7 zVu5^9(HxRms!kKBm9654`>l`>B=J?W8*Aoc{7Ks9tC>0pQoj6CwY+4fMe#ZIx;Uv-kJj-gMyuGm8Ygx1S^s=Ue+>xBYy_?|~sRDBX(LRa~Y$vRh>Px^Ju^ zaEsYP5*f_J40ED^e)BN#e&{pp4vrZGA6C`UCl$E z{Yf7)<;95q&MH{vf_Kld;P7VF0M|BqG&SjU&8v8r$5CxXTkmgLy^h#oo!(9*C^u=8 zq|{)wOmVW_O`kOFH}1q(hK3WuV$-+5w{*OQXKv%_TyGiyu=^i$NQ;LXxXjt~3k-T- z5>1L8%E$N&Iq6{IQ4^TG52@2qnXG34VeBs7%Xc{tr?7~+DzA?rY^y7ft}Jh@%=`bk z0IsiL1?+r}lAn-d&^{1O9TCBY&4V!Tu5FUrT#-eLd$ty9nW}&Qz^^p*n?INkxukib zSM<5oa3Jtkbnd+a^4iTuTrdIMdjs$VocGfY9nCr^vk}m?)eZ5M0uCBvy}MD;OrQ{x z;749zgJyW82_9A}81m&v$^!21r5{8tr$s1a1}t-$TJW39t0yM4;=N&|^;*s561=z9 z$!*Py8bSY#>#dBQ1TOMYYPa4xI4`If6XeG5<2Noym%Z~} zxY1=*v<&Kl;bQ10UGCtzz;t+5Z*u1hBfSIb>hd^a>7AVPLA^Ae9&d7=fDhiSBAEco zjs6EBUDf9Z-LI90joy3+oB*I(y>!+gL)kN9Obn0)2tChx5x|N{a^PoWhj{>M00ypR zQfR$EujDvXB4(s<*~S3}y_i(f%1>7MH&p@UfL(o|bw(gYd*6*PlkeK&y0gK@ejboN zt%7e=@TEi#Db*>2-lV;7{3;WHhm`y}U8kQPymjmXK^vnK3fEL7<-`b(~WAqi1Xt z9c`4*V04W#hZKR`757ik|LTKq0^7 zqt%Hph>+4ssh5$#3IS68D$Hg1Vkx7SQ6k82Ge{X2xH_z4dR;crcPRO=!GF6$89LFB z%kE7R$**q8d`$jnOYWDR;m|ViE<6>$LS~$g@U`PpqhMo*@kV3Z+%Ui5@DF_Riz!r! z{T*^Li+p!uaCY1M0=(Ai*}r^#JM~S);9GFw(AvE?VoIM;(3i$GX;_JxjM=5JGk6Q- zxxGwZL~vgTF>(*Ko7{#6j?kKYpryHASPsJS?^{V+2o0{MIJq2yzN$nblX(WTr~d2n zK;QlkmDHT%uA{gy5qXLZ8?gh%9fOAP=yFxXCdW|34V>wA>_#lTD9T#=TQ4BDi_&P0 zl?IgX`&WmAtKFZeejd|YqxBQy=P6oW5Q91F<9YD07IR$;s^F^6m$aNTM={4L$q~s~ zH_y+VssWfE_lPcz*@??c+HpcCI*=jgn(dyLA=cPsD*?37@QY}<`3i0jX2b$8II${a zYq(@O9A+cED1#U$p!@j>;3QRr!qQF6^;=g#9X=Y&X4weh($(_y`NvrK=d7oUN?b^9 zR|TPPc+}P?hAl|v7!-q($5K;_@2{)B$cVp|i#86$=cA^vQ8G_lmT7S=d}4K$C0fi4 zpf|*1UIw}z&-qgA#T8+#z))nshDhY$qGm`4F?U*BUUEd7o3}MPFwg?0?9&1?mGHm< zQi3rzj@IzJ-tcCV5VZBWJ#VS$>Qs-i%ST|2>$wqPnntrJ5YNf)p3dd2dD)ymSV$aK zB-8)NpDA4Y4Kd4W-8ONeM$o0SE4jMhaZU0+v%vZIv9L*(*LwI-@*yZ__`FeHMC9<~ z4XHLJY>C6D63e_ww+o**+Txqat+cMhPhh+l4Wu~18QQYD_J`;YK|vZ&ugf~VOLL<2 z>bP=8)}h{lBan23z3{{k0Uh+9A!9Vu;G$!MplWpR!-u`8F;W*I&F?pd2+N5{Q<1DT zv{ZA($&Y-8X}?^|b_NL=?nbscR)4i1I{Wv%5&jyoo<8qGN+C4(UUI|}y&%uatcntf z<=d#TdDefIR7yF0Ct;W*=3y%zu&r3Ov-6<`J6b7ha-9aHn~Iv<;7N?dI2%|*;g5|( z3%FKUZ91La`%FxUBe!k$EL1prfyB?ppHQ0g&*sVJq0@SE>u~j z6TM}pQsMaP6en$n9gYA?HzG+j+xRu#3Cpk==5y7dhGnM3qfm)Uez!LO(E7@2|7&Gi z-9f&V2b9IGi>Zw#=$RiO(aSznSnA>UoI=GrVm^caGt8b9()%N2zgyv^`L`l-fC09$ zb)OR^33J%+LoxNAh{>S8j*+2gl&pfW=_=S#MW|ijo_z1I2V^xI8{JBsqm<`rxC@N_ zIlS6Jjgei$MEKC7KTf-h*nHeU$w7*T+`ry2dDWD!6X!s3k7p#y_`j{lk)~#UArDKn zw@axlk7Sfrpcc4sf^Du6)~b*V)+ZsvunsMQ;*)o$bqvf-WA84nF?5s2%}>u4h(j|Y z{|pNFxONC}A^+$ZnwA~EBkdXj@BUJ=I_UXv_;WzVR7It9NRgJxgm>|Vzw zmhia0w0KX5MyIIc*huh~{E?Z&*Mee;>P$ad{S%*D(fk-cC11e4ss?(2y$|Mp2GMBu0P4_(H4N4!U@)0iDw<0)1VPQIeMHDNj%A*BPD0< zyXN|~AlcesewCym`?sz~XlffiFL*AA;I!Rt@{fBN--YFVWy7C3nt#l_j?qZd4!ICXmwbe2fC+#Ubo3-540 z85rV%*%b4keVD0`3Fb=}Htg4-Z-^1^BJLu*Z!C^U?4Mz&MMd9!MqzFN@Ka!>^d=qlO6yGC?r zC{%|)EGV{s1`5v{y9|XYb&e8A-m}-eK16R!Fv(ZE7%djb808ct(1|`-tchh_f=q^1 zUQ-O7@9}#iOdaCH_Or8T#I8Xdg4eDusVa0j2=N>&R-B{^y^>_nQBw+w&1}VikYAqt z8;<=O)qTF-KLPLNTMiqrxp;=)rAaFI^ZrEu-@tI6N;C}edQ(_YyC=?GSp*hq_@83| zlh#v=S+V$t8sf_osx&fg#<41HbhK}%>gCZx_6R?EH0W+pw_C_;1BkT_Uf$0p9#+Cq zdEUdDS=bY!S6a;sUKLe`oBO@(+G)UE`|Mly$$(VxwKnDF&(xC+A!ig2K&CaBe3ty( zcuL{@_D9D6juL|GKH%+1<|u0K8Q3&7wJRUn#h;KxmzWFr&iP~C=Up64xhycTMmoH+ zuu&i_YAN~>DnV<1d1#lramAHCyp^@$%@c6oju^0v9P1w~W8K19kLh|w4M-dnM&97J ziS)g_DimC6o$i0w`1(+yIYXHAg-vlP+td{GgfujnQZ zQ8&fV{}~Llq_*W8z0rauiVQy3ogamNVt*$yH6yR=cpYb8vzFr#NP^!O+iX-gU*{fI zCHQk2&aYxcHg?I@5*32k-7SVzkH_oR?FS6lLOjpB2n*r%^oKIxOmbJhoX`067Dt@ z;MkmS#q$xR+&Xdg`LAz8w3|LjPfR)u?{Y=0O~!gAO>+kc{@8U?I5qa|QrQpk_y%i* zpl{-nbI9wE3&l|*9n6Gfv*fbfo#Le|oR$PWteSV}hThw{eK^d|KTl7v{$idq3EnFF zPUVo=f}>k3GeeLLwG!f_%(kaK5u(HfMdyCMz$MTx;6gKUQt-z>{S^k%8I}1!uVYfg4F5ct38SC*B$DOl z$nH$>{<)zQUpN(~VMmJ;HkW0TJL805iRHo4O5W#*7S8Hw?u{qOsJ6m29<%$kCyjg+L9E4opTbHuG8oPw<#j!!t}AeP^w_#HAyL z$NBlv9uGv2hHBBKxkfU+t3mDf6j_GSGeJ0$(v$5(t|!=+CnM{#Oif zI6tDZPJo+Cz$acW<*Na8<#*l4tDwo1fe7kZ9~%2a+yrMH=BEIJ?qG{Hom_f~EJ8@v z(ZG?SzEi~jD>p7&=frG7AH4;D1}~Q(c#H0sn`2H^md+Hyc1Mu?v^2AT`er~l!#>l!kFJ?M0l!Qn>Xh7WW zbr?j)37uQEvkpQ>BD9@Z(K6>SbhI*wwIvB2Cj%k%KUs>?T_mYxu=KHT3({%y?Oy3R ze^6D^IeXE!L4r!)_v4E0wqnJlqh$Jx&`-MJ8MLJ2}V8y3E3W=w$;^Zw09 zq6(q06xe&%cRMu~5=Dow`|x*M*-;TwmsOSmvCfW=pp6Utza?T&H?KSPoPHaA?a!kiwAPGHBV)9 z_BOqqA+0@_CwIqr!2CYZMsqMbVpw~!M;Z7;Mfpq|`ILh=pdsTokl09)$@r~GDdsj) zhP3=c^yr2(a6?L=;gFuov>j8VLTb3hEC*h;mg2H>qg4qz zj+3rr*jq8zB%a51DOSn+5I4y#lHH^WJC5NjTP)@W!b7w3>>FN%tBQwCs#h?)`MEya zeBd{;CcpvRQlTNAdl9A|{A%J%&C91*_?HPxZoet>8*595JNK=JFZ>PIZltwJ5<5aW z?CZXY{HVvfU<*_!Hz+PgiGDWhl!5_zX!_12r zVdX;~3Rhh*1U(&cz100WWhhD$(Wq5{8!km*eQNv1z7qo=@l{M})j9oDd~o+;pqZEc5k5;@zWo(TO@{$8XAH&?VGHX3n?ri6 z)t78Aah-%w;ZIhCt*a5+qp*!ZRKvhkKtg5%&PGvkc8v>35)ZH3hA-73ZbS_xSH9*r zF+h*s=?PPIMJPjOsFMSU^hMi)@8yrf+Z#+DmHLg%s&|Wby1eOO!#b%>H9M4vRfppSl0pe zc-~0f64@7+%LypBs0@)G@3#pCV`A8^Pcc>I#0mRatzC!P*67Gd$wk?9YX)K{DxP?hR|-itCYmY3?I~q1~9n z_3?mL#=M5_?0HckFYVnhyrxxmO{DGq1pw60j%gIc`Zdh_^9&C3V0ie+V#6^h-Ui+$ z?SwdVc*;N}x=ZVkTyZ0A=qqfVC!fBt-0olpQ4xS{C*ee{lX0j_Uw1k#&fW<-(+3Xt zwfSt@1YR78`Eb_1+0ywb@%zWV3cA1&zU#uC@|_%8ru{hzY5lu~y+o~X>RFPoF=Jk?iU)`0xIJXGyr)7HCTt8S#wrCUR<)G$F8Ti?MWVJLDLv zI{5_5Qp76DXuq~79=czqg2$@L@V|&^`8ePvqVr2dxYqi9SI-zaKP z>2H(;xo@oz-3?DZ4p*n(GGaYX{B!7@b-i^2vEGHgtmr2bXM;y2OkSvH2%coMKQJ|o zkKT5DYjMDr%`0YC`J`e1Ge2eiHD>oJHMf)#Qy&sz7OrCa!9{Sec3kMbzO*!#4>jf@ z?|loM8GX8@t}P2(`Kg2@#vTH(nE3x0b4p+=%A`q!||k*i@hfRM6`O}+Y#2zhS2J+ z%$FbUL2p0t5zABuzR&DkQFBE74BLt8oZfjdUQQXI)KvMV67%C5+OZQ0)KT~cZrXU| z*$9(-9(#MNcF76mSC7dywAarHTp1+(44_OO4^vPnRoH%ib|oEvMHPmZMkT}>gp^d! z)8eSNq7B(#>>@zVhi2=PRw~NKcaXd$fBu3lWDq>L`VRAt5h{A=Se-ay$>8&Pj#X#r z=xifMFvK{nN(}{7AvKu!m~~vKhG$ubDeXfC@b+D;$pZ0Z85VuF2|9iK3b)V?kIYv=?^B7Jb%6sv5|)R>Z-Kj5Bs9!H zL&0pRX8~yR3MfFQ=!(h^x!vbz&{A3`JDXBHgnXh94>3L+thBj)S~o$P63-eN zXoAVfEVJT>bxzRvayoM3hk!}DRwxQ8SV!zEib;*w7r%cMH0K}Nd(45jnJcNkJF252 zN7Vok0wb2G0D6h&`ZdA9Mfw#iNRvpw0eD*h9||SZAoK{WwLu^K2)cW;QbC&Hw}gt{ zI1L_6(F=+)ih9xKT?7Wc_U1!q06~tGdPWsfRpqm^&!92NUAM%plfNzrouQlx{gr2J z4@O7nBy_(@6xo5Y>}v^mLgDb>;Khz;8g{N^rI6s}5JPq;K3Ljt^=}FA34nC_Ez9Q&q;EsiI=7r{+NB~oP7Luu;%LCH z6NTtszw1+U=sY)=4(?0p5JXY2sEqOM&wgsgaWIC++(XnsFm&Dh)^Fnq%x6Zvo%PZZ zs5CPoymM58d7n)IXH*QHwv6L_A1KK8#rD-_P`>S?QBO>Iu1nr5&*Uuhg@a&_3RZWd zJ*B2VsGIrV-gk1|EjW{GxJ@&3A=||?Mm1=Ih`@4&IT(;LA;C#&;GqwF&HO}hjtk-D z)I&Cwl%0K<0cXZ-6#n;wA#C_vcGTgCUsPurVX$cOOCBF6HS(v9h8(2eXEeDBVucA( zrb34bjF?v#e~kkQC=&V|t?r}CDl%6gq;Vv^5kc*Y&ZTnJE{v9VlGd_(?ti#?`FQfs z>Qe4;M?byd;>f{)BdL74bCLC>WQv+3QKeS5d@6g|rBh)R@vM?e>pIoXXVq;AKwxB_ zQmG9=X1rTgz<0wACVWCF8Gz1tDH-+*fk_DMNe3j^$;JBkA4fQj$RV%t-U%WxutD^w z!25C<&Y_iYB47VenD37e2W-$(q7?v?13xhoK0#_~0gewIkG8t0Fz8dV7i^wP^-X|= z4|`(P`&l(V0s4C-NcCO4Y0R`r;k5&oPj^pntmjd#!=|0q{5p~Ofl7N0t{vVlb^>x2 z`rb$ds{~e%UkrLS4!kg;JUyTBJ3{e4-b>qj>$N1g1BfJ9l=|JIvTP*jToO`9bg4KF1#`me2|tP zk~Z;;%5wC_`jYSyDHI5;gXM>@x(^BN;mf1o<7l(^v3pld;Xmn{@=}kZsy&f=a4f_t zP*@W5Qlf&G`^53v{&rIuKNYq|z=)%F+lO7K_9<{}x9!6+Pt?iUr?dTf8pW}uK&w}@ zeJL32+|gJs)^=|S3j;FX7oNdx51UL^;BR)0ADWw7KXUXC%;=%L{!xAfN+;dgTw1NI z>;w(-srDt6HjZ3OTya*^%DD%HFL(>DoJrOy2a!rwiZ7L{pr_I&{MdiHn0rUjb6Q-< zy$K-neHr9)Fnh}@c^ZOKV3eWvf_hB}-MEVCRh%5Egb6WC+t#@RF0x#81_A4Jf`6!e z|9z?@sxwF8qFXxPf|?~ar)5}b>qM&|6_+(sgD3f!hUQA_LUpw)CAlclWi03WWJ2HL z=r&c96{%upM*zh~%e>`8Y8s|tWQL46B~@fD_GW{!(0s*FEiGvLpJj15Rmg^S#*B=+ zr=?RU=fIw{^?Cb-sb0$DTwRMb9HjHG@{#Y{=orgP420jw`Ae$d=0OYJM8f!Dr;|y8 z#+w3YG%C|0hGTI8MV_5|a&@x)SP*>nkxTsT$oWmm9l8+y;tlBYsC+ixHdUUSreKywO-LTXo5Skqvw2u=)u+H zDNgOBe(z@@1mMU)PLJ6*qUfk8AgMx(Rmmv1*D-*u+c}2=Lnm?=xj}9I8F%c-{5}z) z2(ofDBc8zXP;_S-_@bm+S8`xTz?ClzU_`n{u=7OKB z5c#u2s+E===3$;P$)HicGRwN}JwbV60Rg>@mJsFjUAbNSGoMZZWSyVV7_KvaJl~mL zNkEB}i{2RPPNp+>2RY%--WONbc^;5AzuVf+c8@qKfZvZeuu-4&{#0qiy&P0Ax&ILqoj8(Bd9XYd-Re4@i(8FR2K>C`N z#QzwniHep1?*{7x6UleD6NK3K?2vz*=yij7=!Dno>;_}8(ua)nlGQ2GLEQw z0a-xXGbO8!IriC<*m%M~w4FjzdAE!`I11r^c%_n8c_`-=?&?|+qsT&KnCx4gP~VT< zz=&V#MJ0Ip^rA{?_#wsNXm-Ra#|3Likab!O{f$%BJZaIKaAp>boe6C_UhBNU``uH1 z+kotOLCHy_y#{C9n+=Tn4(HqB@q&Vl6ypy=9h}WmbS_K5K7N#E;YaDjXwjX$2S;JS zAsUoFwn>gqRb8)h4kb`ToXTZtrx8x{>23yXn4`_N1TK=dbaG^5ugp5~*0Ms7NRvj~ zp${U&P&ojI8V#=8VX<9i+gTm574rlNP-@m{@@*cgGi=uT0r3Y?o*8>?+riyS;#Z8C zT?HeCpW`_dx^u)J1_JGY=9Zpae)14kSrk3qz2~w67IflL3g$1*_4x5zA<0IIZ_!$H zG6d3hGG!O)ov00Oa^yIDx%3*6J?W-V>s?kLb4YXe%S3HKIUOiP;%u$NP0JQ?3V(Urk1+ce8OR)QFp&>pMvf{4Jfk?Ug+yaMnl) zUS+F6*vKe&mMvoz8x50PJIG6y5tp*wpTa{5)8>14GJ*Nc^C@2z&}X_8w-#6SSKA}B;(A@A zC(GlMUDY#`ed4o14!NU<*tSL;Yxh@i{-DQ6HTo)2T1dPg9L)#8G`cS~F}Zqzt5Ytr z2cAPQCj7eKb%H5P-CLv9cV0&O?5~^EW;(t4b`HY(KA*3-JqJFUIB144@+D?Nfc2}M z8spwtTCpS$Q9^~Pws(ULr>m?Tg1pxS4RBNYi#tJ7$0`_~a_P_7*>mG_iU1tR{F#== z3*$);bqYl##`xOTJn%wSq*i!6OukV}Rn-dmJH$L`Ij@W-#4n=1yZX?9f{}tVdtK1% zBYs%sfJ}JLI+SNUa5X4Wfj9Wat^uPV5EQAL-94!NRf|2u2AQ*k_7u3qh>k!KPJ7a} zi6nXbvWjM-?Q5=rybFLs#)uDRiFPTr=hiPh$eO&ajH194nO3h5Qn9R;5LwDd<(U0C zN+OPP?(_K?>L+emi%?aL1;KLHU$HO>W&8wgg0h+jER1cnB15*?HTiZB-%DF)k!04$ zg^}H%8ofUx|GiWA8LLpVw?9wq(B*+ykca*(hsEys&FjQjan}dZv4>gV8Ly%J&&c$= zfK~@VvxBe5I_tZ+<{-~PQ}0+F-fzJ=U&DU6FyZ?Hn4(dr(Zt{AnAOC=v>ST^`??V9 zJuxkU>ST%!ClpL1C~~jp-LMFQKMe;vEyN82Q5)zNZwC#`cT(6ekqBp@jEEX##9aIz zYtzwB3A-8+s{unRBs3pa##L@kt2^HYpZd^*>DLA3RaVQ32%w_d;Wv~x9ekN>!+FVo zrvF6bwA=3FSvavU>JF~tt3#ocw`KK-Sd4gGm7-H!;ybg;m;>DotD5zJI9KAR``l{M z9Ou%60W|UTt7@|1IKjh*$kZH%Q;)7)_dXxHTwZ1O2hlb{sI4CmfO4=4QGOtVc#;TkbuuMs1@=FoZ4w_0|&^X;(9B|6ouZ#hpQqEwQ+`JhXw0LmA z90%kl=gzUoU6VT5pgdJKp`Q`4-A|!iX3dsyqcg zbH(BM0gEgQ(LRx8o8r5`uB->(x2zKVudtz^4ei?KN;$+DCO-7?QoIr4^M*A;Nz+?6&@aID`$}Vd07( zj=-xh2>pc(a%X&jv}eL;o_d@(K7Ut`VpFtGH|KoO^MX;%V1g3i9soM%*Wa=+52Klv zi+14P&S#j5xO?TRUjO1&C0Jv^iflo5oO|a|>*U>ARmkipCE;hDUFbKxzInh?iJhgG zZYG@I!i$CrwgGT)V~yBToP_mD^7$h(Id;g?A6`C!C;NXGdORE7K=0lQzcCiXx%p^; z{+Jfv51ll;Nng+2Yugp*au~eU6Im{DoA&3*YH(X{nMUKqpuCcPKKqm2-P|3CD0^}{TcUQs^wYvjazmzMYXK+9pcJsDYX5yZtUHHNJ|m6wx5FC z#~Xd;F+1>reimvzzlk?8!KHqeY=MeTQK{pnb;w|gg5yWJ^dfz%Uj#Bo zlEq>KjC(n`fYMS~H4dISDE&c?#) zAby{`S$fnwm@T-y{E!C$F>VG+ty^xt_j$en{d?2@iVtVD|Qgf_*yIIBFNXT_mDI}c&gWYy2MaN6ZOZp znm*2E@w^+5dNi$u{yc*syQkq7zZ>n}v2 zI#_DVQN#4l^=_@LVY~E}8EWG*v^ysOY9~+IzMbnW3LbjYix zs?x`6E;9GilU%I+4JkQC#`PE}&bsD6m85mXCzNjfrBy3A0s&Dpg2x!F> z#atQBSw{%I!%waGO=sPrWjBgSzwciM3{>>ajBJ7ZVJc}Ur&F535mqmF*pLrf$!ZXuO-eKcWJDJJ7(k-_1Xzt=dE3HT0 zZB#eWz_H=3kiM8gZ6QM3`US>BG?kYnP+fk!4|)Jvww=)RFNje-?jm;5Q@^995A%V7 zY`J(s3`#<`CYj`AO0Rj?OL0vpgEcZU<6r~a_m}OF8&woXpJykbFC_tTa69U_0c-Zj za$Dogz324)$&VWAE2$V9KCLNlL=PK@Y}lV9sWoQKelMIB44hD;r#s#&)j|}z1&fJcuk5BWcP7Z zhCi54#M-2K;v1Q+TJq9{?VGtjzIL&L6lvG?U-52xojq0)FzQEdiI>zH^rZSNYKeL%r-9_l2S8A7bKV1OK-tf5k+ z0=7(@uY-{MQjyvBYF2@1~y9H~=w9k*ZO7>Zx!=^_Z2*uu9M`nv=_=wX*QzIcdBuGQ~f%aiNvJ!87G ztR_FXyj^X7pu>^!TOhj1WFs)9Oq9TdI5eeb+r+VYymP}k$yjFT^OL3AvP{=3J6Vww zqI_=00=BE5GnK0PCI*EN#+h+w5t-+w*L(xH0#Y-^pVNu8K-gT9Mz0QpH7cuws9qER2M{EeZWF zMuJ!d2#1u~n*CutnQM^6P)EU*le(0?1Zz_J5kL3Y$6{ikq5g6jON^J5oDLWm1|Pz%2p8| zUeuh$c}6D)mWO)8;;!Y_V2xg|&;fqOCWRil7c}->-zmGLUOpVjN{r#1`R&VowMny;c0lXZFTB2V$>^o`cLl@fu5Rp=b z7!tAQwFSnAiZX13mf^j+No>*j_}x0hv}D-S@-9rLP-Ga(*y>IZ#8shkDCf^ zYmmTl)jQZW^3rnR%7wM2xCgm z{kG#x`N|@np7zua|EvnSrxDeben7l0@MT9lE%KfgbY+G$QjlR!_!<5~kR8}blJP-T zycN9bT=I>EeVYl9!$ye#dc0_Dc%vv=%Qc2hmTpAQWuJix+<4qT!jSUuV!k!d%GvbQ zJVA4e!){@?47}{4xF`MMN%6goFx@A2>Z}qCaJiDRAb?!jC8Lyxv)K6hqrU8Ch}HIG z3LOQAefrPY+*^O{&{3tQm-ul!a>rwp%_3o$YH|zYUQeW+WtS!7hGi@Q2I*}D6O_;3 z!f3}=gy9s!1r3>n=eVarwQ8Tw4;;30@{y7lQ00a2Ygb$!iRUdCeLbGvb=Feoy<)sw z5F>A1)HUNv+6fVceZn(-S=BC?7lPy53|&_3ZDIWKqr?n94WJA zz&Tc&*cnAC!xtLWi;xX2xnY`g`7T6&fCUm&+|8<*zx^HR%MxzCWOF5v&|IC`&N6LB z%?YyU2@h&Bvi<>V=z|4)wd1608gchO=2|R|3L0(Odr@RryntX=i(0T8Je*%quv3jn z!w#cd?jee&HiKw&1dqVxgf;9w|H4Dpeb4z`#qDiD&lk=F14;_%Sv%v5y>9Dm1seN6 z-VE4Xx`qhRnETQ1WYS#rrnvF)F62wpJ-Lv?^g8+1e=4VgH+E+jv!6`K_IJ%KvYRR3 zQA??zvR`^5?<`#I`re{3_O8rHzxzKmU1d-mOSi>cg9g`dAQ0RS4#8c5OK^90cXxMp zC%6W82p%}Nb8v^p{qB8LQ}bhfOm%f{Uwf|}sK&vwK+WB|4dN0YY!p|qpe9g?iBNF&@kHW5VQY<;Tc2Twnp)_jk4W&g`*NiJkD3iVxI> zczuX3W36F{ZE;|&CH42IWY!4_1mc?~GcAzeWe`+s4+>Oc{~P*fKcovJp*10mZ%y7% z-VANU1jBr&Q-Bf*1L^{Zh5tfN! zz1DGTTt}ury0)_;DtUJ1iE(>D1Lnzldw^=%hfQB6=en&RIh#GBJI_~Ull}Z8XYQk) z7wSh7RiGiw8WA6?Q144>)-q`}@X=D8UR|#Q#emXxtNo%4tHYTWabal#Av9Q7znF6m z)%F4{0QoBfI>netd)Dl;N*hGq{xjO{R(PiBa_9wX3f-J1*NcK8C!KM07Hn`8l05w% z&=$XzTcDq(4+WCzyt*-`*r-zZ$@ZMX;~c1bGpCK|dWvrkmsoI8=&BS1gI>zf2J)IN z-8?;l&ESsGpc11uc+-EEcS3q6Lu)zspXwNPBqH3?=N1 z%IAYGV~Sdde~6?`IgqD;>sJwAZJa-=Zo&;jf|5I=m@xYi6amHlvW7Y`4~^nxC7b>D zbcmiBGSFhB1pC|w9;_xf9r!YyQ6X`OxWobXUNSA2YP$%U3b?Ie z;_|4iKu~V8A_fglEyGUVoBE!sUZg$r)BL6GEA>q-kKI47*x{ zypj20*Y6X|rCGmFA`z}}B5D2!AVcU|KvnRJQ0P9@wXQ2>QuQC!B78PrnfDEF!rQIO765HdI)3La1C#Y(|3 zN^hZXt(lB5eM4Cfm*wG~c%m{-P9q(~=q@(k=jSQ~Hb^mNd&J{$YOppu85mJ=`9P(7 z5?S@5QzBTOmg#zIrIsW*_3`pvz^m!6*~AATZpKEiADL#tC%y|xI3_={P!(cc5UMzF5`=#~ zQ%&ojXT(J03%~vFwApt9`eStrYE6R8G76|cIb<-V#ZW?BQ$Qfk-sJ1j}-Dic>l$58vQ#)Hrw??o_Ei`1OL21Fh{Md~?hgaNMT?kxGi7%#j z{lG^KPyb>&sHX8(VPhw60FDmTKe?ym$%ZZWpO}3)Zu$TzUB=|8xc2Fm^(yI9y0{{t zCA!|lr?r)_X1hhQ{J6!VpvXgQnB(D88*jE&)WX$I&8?A^te*d1QtC$b zeDPV6#gI(IV@E(ooj(l>%2B(4g&`3Dm*6OezMQrC=S=#?3Vs3=k-Ne)^Kjh~03h$X z0TmI6a3f?0BnX5_7lpl@XtODWZtp{(n~D}}S>ald#g9_OVcsRz3l%R#di5^HtU z&$?a*?8#}t;Ig&>} z>gRn1d$FU7E^@vIh3bu7NIOh@T)s1dH*-DG#h8uMZ@1dOQuqGo8jvzB&mr2~ z3wZTZ71AJ9Wd_xS%R&$k2lbUbH@L>#$Bztq>z>Hwurca4ypYbTv!etND51j7pGh1# zef2YPLz}ON$gji_W8L=WO`_blO|%|GwI4^`#laCa!7a^DUlTKfT9P%v1d_M$EdYHx zA3P44NuEgPjMO+aPuiQCOOlnCU#R>iuos3I{5`oSmxDVOPMAQfH8W^z68==X?!ZqT zbK1@KT~2ezoktk0Dx)h3&V&lJOZZ$L<4%3FspL1>2-=}%GDYAzW(5>8m`;a`a=`T$ zQ7p#XSBsxKuM^_(DMX>Yr9eH+a>44qf;Cs41;r>-CTYNZJ**{2Atn8b4!u_{Wv9&% zSYLGoX9^Qr!#!Pv@3eH+d(olc_%74#PVJ1|Ivt;29Mk!29yxSCaOd zL>R#ya7nqZ_rucfy{;}_-k-BVF4RrcVgO1-v4VPBUheX@#f2}q(@vfunh3L>jcn!T z_}?#m{z_tMas&Ka8}uOBrbEai9M?N;d%4OD1SIZfiiYz`PZx8(X}pej-{XxA6dn>7 zAyHb!ByQ4my)<8B z&9FJAz+o3pW5;iaC}3UndEob&S-`aJvA4x+B`#7jsk~*6?Ze{#p#XRysS`|NMs$6* z|29JxJjW%3AP`YqS06w>Zsac9{M~Tk-aBPp)Rz*bezPK?-7l_LPz;+Q2OxSF3Q?v& zNS>6F#mCreZOf9 zlb>JUrc`rQQ!dMNBNg*V#lQBs_`Z2PPMui)$(8-g{c5 zdM}aa(Sa)BHcWMmG_kB3ZZUB`|Mo)=s3>U>F70IEXLlfWnAb$=mSr?&!Yz`a5M()7 zCHovjKJ`6wEy>eJjCoqO{yzRpT6f*DaUeT=GtP&|=j(hS9ob$n`6Q(Ru?AxZKo6OO zyB3X`#dI5+DXa1e*aCTwK*hp^*iaanDL8XWs8_5u{IfBa`L0P8x4#Fae)04K^r}`b z+IR8a{{aAlVpMG?-Gs&u!7>Igmuc7r=$S6tu73~|H^x0ci^!n8LcwxRJ3HX;4nc_QY3~lh2Gm8gTCAy zQ;M>(hI(6gPkwZH(UvW;sE#$oqcFf1*3EtNb|cfX?)X33$UufNaU7z^(UZ>I4hzXn0tVvEKiC$C|kdB&;ZTK_bC4wlipXwSfCOT$AZ z(XJyG>fSKx%7mf7^Kol#f{U)a;LzhYXQg6dt3niO!hiCwt)J+cW)H-P2LSx}?6gHR$rGMfdgf*a~w;Cyp4D)CqT!I~%8|M?N9*)LA7S1Re-( zoxQoYLHgv4Xcci=u9-AV#@uk{;rLw@#-T|p1 zMIZEp5Ii~*Hv}R((|yN`IW_cY5AS`-QmL8)*(&-UQi~sySVXu5--FjjmUbE&Rxt11 z1{Fk5t0BHNP8x)w%SkP+X+K#H4s74VArYtPXK)B3!{ZKY2^P{-_z|KysSa!mt6{?8 z$mk4B59S-iJ0juJ1-~3sQ4qc6e1W3ALP$r+q7R~isf^;gZS0}%Gfn03e<*338CYv2 zTmvk6Tc>z3EkUDW-Cd>eN#5_>kgWVb!pt}t@aA2CjTQM?H;XFLscc-B=<%874nve^ zp6U$98g{QxFE9DLUv3lR5#cPu?k(y&eTRKB*c%AvF*|n9OY|9zFB2z+5Y|FEa*LAy zqa6)82LaOWQV6(glQ|!aAf9%Ko?0m6iA+uunf>g66w8g~EPWVi7SYH&Q zeh3bY{$9D5PfY){XJ@Y-sy(tfeLhA$jKOeG96Je_Rt!0A)6KZ<+s4XH<<4*674NW{4mNIR(kUdLY(H>c@qoMq>reG{AY@*G&=_! z>ypi%wmE3fPqw6jAfl`tx^JZL6*EqZs?e_h2}G$yhFw`_u7MVj6a*)Wk&BNBEw5Io z@bnu~1G5Z%rxMJNigRy2```4X_>&IP=KLJRMfiqp*}GJq?_qB84EUpeyUhx2eg5@| zhR<)ud;Ohl%(#q^K`2PSkV1lN*=|cHt?Zfqt7b0{h&f^E++0YKbNkdkyveRt$&0n9 z*`-p;sm|USr)q3C5Pii0L(XW5N|D77Lh%#@5u)08haiJ;)mC@4P=TOIsX%@aonJYT zC^D`x*lsRE_7nrhzIe%Jj}A|soH~H!UW1_(@*6U|JKvdQIyS%Y>Tks0W^MFTV-3NxBX=X5yV-up}M5p`8W%ZuaxnLYvp`0%) z8MCAvix%U>4e|=M@t5y^DYJnzq9GN`TCToUYqI~8#=|=j|Ea(>N1BT_*u&)t^7#f1 zT^^vcXEiN2jrWl;5HQ?HdK$qjWT8S59Lg1<*)&hVky@*aZ}Fmr1z>2ykh1KGT)nk{ z=)k)u*4xH<&#^kOrf+jJf7$h_7v)sw*g4#2YY#)#Mj<42&qa6Rku>a~J|Vj*1K4RH zs8!NhgCo%JOGbqs>EWontVmt_%4UQ{(n7tbdP8_!xgNqCHY)mk1xjGO_^UjQP+~pGF8J-Xn;)r1|xa;D#+^AWtPLei4cD z&*$YAM9iV4-9fm>3uC)X6Y2Jhv3<4qmy#ZqoHRf6(U0EaG`cg=PvKQaLfxitq;J#_QblJo`@A zS8CiuaNM+ygaov6_J9D#4nsU_;0{zljPB&!EiP+UX%dXG#}ey+1J-xHgl}dFZE;KE zY!D3_8{U@v^i$Y>Bp<;f$-@xsgW`mMX45r}#v#ZHfZ++md1C0AgD8dp^!^5@ioV6r z0lC&43jsjwm^pV9G0cl0mSqPOl20@($&=IW;gDG9o+4Y!3>;bI<{7YJi*g@xP02Uq z!!>RSN&y;-cua0&L!H5pRmY2HhK`k)^0j;r?!dj5d7X*EG^^|A7vTVR6PMBJ*_Ib< zd)Y6{B=RUT^H(tev0Uh_P;bE;kVdq7-1G6TL)Y6X{hsIPF4iIe95K#rct}y}8)sNN zuwESZlcuX~Q}VVBjJ)-4`DZmk)4{pFY*!beX~#hIBjbsqOqD>?c{z`-oh?9_uYFlyP1!OujGIF6Cjs%4^Jb_ z+1tPh?2J_;hxS@{<`)x1cZ4H0djEG!TDQ& zU&RJPdVZM?<{4jz6=1s6npqZBddU<&*R zZwTVGHX54YSQ7(t&&N226F#_%lQUl0xbq|Ro6$Cb2)g4SYNqeZF9Xhc50p9_rw4C& zx+d8da7DC(*r^xO+Hi+?K4w!5p20ur*Po@Gqt=_IDM|2xrYzd5>< zCFAa`;CmJ3)-wYmHYw<)(3vCW!4TeU%^^fO>)=_cAboDMxc^1&0sxXvB0w(3gfgNF$56Fvn9{HcqvCOC-~i#a%q zwe6c|N(c5%k;ZZRwqS7^Ebsl$iYDoFbU3NM6m9D<)*ySZzzQcm??#Ot=CU!Wybo)? zL(TX{Fgl?tScv!AYE9dKOD5JC$I_@>VTpyVYos-)<-kwr?R^4UU)nyGCXYbiSCkf| z{#Rlwg;wGym%%i1Opk32zU&f4tdk5mI~h+Bw^bOv$&k%oO|S9b^Q`p}K0KJbsaE&R zQhm?ZOF6dqeaL_|d2I>1kA&0Aj*X2SK-V|i3$G@)%6_-$%s ze@Enui9%PaMXMc&Pp|F%jg|&nQmu{K@cg}RS3Et^KHuzrw46X@&cM$xHVnXRy!ISh8F~6*QB$6GPw`+Z4l4j zi_z{_vCO+lXrs;_p4J^uh-W!xFSAc?+}CdWj`Pgse-d8!JIeO9u16g3?lE&gZ=lm| zw!|)UAOg*dJ^=I^JV8XNTTVGumJ^RLfX*`ci_5BrF6^O&?fkshe8{s*4-`WnWYod1gi9 zQ)y^HZ&nret`|>mV6=hebL?odHk{cIeG*QzXF=e$4*muq@0Inzwa_)B!!`Vy#|vdd zy@2Z6eKz;^UbG(79p~tiG}NHyXDBm)5;3>G+E(h}7w2*YoeYBTz)u}ixJv0WSdHBb zYXT`+@`WL6j!Ua#9Fd2T<+shE-eK(iy702WniFpOxZH2vlbK7yS-SdfhI3XuEs`! zuDL~`xfksh+GLIZY^k_o1IN8xAYbIV0@3}4wNSqn`U}%K$roO_s!I^oj^G}g#3hC# z7sU9BW7|VD=930htebEg)euZLw)lGMsdF z9#u13I3><@3-p$u2uP0ttvlP0RZWYEo^BzBU6Las`s4TzE#;#V@s(kCTyHVJS;1$> zb#aQ$o#uMOfJc0Egc*#rm`AZB7P`G(3{1wG18K;~T zUh}&S;#%j&%mN>6%~Cxizio$sVHVDCUgGPL*z8+)ffCR8(PO3O1!KV_KXQuh%(cc$ zg9a0;2Kd-{cf&s=(esGXZC4Y@Z|5jyS+e$`4TiIBn4LgnoCvm88My_7vBhUY|9b8!gJixfzv#6u8W(G zCSBe9Y*r5A`tw`?9$aIEG4_NPiT^O%*GyA#l@QXtx#rS71WLPORklI)uo>_NyeW+u z8)|j?864+xWjt&e8WQ^Z`jO~5OTDeOB^h#KtGIkefgM+=WGH!cgcr-6F`A30>0OJM zfXC*tK2rD`5oyRxkWBD<__+EB&sSyQ4xj$Gk6O5Bj678Y0ap%s&5m%Pu3=!g&&#P6 zw)<$yxA=!PpH9@PJfib_>mtI1@2czHi%Z3&bO*v6JoYmjGcv}?1t5+pclnSyFy1mK zN)MbIzX>YK&AA~3HZf@IcYJj3@+CZKO?gz-O zsbSZp?|WJE+nQ&RLViZ9Pc&38<2e{s&bj72r{snEK)gJC$)f^>vFGtwF(FX0oW`NX zz9Al?B3P<)_6GKrv(AtYtfNAySMgRgs0%=$o4@SQm|P?9x%`Gp{Jk?PQ)iVa6g#>l zqGE|fg2%xTTY^}N!esZT+iUJI-M{X3WJ7l@7})fEo85@If)a>X5Ug3v95PNkzU4CG zCdh%Kkf%*iK}U0}9x9u>4tNjk{NO{CZ`L$8F<;2;;J*gBN~BhQP*(=!1kE&t=i?lx zvu|$U4XUi3&7`U2nQ;tZiYT9R)7B@;w4A&n6g^S7G}K^sT*I? zl5${iaYIP_V=e!K9x(%|QU7r0^nLp83cRFJ4(yBjv!RE{-JMMwrO-GwAy)H@I;YuV zdc!gU&hGORSuvb3Uc@e&W_t*LPIX;FQjwVqBT=H;A{8l3LB+unCJuXW<5_&13I~o| z?O~t}pCJ-^ebQ$_#&lU8r{FdpJk#o zU5^c=&}=Dh_^lUWc-fiN1g43cpOA2oZ~!1-4KoKBNMPnuulrok2(WaROFY-ZUy!l# zJDtgj@BgeWy)QDP|3Sr1o7OEzAhXC-{Yj#U)=H2C7Y;M0bR+4V4B-RB{dm^0m$W_X z%mhlUJ0xkXD~{7gAGp+GJ@^GNgd?Eu0BDaA$3r{Zs_K{anI+u7H7z%Uhzvl@?-Ci6 zP$b+q1fe^88BE9>kM9l+hs^hTlCl|@1x>8k>}aUv29|=x^#}Hwv(xLhZ+r86G+t+? zs~)y<^=F8534(KCu*eBAJoEXsaR-Fl9M-84vHvY;PI+It$K@zX#~!^T2fAY0gw`5y z5WxN>MVJ%=xgBQQi#^`5MKy*YPVC|b#y3__>5C?eSj~z4X+QxqA&Cu#!3jtzdF=-3 z@1Ms#sE>uoCr!>@zCyf^nVDCc^54dsVH22wxKJkb z_0o?Gy3*j@fOR&%kiM;+_Yce^;(TGkS&?z(7-qS4v04-LsH!3~ufet$WKfdhlg9c) zLh8}Ii8Nq#Y!y_BF*i-3aW!yA5`j+*Bn7aP2d8_@W|0@GkPG2*^2;*D<%a$L<^%+{?1x2-`+TPkq*)vBWn0!Lc&u}ZV%zV`in|J7!2I*L8A?x6rfTzNYcj#-MD{C#5YVHy3w81O zo7ruID@1a|=X8jLqdsVjlfdhEYYm!hh88AAqr}P=M6VziBS)7!fV8!JQs}{BoE(6X zzyjDs+VzMF8Z zR1YCG`Dlse-xq*cA`PiVdASCqKl@(0@D%^5(do}4_tUwrnK?gr_hS}+nF)E@LT`tO z(gaM6;`Qn21#^Mj^@(=??O1R#(UaOFO^`9*b+_%&?B&@O)bxkLs(7=%5Ge;YA7t@( zb}%C>dXP9wOsL|MJQ0R;KfEta>;n{wOb58kpRv#KS(a6p$R!)8L5@+|L6J=Vsd0Zz zQjWNy8`Mmse%IE%$h54X#!)s-+(u)*;0%na%Kvm zdjO=hhf|p2Q z-It|vol$OWFO~UY4O+DoNex@1ts9L49n6jtBZg|J&oFqlzMDV+Jc_}~+2*Gng$j=> zR?3+#`lVt1g;l?z=}5-OYRwC_WGr)A0bNYv)9X`d3g646fL4sMbCOi3GCQY4BLF>@ zCa1@^b&rMuq2Fc~3>ui62R7A1f4g_8b|HHxWo4~=ks*qRRH)n z0Eamqhy_zThkz|e*62k_qPE&Cvi4Ax-Kf}RA26P;!NC-0MZ#nI!6yMBB2B>_KH_25 z(N*Rc-_DrrWBx3$s?A^Z<}yF2wYq{FjDA1yH_>k~f+FH3hzKO9jQt~laol|L;|zjy z#*QKcv0%-AX6l{z&jZi%Ug|%VBrc7PG`$gSDXYwwLx2>kRqiK+4fFMDo+qD#eXrH* zpf`|X5b|2G2cCR2HnQLGocAxY^9nKPx+-QM4QYENPB4f?%!)oa4@Qhim|h5bg}FE% zeq6IO9R?GPB$4W9NXz*HvzsUxE79hKczKgpV574Z7W@2Rom^-*v-;|X6}(!E2WfaO z=9AMAfj)9?W(Wawl*I?}xl5EX&`&NkpiX&N}GZ)(T-^?{0AQ8 z(gdS~o3w&U$z)@d;vtZh?TW-ReZ(X!#)R?QZRiC}&`^t8H9D8KxbAlI32kj{hRXSG zW>=_Ggs_8@R(&qO^ec!(0p0umF)kOz^+pE`NW=xX>Yf3>vLNqatFcpSfa z(&Fd0Uc-GQol>hxEQkL<#$Sf05&GqDawyx{y^#g30As!J7xT^E`qRZ~bQzT0s->?= zWiWy`KTUlnB<;CUP*&X#TXQBnSI=&(&IKZVdy2=h3=4#?@*+}@|GeHx5CQ-q{hkuA zeQPCodWl+B8xY`s0R6#PdLOc?J(-TaD0kE_qf^sS#T9n}WXn=h0nIVbK->atllE5l zl}mXip*N{lDeLp_=U$t@n*F^@tp9mU43|%ojvn0(;MMPWH(9x&sN>FUtLif+`CtG7 zpt^d=Uu78R=1Pp0u<#R9-s9ebFbxO1>m|PCi7{>0AuZ!!FRoE6W}~wbl$CMMkyjhb z$Qw>N*jLkzL0Gi>d((XJI#aYR`Jad8;)SE&lh?kk`F^|_8KY&+v*5OH-7CBz=?VF8 zQi&1DFN(cbPhXdWszcNSPoUsN)qm~ab=fF>fG)TBoz}{6Q4`05FL!?B>Jg~Y>F4R6 z5KuzPg_~Sk@)Hg%3UnDSck!DKZ!{bGBNmucUj^m<*!R(vvjQD3jFU17Vf-~inK;sD zJ3bcc&`iJiJzU=R1rLDm=a1ksUma~V1KO`kv#4jU>?@@eUZ0yM@fhNGt;eyK{Ymjs zzFL+aBJr1$sD^-)k`e#F`_+%wg1UpY<~ZdltGpLIZ~mljtX<$4ytzpi4Eyi4!ho!b z4<7nN9GR)+|E7h57c6&X+>fZkJcuRwAwJpEnbR?dmqU@J9&B$c`T{{%(2=C1cn zYIygeFU%EYp@^&<%`IqP!=On&5&KtLh1q$=Mi7`S{_eY9ko{ok8a?CnM4MdyYxgzT z@Ych6&fXe32cIq(>Ha!jg%g=!c%Q8mrl0AAwl)yH(RCkts0z72k|iny$mwP^;9fWEhnf`7bnJ zp1WS~M3aZ>nxZJy5W;sv|LlbpBWJ*Oqv*m$#pU)#7YFSHG%0=XdNVzr=MDuwf@Q*F z4fhAwYjRZ2@;Lf#9I};nh4{2WMkMtNzce2A!-uwupFKP02aCIfDT}H$0@6YX%EBv| zzQ2LFq6JHFgC%Wh7QbMF_?rD141bQqvV>Ah8&$apC|~x5U{z$V!hEggb=cAFrE)U} zzc#eM+8*D2Ayi6D%d1vN&Nb4`6Ip*$IeXQ7=h-K231d@)I zG^3H0Xp9w?FJgC4{9Ue<=av77WT(%Zyjv17&WYr{XwG_IRy+A8~XxT$r!+;=(KR&R4Q7kY(g&*qa0)534FSpbo zon_7_r&WN*ueA9A!nuM=3x8<#-6sfck6JsxnAvz$=T^j7r%^m*!?f)x=YTXvGtIrRM+vA z8?uM)hj>4_B;(%)1jELk^rCM*bSQLfS&OOoQT2_%{rRP^3w=$mQxW#In|O(HLn#bR z$3`Vi$-+j2x;tKDAoq=v zUR*z@Brd)Cu*i5NKcwgv)#Z*=^tkKWv)IFd?>i|(Yrv*hFLmXSCeeqIae8FOuy-D1 zb=mDP_H!(yC|yiK|yzV0=^ z{!j6P&S?4c-k+BCJvLufojgJIVNkh|xMoCx%FP`2FRx(eB^~&wH_m%lipVr|kt2)3 zlZ4(RO0Jn)L#0!?;*N6imCs(NQAHzr@feh%nO;8J5h^|x`NIRdENpGxBopK!%;XXz z<-Q3@(ncg2(b_fr(U8*ek?HPv$-491(Rzp9bT>flnh%+|xbz|gjA9qp>Rd|OhF(vV z<24u>$G0{-?9OHbS9gp)-g7%~4{bJ=S*`hpaYnPNqJdekNjV}{j+ps zpYv>pgDmK-(jLg!dtDgUO|CZEUl7Lv&r^LuJ?=l@Uc4>w5&ob^42De@1zt_$Vc*Qp zecyipSgJTIn6Zh|W}`kZNH|->wCYn;IPoMjrh{(?+ftO~)ZG&N%ckm1i;5BCSej%H z8d#|$-B;JAwcYq%24l03H=k~R!nrSp4pqYfV0K6L+ynu{3U^J#1D0OWH}j3L4R6JeAkM^=1>K4F-s zyRvT{@P>#ZyrwK#X&%nF6ew?|;B)0&jLj=;jbW{n>HGF|WNK^GOqaX8FtP8Z#iyy1 zXk&JLfqjLlUs=>Pq^Q(Mxbtkt1-<*Z>vntHG6xl}+u7Hiv`R^8&4kuQjbE=cX*C6p zv#t@FE9PqVc0m#totanhxoYqSpvZN-8$i=ZgI%SOy3l7bg!y%gPa77DzCcn z#~L$ewS0WS-8KC$8Md-K%J;uTX6zK)D?P9y<1Y`Ti`-irj_`L=l5+kkKqnRg2PJH5 zyG*rL)yccD8)oopMZqXy8^8yU8vLha~4(oxpS$HqM3O&EHYNtn-al z+ea&#k>jy37~N^nJEu7|@?hvgfLoW-WJS8T3*7jR*pk6yWU{C+{iEjeg&RGA^%MAr zUwkXN-^?IB?vXg0HXV!nyeo!Sg?S`2su)4gkwdofnUGK`A=m%E6`d4|FDt}+k^afb zO~#EBYztr$@z2)&BQrlsf2CXme>V@OtekJ%kR_ZZ9uP7rV50AnIO=a1k5aHjzw_j7 rENbfR<<&{One*T8G9P>);UGTExqJ;z?KS@AN?=JbInf$n{eb@i2V%j# diff --git a/asset/js/script.js b/asset/js/script.js index e971e97..fec119d 100644 --- a/asset/js/script.js +++ b/asset/js/script.js @@ -13,6 +13,9 @@ var currently_migrating = false; var profile_name_edited = false; var checked_licence = false; + var show_prefix_notice = false; + var show_ssl_notice = false; + var show_version_notice = false; var admin_url = ajaxurl.replace( '/admin-ajax.php', '' ), spinner_url = admin_url + '/images/wpspin_light'; @@ -42,6 +45,33 @@ return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n; } + function is_int(n) { + n = parseInt(n); + return typeof n === 'number' && n % 1 == 0; + } + + function is_json( maybe_json ) { + try { + var json_object = jQuery.parseJSON( maybe_json ); + } + catch(e){ + return false; + } + return true; + } + + function add_commas( number_string ) { + number_string += ''; + x = number_string.split('.'); + x1 = x[0]; + x2 = x.length > 1 ? '.' + x[1] : ''; + var rgx = /(\d+)(\d{3})/; + while (rgx.test(x1)) { + x1 = x1.replace(rgx, '$1' + ',' + '$2'); + } + return x1 + x2; + } + function setup_counter() { var c = 0, counter_display = $('.timer'), @@ -77,9 +107,42 @@ return r; } + function maybe_show_ssl_warning( url, key, remote_scheme ) { + var scheme = url.substr(0, url.indexOf(':')); + if( remote_scheme != scheme ) { + $('.ssl-notice').show(); + show_ssl_notice = true; + url = url.replace('https','http'); + $('.pull-push-connection-info').val( url + "\n" + key ); + } + } + + function maybe_show_version_warning( plugin_version, url ) { + if( typeof plugin_version != 'undefined' && plugin_version != wpmdb_plugin_version ) { + $('.different-plugin-version-notice').show(); + $('.remote-version').html( plugin_version ); + $('.remote-location').html( url ); + $('.step-two').hide(); + show_version_notice = true; + } + } + + function maybe_show_prefix_notice( prefix ) { + if( prefix != wpmdb_this_prefix ) { + $('.remote-prefix').html( prefix ); + show_prefix_notice = true; + if( $('#pull').is(':checked') ){ + $('.prefix-notice.pull').show(); + } + else { + $('.prefix-notice.push').show(); + } + } + } + function get_domain_name( url ){ var temp_url = url; - var domain = temp_url.replace('http://','').replace('https://','').replace('www.','').split(/[/?#]/)[0]; + var domain = temp_url.replace( /\/\/(.*)@/, '//' ).replace('http://','').replace('https://','').replace('www.','').split(/[/?#]/)[0]; return domain; } @@ -99,11 +162,54 @@ } $(document).ready(function() { + if( navigator.appName.indexOf('Internet Explorer') != -1 ) { + $('.ie-warning').show(); + } + + $('.slider').slider({ + range: 'min', + value: wpmdb_max_request / 1024, + min: 512, + max: wpmdb_bottleneck / 1024, + step: 512, + slide: function( event, ui ) { + $('.amount').html( add_commas( ui.value ) + ' kB' ); + }, + change: function( event, ui ) { + $('.amount').after( '' ); + $('.slider').slider('disable'); + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'json', + cache: false, + data: { + action : 'wpmdb_update_max_request_size', + max_request_size : parseInt( ui.value ), + }, + error: function(jqXHR, textStatus, errorThrown){ + $('.slider').slider('enable'); + $('.slider-spinner').remove(); + alert( 'A problem occurred when trying to change the maximum request size, please try again.' ); + }, + success: function(data){ + $('.slider').slider('enable'); + $('.slider-spinner').remove(); + $('.slider-success-msg').show(); + $('.slider-success-msg').fadeOut(2000,function(){ + $(this).hide(); + }); + } + }); + } + }); + $('.amount').html( add_commas( $('.slider').slider('value') ) + ' kB' ); var progress_content_original = $('.progress-content').clone(); $('.progress-content').remove(); var this_tables = $.parseJSON(wpmdb_this_tables); + var this_prefixed_tables = $.parseJSON(wpmdb_this_prefixed_tables); var push_select = $('#select-tables').clone(); var pull_select = $('#select-tables').clone(); @@ -121,12 +227,12 @@ }); $('.backup-options').show(); + $('.keep-active-plugins').show(); if( $('#savefile').is(':checked') ){ $('.backup-options').hide(); + $('.keep-active-plugins').hide(); } - $('.support-content p').append( '' ); - function check_licence( licence ){ $.ajax({ url: ajaxurl, @@ -134,11 +240,11 @@ dataType: 'json', cache: false, data: { - action : 'wpmdb_check_licence', - licence_key : licence, + action : 'wpmdb_check_licence', + licence : licence, }, error: function(jqXHR, textStatus, errorThrown){ - console.log( 'A problem occured when trying to check the license, please try again.' ); + alert( 'A problem occurred when trying to check the license, please try again.' ); }, success: function(data){ if ( typeof data.errors !== 'undefined' ) { @@ -185,7 +291,7 @@ intent: intent, }, error: function(jqXHR, textStatus, errorThrown){ - $('.connection-status').html( 'A problem occured when attempting to connect to the remote server, please check the details and try again. (#102)' ); + $('.connection-status').html( 'A problem occurred when attempting to connect to the remote server, please check the details and try again. (#102)' ); $('.connection-status').addClass( 'migration-error' ); $('.ajax-spinner').remove(); doing_ajax = false; @@ -197,11 +303,17 @@ if( typeof data.wpmdb_error != 'undefined' && data.wpmdb_error == 1 ){ $('.connection-status').html( data.body ); $('.connection-status').addClass( 'migration-error' ); + + if( data.body.indexOf( '401 Unauthorized' ) > -1 ) { + $('.basic-access-auth-wrapper').show(); + } + return; } - var original_body = data; - data = $.parseJSON( data ); + maybe_show_ssl_warning( connection_info[0], connection_info[1], data.scheme ); + maybe_show_version_warning( data.plugin_version, connection_info[0] ); + maybe_show_prefix_notice( data.prefix ); $('.pull-push-connection-info').addClass('temp-disabled'); $('.pull-push-connection-info').attr('readonly','readonly'); @@ -211,8 +323,7 @@ $('.step-two').show(); connection_established = true; connection_data = data; - - $('.remote-json-data').val(original_body); + move_connection_info_box(); var loaded_tables = ''; if( wpmdb_default_profile == false && wpmdb_export_with_prefix == false ){ @@ -239,6 +350,7 @@ $('#select-tables').remove(); $('.select-tables-wrap').prepend(pull_select); $('.table-prefix').html(data.prefix); + $('.uploads-dir').html(wpmdb_this_uploads_dir); } } @@ -282,7 +394,7 @@ error: function(jqXHR, textStatus, errorThrown){ doing_licence_registration_ajax = false; $('.register-licence-ajax-spinner').remove(); - $('.licence-status').html( 'A problem occured when trying to register the license, please try again.' ); + $('.licence-status').html( 'A problem occurred when trying to register the license, please try again.' ); }, success: function(data){ doing_licence_registration_ajax = false; @@ -320,7 +432,7 @@ action : 'wpmdb_clear_log', }, error: function(jqXHR, textStatus, errorThrown){ - alert('An error occured when trying to clear the debug log. You can clear it manually by accessing the file system. (#132)'); + alert('An error occurred when trying to clear the debug log. You can clear it manually by accessing the file system. (#132)'); }, success: function(data){ } @@ -338,7 +450,7 @@ action : 'wpmdb_get_log', }, error: function(jqXHR, textStatus, errorThrown){ - alert('An error occured when trying to update the debug log. Please contact support. (#133)'); + alert('An error occurred when trying to update the debug log. Please contact support. (#133)'); }, success: function(data){ $('.debug-log-textarea').val(data); @@ -421,7 +533,7 @@ $(this).blur(); event.preventDefault(); - // check that they've select some tables to migrate + // check that they've selected some tables to migrate if( $('#migrate-selected').is(':checked') && $('#select-tables').val() == null ){ alert( 'Please select at least one table to migrate.'); return; @@ -455,7 +567,7 @@ profile: profile, }, error: function(jqXHR, textStatus, errorThrown){ - alert('An error occured when attempting to save the migration profile. Please see the Help tab for details on how to request support. (#118)'); + alert('An error occurred when attempting to save the migration profile. Please see the Help tab for details on how to request support. (#118)'); }, success: function(data){ if(create_new_profile){ @@ -504,7 +616,7 @@ var remote_site = connection_info[0]; var secret_key = connection_info[1]; var tables_to_migrate = ''; - var table_sizes = ''; + var table_rows = ''; var static_migration_label = ''; @@ -531,50 +643,50 @@ // user is pushing or exporting if( migration_intent == 'push' || migration_intent == 'savefile' ){ // default value, assuming we're not backing up - table_sizes = $.parseJSON(wpmdb_this_table_sizes); + table_rows = $.parseJSON(wpmdb_this_table_rows); // backing up, during a push, need to only grab the common tables if( stage == 'backup' ){ tables_to_migrate = get_intersect(connection_data.tables,temp_tables_to_migrate); - table_sizes = connection_data.table_sizes; + table_rows = connection_data.table_rows; } } else{ - table_sizes = connection_data.table_sizes; + table_rows = connection_data.table_rows; if( stage == 'backup' ){ tables_to_migrate = get_intersect(temp_tables_to_migrate,this_tables); - table_sizes = $.parseJSON(wpmdb_this_table_sizes); + table_rows = $.parseJSON(wpmdb_this_table_rows); } } } else{ if( migration_intent == 'push' || migration_intent == 'savefile' ){ - tables_to_migrate = this_tables; - table_sizes = $.parseJSON(wpmdb_this_table_sizes); + tables_to_migrate = this_prefixed_tables; + table_rows = $.parseJSON(wpmdb_this_table_rows); if( stage == 'backup' ){ - tables_to_migrate = get_intersect(connection_data.tables,this_tables); - table_sizes = connection_data.table_sizes; + tables_to_migrate = get_intersect(connection_data.prefixed_tables,this_prefixed_tables); + table_rows = connection_data.table_rows; } } else{ - tables_to_migrate = connection_data.tables; - table_sizes = connection_data.table_sizes; + tables_to_migrate = connection_data.prefixed_tables; + table_rows = connection_data.table_rows; if( stage == 'backup' ){ - tables_to_migrate = get_intersect(connection_data.tables,this_tables); - table_sizes = $.parseJSON(wpmdb_this_table_sizes); + tables_to_migrate = get_intersect(connection_data.tables,this_prefixed_tables); + table_rows = $.parseJSON(wpmdb_this_table_rows); } } } - function decide_tables_to_display( tables_to_migrate, table_sizes ){ + function decide_tables_to_display_rows( tables_to_migrate, table_rows ){ var total_size = 0; $.each(tables_to_migrate, function(index, value) { - total_size += parseInt(table_sizes[value]); + total_size += parseInt(table_rows[value]); }); var last_element = ''; $.each(tables_to_migrate, function(index, value) { - var percent = table_sizes[value] / total_size * 100; + var percent = table_rows[value] / total_size * 100; var percent_rounded = Math.round(percent*1000)/1000; $('.progress-tables').append('
    ' + value + '
    '); $('.progress-tables-hover-boxes').append('
    '); @@ -586,9 +698,9 @@ if( $(this).width() < 1 && tables_to_migrate[index] != last_element ){ $(this).hide(); $('.progress-chunk-hover[data-table=' + tables_to_migrate[index] + ']').hide(); - table_sizes[last_element] = Number(table_sizes[last_element]); - table_sizes[last_element] += Number(table_sizes[tables_to_migrate[index]]); - table_sizes[tables_to_migrate[index]] = 0; + table_rows[last_element] = Number(table_rows[last_element]); + table_rows[last_element] += Number(table_rows[tables_to_migrate[index]]); + table_rows[tables_to_migrate[index]] = 0; } var element = this; setTimeout(function(){ @@ -604,21 +716,21 @@ }); percent_rounded = 0; - if( table_sizes[last_element] != 0 ){ - var percent = table_sizes[last_element] / total_size * 100; + if( table_rows[last_element] != 0 ){ + var percent = table_rows[last_element] / total_size * 100; var percent_rounded = Math.round(percent*1000)/1000; } $('.progress-tables .progress-chunk:last').css('width',percent_rounded + '%'); $('.progress-chunk-hover:last').css('width',percent_rounded + '%'); - var return_vals = [table_sizes,total_size]; + var return_vals = [table_rows,total_size]; return return_vals; } - table_details = decide_tables_to_display( tables_to_migrate, table_sizes ); - table_sizes = table_details[0]; + table_details = decide_tables_to_display_rows( tables_to_migrate, table_rows ); + table_rows = table_details[0]; total_size = table_details[1]; $('.progress-title').after( '' ); @@ -640,11 +752,11 @@ url : remote_site, key : secret_key, form_data : form_data, - stage : stage, + stage : stage, }, error: function(jqXHR, textStatus, errorThrown){ $('.progress-title').html('Migration failed'); - $('.progress-text').html( 'A problem occured when attempting to connect to the local server, please check the details and try again. (#112)' ); + $('.progress-text').html( 'A problem occurred when attempting to connect to the local server, please check the details and try again. (#112)' ); $('.progress-text').addClass( 'migration-error' ); }, success: function(data){ @@ -656,16 +768,19 @@ return; } - var datetime = data.datetime; - - data = $.parseJSON( data ); + var dump_url = data.dump_url; + var dump_filename = data.dump_filename; var table_migration_error = false; var i = 0; var progress_size = 0; var overall_percent = 0; + var table_progress = 0; + var temp_progress = 0; + var last_progress = 0; + var overall_table_progress = 0; - function migrate_table_recursive(){ + function migrate_table_recursive( current_row, primary_keys ){ if( i >= tables_to_migrate.length ){ if( stage == 'backup' ) { @@ -677,46 +792,54 @@ if( table_intent == 'migrate_select' ){ tables_to_migrate = $('#select-tables').val(); if( migration_intent == 'push' || migration_intent == 'savefile' ){ - table_sizes = $.parseJSON(wpmdb_this_table_sizes); + table_rows = $.parseJSON(wpmdb_this_table_rows); } else{ - table_sizes = connection_data.table_sizes; + table_rows = connection_data.table_rows; } } else{ if( migration_intent == 'push' || migration_intent == 'savefile' ){ - tables_to_migrate = this_tables; - table_sizes = $.parseJSON(wpmdb_this_table_sizes); + tables_to_migrate = this_prefixed_tables; + table_rows = $.parseJSON(wpmdb_this_table_rows); } else{ - tables_to_migrate = connection_data.tables; - table_sizes = connection_data.table_sizes; + tables_to_migrate = connection_data.prefixed_tables; + table_rows = connection_data.table_rows; } } $('.progress-tables').empty(); $('.progress-tables-hover-boxes').empty(); - table_details = decide_tables_to_display( tables_to_migrate, table_sizes ); - table_sizes = table_details[0]; + table_details = decide_tables_to_display_rows( tables_to_migrate, table_rows ); + table_rows = table_details[0]; total_size = table_details[1]; } else { - stage == 'end'; migration_complete(); return; } } - if( stage == 'backup'){ + if( stage == 'backup' ){ $('.progress-text').html( overall_percent + '% - Backing up "' + tables_to_migrate[i] + '"' ); } else{ $('.progress-text').html( overall_percent + '% - Migrating "' + tables_to_migrate[i] + '"'); } - + last_table = 0; + if( i == ( tables_to_migrate.length - 1 ) ) { + last_table = 1; + } + + gzip = 0; + if( parseInt( connection_data.gzip ) == 1 ) { + gzip = 1; + } + $.ajax({ url: ajaxurl, type: 'POST', @@ -724,27 +847,35 @@ cache: false, timeout: 0, data: { - action : 'wpmdb_prepare_table_migration', - intent : migration_intent, - url : remote_site, - key : secret_key, - table : tables_to_migrate[i], - form_data : form_data, - datetime : datetime, - stage : stage, - bottleneck : connection_data.bottleneck + action : 'wpmdb_prepare_table_migration', + intent : migration_intent, + url : remote_site, + key : secret_key, + table : tables_to_migrate[i], + form_data : form_data, + stage : stage, + bottleneck : connection_data.bottleneck, + prefix : connection_data.prefix, + current_row : current_row, + dump_filename : dump_filename, + last_table : last_table, + primary_keys : primary_keys, + gzip : gzip, }, error: function(jqXHR, textStatus, errorThrown){ $('.progress-title').html('Migration failed'); - $('.progress-text').html( 'A problem occured when processing the ' + tables_to_migrate[i] + ' table. (#113)' ); + $('.progress-text').html( 'A problem occurred when processing the ' + tables_to_migrate[i] + ' table. (#113)' ); $('.progress-text').addClass( 'migration-error' ); - console.log( jqXHR + ' : ' + textStatus + ' : ' + errorThrown ); + console.log( jqXHR ); + console.log( textStatus ); + console.log( errorThrown ); table_migration_error = true; migration_complete_events(); return; }, success: function(data){ - if( data != '' ){ + data = $.trim( data ); + if( ! is_json( data ) ){ $('.progress-title').html('Migration failed'); $('.progress-text').html(data); $('.progress-text').addClass('migration-error'); @@ -752,12 +883,29 @@ migration_complete_events(); return; } - progress_size += parseInt(table_sizes[tables_to_migrate[i]]); + + row_information = $.parseJSON( data ); + + if( row_information.current_row == '-1' ) { + progress_size -= overall_table_progress; + overall_table_progress = 0; + last_progress = 0; + progress_size += parseInt(table_rows[tables_to_migrate[i]]); + i++; + row_information.current_row = ''; + row_information.primary_keys = ''; + } + else { + temp_progress = parseInt( row_information.current_row ); + table_progress = temp_progress - last_progress; + last_progress = temp_progress; + progress_size += table_progress; + overall_table_progress += table_progress; + } var percent = 100 * progress_size / total_size; $('.progress-bar').width(percent + '%'); - i++; overall_percent = Math.floor(percent); - migrate_table_recursive(); + migrate_table_recursive( row_information.current_row, row_information.primary_keys ); } }); @@ -768,21 +916,14 @@ currently_migrating = false; var migrate_complete_text = 'Migration complete'; if( $('#save_computer').is(':checked') ){ - var url = wpmdb_this_download_url + datetime; - + var url = wpmdb_this_download_url + encodeURIComponent( dump_filename ); if( $('#gzip_file').is(':checked') ){ url += '&gzip=1'; } - window.location = url; - } else{ - var download_url = wpmdb_this_upload_url + wpmdb_this_website_name + '-migrate-' + datetime + '.sql'; - if( $('#gzip_file').is(':checked') ){ - download_url += '.gz'; - } - migrate_complete_text = 'Migration complete, your backup is located at:
    ' + download_url + '.'; + migrate_complete_text = 'Migration complete, your backup is located at: ' + dump_url + '.'; } if( table_migration_error == false ){ @@ -805,17 +946,25 @@ url : remote_site, key : secret_key, form_data : form_data, - datetime : datetime, stage : stage, + prefix : connection_data.prefix, }, error: function(jqXHR, textStatus, errorThrown){ $('.progress-title').html('Migration failed'); - $('.progress-text').html('A problem occured when finalizing the backup. (#132)'); + $('.progress-text').html('A problem occurred when finalizing the backup. (#132)'); $('.progress-text').addClass('migration-error'); - console.log( jqXHR + ' : ' + textStatus + ' : ' + errorThrown ); + alert( jqXHR + ' : ' + textStatus + ' : ' + errorThrown ); table_migration_error = true; }, success: function(data){ + if( $.trim( data ) != '' ){ + $('.progress-title').html('Migration failed'); + $('.progress-text').html(data); + $('.progress-text').addClass('migration-error'); + table_migration_error = true; + migration_complete_events(); + return; + } $('.progress-text').html('Migration complete'); $('.progress-title').html(completed_msg); } @@ -824,7 +973,7 @@ } } - migrate_table_recursive(); + migrate_table_recursive( '-1', '' ); } @@ -869,6 +1018,12 @@ return; } + // check that they've selected some tables to migrate + if( $('#migrate-selected').is(':checked') && $('#select-tables').val() == null ){ + alert( 'Please select at least one table to migrate.'); + return; + } + if( $.trim( $('.create-new-profile').val() ) == '' && $('#create_new').is(':checked') ){ alert('Please enter a name for your migration profile.'); $('.create-new-profile').focus(); @@ -895,10 +1050,10 @@ cache: false, data: { action: 'wpmdb_save_profile', - profile: profile, + profile: profile, }, error: function(jqXHR, textStatus, errorThrown){ - alert('An error occured when attempting to save the migration profile. Please see the Help tab for details on how to request support. (#104)'); + alert('An error occurred when attempting to save the migration profile. Please see the Help tab for details on how to request support. (#104)'); $('.save-settings-button').removeAttr('disabled'); $('.save-profile-ajax-spinner').remove(); $('.save-settings-button').after('Saved'); @@ -954,12 +1109,6 @@ $('.migrate-selection.option-group input[type=radio]').change(function() { move_connection_info_box(); - - $('.backup-options').show(); - if( $('#savefile').is(':checked') ){ - $('.backup-options').hide(); - } - if( connection_established ){ change_replace_values(); } @@ -969,6 +1118,12 @@ function move_connection_info_box(){ $('.import-button').hide(); $('.connection-status').hide(); + $('.prefix-notice').hide(); + $('.ssl-notice').hide(); + $('.different-plugin-version-notice').hide(); + $('.step-two').show(); + $('.backup-options').show(); + $('.keep-active-plugins').show(); var connection_info = $.trim( $('.pull-push-connection-info').val() ).split("\n"); if( $('#pull').is(':checked') ){ $('.pull-list li').append( connection_info_box ); @@ -977,10 +1132,21 @@ $('.connection-status').hide(); $('.step-two').show(); $('.table-prefix').html(connection_data.prefix); + $('.uploads-dir').html(wpmdb_this_uploads_dir); if( profile_name_edited == false ){ var profile_name = get_domain_name( connection_info[0] ); $('.create-new-profile').val(profile_name); } + if( show_prefix_notice == true ) { + $('.prefix-notice.pull').show(); + } + if( show_ssl_notice == true ) { + $('.ssl-notice').show(); + } + if( show_version_notice == true ) { + $('.different-plugin-version-notice').show(); + $('.step-two').hide(); + } } else{ $('.connection-status').show(); @@ -994,10 +1160,21 @@ $('.connection-status').hide(); $('.step-two').show(); $('.table-prefix').html(wpmdb_this_prefix); + $('.uploads-dir').html(connection_data.uploads_dir); if( profile_name_edited == false ){ var profile_name = get_domain_name( connection_info[0] ); $('.create-new-profile').val(profile_name); } + if( show_prefix_notice == true ) { + $('.prefix-notice.push').show(); + } + if( show_ssl_notice == true ) { + $('.ssl-notice').show(); + } + if( show_version_notice == true ) { + $('.different-plugin-version-notice').show(); + $('.step-two').hide(); + } } else{ $('.connection-status').show(); @@ -1011,18 +1188,11 @@ if( profile_name_edited == false ){ $('.create-new-profile').val(''); } + $('.backup-options').hide(); + $('.keep-active-plugins').hide(); } } - - // replace tables and replaces depending on which option is selected - var intent = $('input[name=action]:checked').val(); - if( intent == 'pull' ){ - last_replace_switch = 'pull'; - } - else if( intent == 'savefile' || intent == 'push' ){ - last_replace_switch = 'push'; - } - + function change_replace_values(){ if( $('#push').is(':checked') || $('#savefile').is(':checked') ){ if( last_replace_switch == '' || last_replace_switch == 'pull' ){ @@ -1068,15 +1238,15 @@ } // show / hide GUID helper description - $('.replace-guid-helper').click(function(){ - $('.replace-guids-info').toggle(); + $('.general-helper').click(function(){ + $(this).next().toggle(); }); $('body').click(function(){ - $('.replace-guids-info').hide(); + $('.helper-message').hide(); }); - $('.replace-guids-info').click(function(e){ + $('.helper-message').click(function(e){ e.stopPropagation(); }); @@ -1093,8 +1263,9 @@ if( $(this).hasClass('help') ) { refresh_debug_log(); - if( wpmdb_licence != '0' && checked_licence == false ) { - check_licence( wpmdb_licence ); + if( checked_licence == false && wpmdb_has_licence == '1' ) { + $('.support-content p').append( '' ); + check_licence(); checked_licence = true; } } @@ -1145,8 +1316,9 @@ if ( hash == 'help' ) { refresh_debug_log(); - if( wpmdb_licence != '0' ) { - check_licence( wpmdb_licence ); + if( wpmdb_has_licence == '1' ) { + $('.support-content p').append( '' ); + check_licence(); checked_licence = true; } } @@ -1172,7 +1344,7 @@ action: 'wpmdb_reset_api_key', }, error: function(jqXHR, textStatus, errorThrown){ - alert('An error occured when trying to generate the API key. Please see the Help tab for details on how to request support. (#105)'); + alert('An error occurred when trying to generate the API key. Please see the Help tab for details on how to request support. (#105)'); $('.reset-api-key-ajax-spinner').remove(); doing_reset_api_key_ajax = false; }, @@ -1219,7 +1391,7 @@ profile_id : $(this).attr('data-profile-id') }, error: function(jqXHR, textStatus, errorThrown){ - alert('An error occured when trying to delete the profile. Please see the Help tab for details on how to request support. (#106)'); + alert('An error occurred when trying to delete the profile. Please see the Help tab for details on how to request support. (#106)'); }, success: function(data){ if( data == '-1' ){ @@ -1251,7 +1423,7 @@ profile_id : $(this).attr('data-profile-id') }, error: function(jqXHR, textStatus, errorThrown){ - alert('An error occured when trying to delete the profile. Please see the Help tab for details on how to request support. (#107)'); + alert('An error occurred when trying to delete the profile. Please see the Help tab for details on how to request support. (#107)'); } }); @@ -1265,8 +1437,11 @@ return; } else{ - $(this).removeClass('temp-disabled'); - $(this).removeAttr('readonly'); + $('.ssl-notice').hide(); + $('.different-plugin-version-notice').hide(); + $('.migrate-db-button').show(); + $('.temp-disabled').removeAttr('readonly'); + $('.temp-disabled').removeClass('temp-disabled'); $('.connect-button').show(); $('.step-two').hide(); $('.connection-status').show().html('Please enter the connection information above to continue.'); @@ -1293,7 +1468,7 @@ setting : setting }, error: function(jqXHR, textStatus, errorThrown){ - alert('An error occured when trying to save the settings. Please try again. If the problem persists, please see the Help tab for details on how to request support. (#108)'); + alert('An error occurred when trying to save the settings. Please try again. If the problem persists, please see the Help tab for details on how to request support. (#108)'); $('.ajax-spinner').remove(); }, success: function(data){ @@ -1316,20 +1491,28 @@ $('.connect-button').click(function(event){ event.preventDefault(); $(this).blur(); - connection_box_changed($('.pull-push-connection-info').val()); + connection_box_changed(); }); // send paste even to connection_box_changed() function $('.pull-push-connection-info').bind('paste', function(e) { var $this = this; setTimeout(function () { - connection_box_changed($($this).val()); + connection_box_changed(); }, 0); }); $('body').delegate('.try-again','click',function(){ - connection_box_changed($('.pull-push-connection-info').val()); + connection_box_changed(); + }); + + $('body').delegate('.try-http','click',function(){ + var connection_info = $.trim( $('.pull-push-connection-info').val() ).split("\n"); + var new_url = connection_info[0].replace( 'https', 'http' ); + var new_contents = new_url + "\n" + connection_info[1]; + $('.pull-push-connection-info').val( new_contents ); + connection_box_changed(); }); $('.create-new-profile').change(function(){ @@ -1343,6 +1526,8 @@ if( doing_ajax || $($this).hasClass('temp-disabled') ){ return; } + + var data = $('.pull-push-connection-info').val(); var connection_info = $.trim(data).split("\n"); var error = false; @@ -1384,9 +1569,26 @@ return; } + if( wpmdb_openssl_available == false ) { + connection_info[0] = connection_info[0].replace('https://','http://'); + var new_connection_info_contents = connection_info[0] + "\n" + connection_info[1]; + $('.pull-push-connection-info').val(new_connection_info_contents); + } + + show_prefix_notice = false; doing_ajax = true; + + if( $('.basic-access-auth-wrapper').is(':visible') ) { + connection_info[0] = connection_info[0].replace( /\/\/(.*)@/, '//' ); + connection_info[0] = connection_info[0].replace( '//', '//' + $.trim( $('.auth-username').val() ) + ':' + $.trim( $('.auth-password').val() ) + '@' ); + var new_connection_info_contents = connection_info[0] + "\n" + connection_info[1]; + $('.pull-push-connection-info').val(new_connection_info_contents); + $('.basic-access-auth-wrapper').hide(); + } $('.step-two').hide(); + $('.ssl-notice').hide(); + $('.prefix-notice').hide(); $('.connection-status').show(); $('.connection-status').html( 'Establishing connection to remote server, please wait' ); @@ -1409,7 +1611,7 @@ intent: intent, }, error: function(jqXHR, textStatus, errorThrown){ - $('.connection-status').html( 'A problem occured when attempting to connect to the local server, please check the details and try again. (#100)' ); + $('.connection-status').html( 'A problem occurred when attempting to connect to the local server, please check the details and try again. (#100)' ); $('.connection-status').addClass( 'migration-error' ); $('.ajax-spinner').remove(); doing_ajax = false; @@ -1421,14 +1623,16 @@ if( typeof data.wpmdb_error != 'undefined' && data.wpmdb_error == 1 ){ $('.connection-status').html( data.body ); $('.connection-status').addClass( 'migration-error' ); + + if( data.body.indexOf( '401 Unauthorized' ) > -1 ) { + $('.basic-access-auth-wrapper').show(); + } + return; } var profile_name = get_domain_name( connection_info[0] ); $('.create-new-profile').val(profile_name); - - var original_body = data; - data = $.parseJSON( data ); $('.pull-push-connection-info').addClass('temp-disabled'); $('.pull-push-connection-info').attr('readonly','readonly'); @@ -1438,14 +1642,17 @@ $('.step-two').show(); connection_established = true; connection_data = data; + move_connection_info_box(); - $('.remote-json-data').val(original_body); + maybe_show_ssl_warning( connection_info[0], connection_info[1], data.scheme ); + maybe_show_version_warning( data.plugin_version, connection_info[0] ); + maybe_show_prefix_notice( data.prefix ); var table_select = document.createElement('select'); $(table_select).attr('multiple', 'multiple').attr('name','select-tables[]').attr('id','select-tables'); $.each(connection_data.tables, function(index, value) { - $(table_select).append(''); + $(table_select).append(''); }); pull_select = table_select; @@ -1453,15 +1660,21 @@ if( $('#pull').is(':checked') ){ $('#new-url').val( wpmdb_this_url ); $('#new-path').val( wpmdb_this_path ); + if( wpmdb_is_multisite == true ) { + $('#new-domain').val( wpmdb_this_domain ); + } $('#old-url').val( data.url ); $('#old-path').val( data.path ); + $('#old-domain').val( data.domain ); $('#select-tables').remove(); $('.select-tables-wrap').prepend(pull_select); $('.table-prefix').html(data.prefix); + $('.uploads-dir').html(wpmdb_this_uploads_dir); } else{ $('#new-url').val( data.url ); $('#new-path').val( data.path ); + $('#new-domain').val( data.domain ); } } diff --git a/asset/sass/styles.scss b/asset/sass/styles.scss index 547efa9..dc470e1 100644 --- a/asset/sass/styles.scss +++ b/asset/sass/styles.scss @@ -1,6 +1,9 @@ @import "compass"; .wpmdb{ + > .warning { + max-width: 750px; + } /* ============================================================================= Common & Global @@ -25,7 +28,8 @@ margin-top: 0; } - input[type=text] { + input[type=text], + input[type=password] { padding: 5px; } @@ -92,6 +96,7 @@ .connection-status{ display: none; + overflow: auto; } .connection-status.error{ @@ -293,6 +298,20 @@ padding: 10px; } + .basic-access-auth-wrapper { + display: none; + margin-bottom: 5px; + } + + .auth-username, .auth-password { + width: 206px; + margin-top: 3px; + } + + .auth-password { + width: 207px; + } + .connection-info-wrapper { display: none; width: 670px; @@ -462,7 +481,7 @@ /* Advanced Options */ - .replace-guid-helper { + .general-helper { border-radius: 50%; border: 1px solid #ccc; background-color: #eee; @@ -471,15 +490,16 @@ display: inline-block; position: relative; top: 4px; + margin-top: -4px; cursor: pointer; margin-left: 2px; } - .replace-guid-helper:hover { + .general-helper:hover { border-color: #aaa; } - .replace-guid-helper:after { + .general-helper:after { content: "?"; color: #999999; font-size: 10px; @@ -489,21 +509,29 @@ top: -1px; } - .replace-guids-info { + .helper-message { padding: 10px; border: 1px solid #ccc; border-radius: 3px; background-color: #fff; position: absolute; width: 500px; - left: 140px; z-index: 100; - top: -7px; display: none; box-shadow: 0px 0px 5px #ccc; } + + .ssl-verify-message { + left: 182px; + top: -10px; + } + + .replace-guids-info { + left: 140px; + top: -10px; + } - .replace-guids-info:after { + .helper-message:after { content: ''; border-bottom: 7px solid transparent; border-right: 7px solid #fff; @@ -516,7 +544,7 @@ width: 0; } - .replace-guids-info:before { + .helper-message:before { content: ''; border-bottom: 7px solid transparent; border-right: 7px solid #aaa; @@ -532,6 +560,40 @@ .label-disabled { color: #888; } + + .prefix-notice, .ssl-notice, .different-plugin-version-notice, .mysqli-notice { + background-color: #FFFFE0; + border: 1px solid #E6DB55; + padding: 15px; + border-radius: 3px; + margin-bottom: 15px; + display: none; + width: 710px; + p{ + margin-top: 0px; + } + p:last-child { + margin: 0px; + } + } + + .different-plugin-version-notice, .mysqli-notice { + background-color: #FFEBE8; + border-color: #CC0000; + a { + color: #CC0000; + text-decoration: underline; + } + } + + .mysqli-notice { + display: block; + } + + .ssl-notice { + margin-bottom: 0; + margin-top: 15px; + } /* Save migration profile */ @@ -622,6 +684,76 @@ .settings-tab{ display: none; + .slider { + max-width: 416px; + } + + .slider-label { + display: block; + margin-bottom: 10px; + float: left; + width: 50%; + } + + .slider-label-wrapper { + max-width: 416px; + width: 100%; + position: relative; + } + + .amount { + width: 50%; + text-align: right; + display: block; + text-align: right; + float: left; + } + + .slider-message { + top: -11px; + left: 164px; + } + + .slider-spinner { + position: absolute; + right: -35px; + bottom: -13px; + } + + .slider-success-msg { + display: none; + right: -53px; + bottom: -13px; + position: absolute; + font-weight: bold; + } + + .ui-slider { + border: 1px solid #dfdfdf; + height: 10px; + border-radius: 2px; + position: relative; + } + + .ui-slider-handle { + width: 7px; + height: 20px; + background-color: #aaa; + display: block; + position: absolute; + top: -5px; + outline: none; + } + + .ui-slider-handle:active { + background-color: #999; + } + + .ui-slider-range { + background-color: #eee; + height: 100%; + } + .option-section{ li label{ @@ -653,6 +785,14 @@ font-weight: bold; } + .verify-ssl .ajax-spinner { + right: -45px; + } + + .verify-ssl .ajax-success-msg { + right: -65px; + } + } } @@ -696,7 +836,7 @@ } /* ============================================================================= - Settings Tab + Help Tab ========================================================================== */ .help-tab { @@ -737,9 +877,6 @@ .videos { width: 640px; - border-bottom: 1px solid #CCCCCC; - margin-bottom: 25px; - padding-bottom: 28px; ul > li { margin-bottom: 30px; @@ -810,6 +947,9 @@ .debug { width: 640px; + border-bottom: 1px solid #CCCCCC; + margin-bottom: 25px; + padding-bottom: 28px; textarea{ width: 100%; @@ -830,6 +970,7 @@ iframe { display: none; } + } } @@ -847,8 +988,13 @@ } .migration-error { - color: #A21B1B; - font-weight: bold; + color: #A21B1B; + display: block; + font-weight: bold; + max-height: 400px; + max-width: 100%; + overflow: scroll; + word-wrap: break-word; } .progress-content{ @@ -964,7 +1110,6 @@ border: 1px solid #ccc; border-radius: 3px; background-color: #fff; - colour: #333; font-family: "Courier New",Courier,monospace; font-size: 12px; display: inline-block; diff --git a/class/wp-migrate-db.php b/class/wp-migrate-db.php index c749a65..f136a6c 100644 --- a/class/wp-migrate-db.php +++ b/class/wp-migrate-db.php @@ -1,7 +1,5 @@ plugin_file_path = $plugin_file_path; @@ -39,10 +41,6 @@ function __construct( $plugin_file_path ) { $this->plugin_slug = basename( $this->plugin_dir_path ); $this->plugin_basename = plugin_basename( $plugin_file_path ); - $upload_dir = wp_upload_dir(); - $this->upload_dir = $upload_dir['basedir']; - $this->upload_url = $upload_dir['baseurl']; - $this->replaced['serialized']['count'] = 0; $this->replaced['serialized']['strings'] = ''; $this->replaced['nonserialized']['count'] = 0; @@ -51,32 +49,68 @@ function __construct( $plugin_file_path ) { $this->dbrains_api_base = DBRAINS_API_BASE; } + if( $this->open_ssl_enabled() == false ) { + $this->dbrains_api_base = str_replace( 'https://', 'http://', $this->dbrains_api_base ); + } + $this->transient_timeout = 60 * 60 * 12; $this->transient_retry_timeout = 60 * 60 * 2; $this->dbrains_api_url = $this->dbrains_api_base . '/?wc-api=delicious-brains'; - $this->settings = get_site_option( 'wpmdb_settings' ); + $this->settings = get_option( 'wpmdb_settings' ); $this->max_insert_string_len = 50000; // 50000 is the default as defined by phphmyadmin + $default_settings = array( + 'key' => $this->generate_key(), + 'allow_pull' => false, + 'allow_push' => false, + 'profiles' => array(), + 'licence' => '', + 'licence_email' => '', + 'verify_ssl' => false, + ); + + if( empty( $this->settings['max_request'] ) ) { + $this->settings['max_request'] = min( 1024 * 1024, $this->get_bottleneck( 'max' ) ); + update_option( 'wpmdb_settings', $this->settings ); + } + // if no settings exist then this is a fresh install, set up some default settings if ( empty( $this->settings ) ) { - $this->settings = array( - 'key' => $this->generate_key(), - 'allow_pull' => false, - 'allow_push' => false, - 'profiles' => array(), - 'licence' => '', - 'licence_email' => '' - ); - update_site_option( 'wpmdb_settings', $this->settings ); + $this->settings = $default_settings; + update_option( 'wpmdb_settings', $this->settings ); + } + // When we add a new setting, an existing customer's db won't have this + // new setting, so we need to add it. Otherwise, they'll see + // array index errors in debug mode + else { + $update_settings = false; + + foreach ( $default_settings as $key => $value ) { + if ( !isset( $this->settings[$key] ) ) { + $this->settings[$key] = $value; + $update_settings = true; + } + } + + if ( $update_settings ) { + update_option( 'wpmdb_settings', $this->settings ); + } } add_filter( 'plugin_action_links_' . $this->plugin_basename, array( $this, 'plugin_action_links' ) ); + add_filter( 'network_admin_plugin_action_links_' . $this->plugin_basename, array( $this, 'plugin_action_links' ) ); - add_action( 'admin_menu', array( $this, 'admin_menu' ) ); - add_action( 'admin_head-tools_page_wp-migrate-db-pro', array( $this, 'admin_head_connection_info' ) ); + if ( is_multisite() ) { + add_action( 'network_admin_menu', array( $this, 'network_admin_menu' ) ); + $this->plugin_base = 'settings.php?page=wp-migrate-db-pro'; + } + else { + add_action( 'admin_menu', array( $this, 'admin_menu' ) ); + $this->plugin_base = 'tools.php?page=wp-migrate-db-pro'; + } // internal AJAX handlers add_action( 'wp_ajax_wpmdb_prepare_remote_connection', array( $this, 'ajax_prepare_remote_connection' ) ); @@ -91,6 +125,8 @@ function __construct( $plugin_file_path ) { add_action( 'wp_ajax_wpmdb_get_log', array( $this, 'ajax_get_log' ) ); add_action( 'wp_ajax_wpmdb_activate_licence', array( $this, 'ajax_activate_licence' ) ); add_action( 'wp_ajax_wpmdb_check_licence', array( $this, 'ajax_check_licence' ) ); + add_action( 'wp_ajax_wpmdb_fire_migration_complete', array( $this, 'fire_migration_complete' ) ); + add_action( 'wp_ajax_wpmdb_update_max_request_size', array( $this, 'ajax_update_max_request_size' ) ); // external AJAX handlers add_action( 'wp_ajax_nopriv_wpmdb_establish_remote_connection', array( $this, 'ajax_establish_remote_connection' ) ); @@ -99,6 +135,7 @@ function __construct( $plugin_file_path ) { add_action( 'wp_ajax_nopriv_wpmdb_prepare_table_migration', array( $this, 'ajax_prepare_table_migration' ) ); add_action( 'wp_ajax_nopriv_wpmdb_finalize_backup', array( $this, 'ajax_finalize_backup' ) ); add_action( 'wp_ajax_nopriv_wpmdb_process_pull_request', array( $this, 'ajax_process_pull_request' ) ); + add_action( 'wp_ajax_nopriv_wpmdb_fire_migration_complete', array( $this, 'fire_migration_complete' ) ); // Take over the update check add_filter( 'site_transient_update_plugins', array( $this, 'site_transient_update_plugins' ) ); @@ -125,7 +162,9 @@ function __construct( $plugin_file_path ) { $home_url = rtrim( home_url( '', 'http' ), '\\/' ); if ( $site_url != $home_url ) { $difference = str_replace( $home_url, '', $site_url ); - $absolute_path = rtrim( substr( ABSPATH, 0, -strlen( $difference ) ), '\\/' ); + if( strpos( $absolute_path, $difference ) !== false ) { + $absolute_path = rtrim( substr( $absolute_path, 0, -strlen( $difference ) ), '\\/' ); + } } $this->absolute_root_file_path = $absolute_path; @@ -146,6 +185,7 @@ function __construct( $plugin_file_path ) { 'create_new_profile', 'create_backup', 'remove_backup', + 'keep_active_plugins', ); $this->default_profile = array( @@ -159,17 +199,92 @@ function __construct( $plugin_file_path ) { 'select_tables' => array(), ); - $this->plugin_base = 'tools.php?page=wp-migrate-db-pro'; - // this is how many DB rows are processed at a time, allow devs to change this value $this->rows_per_segment = apply_filters( 'wpmdb_rows_per_segment', $this->rows_per_segment ); + // allow devs to change the temporary prefix applied to the tables + $this->temp_prefix = apply_filters( 'wpmdb_temporary_prefix', $this->temp_prefix ); + // testing only - if uncommented, will always check for plugin updates //delete_site_transient( 'update_plugins' ); //delete_site_transient( 'wpmdb_upgrade_data' ); //delete_site_transient( 'wpmdb_licence_response' ); } + function get_alter_table_name() { + if ( ! is_null( $this->alter_table_name ) ) { + return $this->alter_table_name; + } + global $wpdb; + $this->alter_table_name = apply_filters( 'wpmdb_alter_table_name', $wpdb->prefix . 'wpmdb_alter_statements' ); + return $this->alter_table_name; + } + + function get_create_alter_table_query() { + if ( ! is_null( $this->create_alter_table_query ) ) { + return $this->create_alter_table_query; + } + $alter_table_name = $this->get_alter_table_name(); + $this->create_alter_table_query = sprintf( "DROP TABLE IF EXISTS `%s`;\n", $alter_table_name ); + $this->create_alter_table_query .= sprintf( "CREATE TABLE `%s` ( `query` longtext NOT NULL );\n", $alter_table_name ); + $this->create_alter_table_query = apply_filters( 'wpmdb_create_alter_table_query', $this->create_alter_table_query ); + return $this->create_alter_table_query; + } + + function get_short_uploads_dir() { + $short_path = str_replace( $this->absolute_root_file_path, '', $this->get_upload_info( 'path' ) ); + return trailingslashit( substr( str_replace( '\\', '/', $short_path ), 1 ) ); + } + + function get_upload_info( $type = 'path' ) { + // Let developers define their own path to for export files + // Note: We require a very specific data set here, it should be similiar to the following + // array( + // 'path' => '/path/to/custom/uploads/directory', <- note missing end trailing slash + // 'url' => 'http://yourwebsite.com/custom/uploads/directory' <- note missing end trailing slash + // ); + $upload_info = apply_filters( 'wpmdb_upload_info', array() ); + if ( !empty( $upload_info ) ) { + return $upload_info[$type]; + } + + $upload_dir = wp_upload_dir(); + + $upload_info['path'] = $upload_dir['basedir']; + $upload_info['url'] = $upload_dir['baseurl']; + + $upload_dir_name = apply_filters( 'wpmdb_upload_dir_name', 'wp-migrate-db' ); + + if( ! file_exists( $upload_dir['basedir'] . DS . $upload_dir_name ) ) { + $url = wp_nonce_url( $this->plugin_base, 'wp-migrate-db-pro-nonce' ); + + if( false === mkdir( $upload_dir['basedir'] . DS . $upload_dir_name, 0755 ) ) { + return $upload_info[$type]; + } + + $filename = $upload_dir['basedir'] . DS . $upload_dir_name . DS . 'index.php'; + if( false === file_put_contents( $filename, "" ) ) { + return $upload_info[$type]; + } + } + + $upload_info['path'] .= DS . $upload_dir_name; + $upload_info['url'] .= '/' . $upload_dir_name; + + return $upload_info[$type]; + } + + function ajax_update_max_request_size() { + $this->settings['max_request'] = (int) $_POST['max_request_size'] * 1024; + update_option( 'wpmdb_settings', $this->settings ); + exit; + } + + function filter_post_elements( $post_array, $accepted_elements ) { + $accepted_elements[] = 'sig'; + return array_intersect_key( $post_array, array_flip( $accepted_elements ) ); + } + function verify_download( $response, $args, $url ) { $download_url = $this->get_plugin_update_download_url(); @@ -214,7 +329,7 @@ function check_licence( $licence_key ) { } function ajax_check_licence() { - $licence = ( empty( $_POST['licence_key'] ) ? $this->settings['licence'] : $_POST['licence_key'] ); + $licence = ( empty( $_POST['licence'] ) ? $this->get_licence_key() : $_POST['licence'] ); $response = $this->check_licence( $licence ); echo $response; exit; @@ -226,6 +341,10 @@ function ajax_activate_licence() { 'site_url' => site_url( '', 'http' ) ); + if( $this->is_licence_constant() ) { + $args['licence_key'] = $this->get_licence_key(); + } + $response = $this->dbrains_api_request( 'activate_licence', $args ); echo $response; @@ -233,9 +352,11 @@ function ajax_activate_licence() { $response = json_decode( $response, true ); if ( $response && !isset( $response['errors'] ) ) { - $this->settings['licence'] = $_POST['licence_key']; + if ( !$this->is_licence_constant() ) { + $this->settings['licence'] = $_POST['licence_key']; + } $this->settings['licence_email'] = $response['email']; - update_site_option( 'wpmdb_settings', $this->settings ); + update_option( 'wpmdb_settings', $this->settings ); } exit; @@ -249,10 +370,13 @@ function get_dbrains_api_url( $request, $args = array() ) { } function dbrains_api_request( $request, $args = array() ) { + $sslverify = ( $this->settings['verify_ssl'] == 1 ? true : false ); + $url = $this->get_dbrains_api_url( $request, $args ); $response = wp_remote_get( $url, array( 'timeout' => 30, - 'blocking' => true + 'blocking' => true, + 'sslverify' => $sslverify ) ); if ( is_wp_error( $response ) || (int) $response['response']['code'] < 200 || (int) $response['response']['code'] > 399 ) { @@ -271,37 +395,133 @@ function display_errors() { return false; } - function get_db_object(){ - $db = new mysqli( DB_HOST, DB_USER, DB_PASSWORD, DB_NAME ); - $db->set_charset( DB_CHARSET ); - return $db; + function array_to_multipart( $data ) { + if ( !$data || !is_array( $data ) ) { + return $data; + } + + $result = ''; + + foreach ( $data as $key => $value ) { + $result .= '--' . $this->multipart_boundary . "\r\n" . + sprintf( 'Content-Disposition: form-data; name="%s"', $key ); + + if ( 'chunk' == $key ) { + if ( $data['chunk_gzipped'] ) { + $result .= "; filename=\"chunk.txt.gz\"\r\nContent-Type: application/x-gzip"; + } + else { + $result .= "; filename=\"chunk.txt\"\r\nContent-Type: text/plain;"; + } + } + else { + $result .= "\r\nContent-Type: text/plain; charset=" . get_option( 'blog_charset' ); + } + + $result .= "\r\n\r\n" . $value . "\r\n"; + } + + $result .= "--" . $this->multipart_boundary . "--\r\n"; + + return $result; + } + + function is_json( $string, $strict = false ) { + $json = @json_decode( $string, true ); + if( $strict == true && ! is_array( $json ) ) return false; + return ! ( $json == NULL || $json == false ); } - function remote_post( $url, $data, $scope, $args = array() ) { - set_time_limit( 0 ); + function remote_post( $url, $data, $scope, $args = array(), $expecting_serial = false ) { + $this->set_time_limit(); + + if( function_exists( 'fsockopen' ) && strpos( $url, 'https://' ) === 0 && $scope == 'ajax_prepare_remote_connection' ) { + $url_parts = parse_url( $url ); + $host = $url_parts['host']; + if( $pf = @fsockopen( $host, 443, $err, $err_string, 1 ) ) { + // worked + fclose( $pf ); + } + else { + // failed + $url = substr_replace( $url, 'http', 0, 5 ); + } + } + + $sslverify = ( $this->settings['verify_ssl'] == 1 ? true : false ); + + $default_remote_post_timeout = apply_filters( 'wpmdb_default_remote_post_timeout', 60 * 20 ); $args = wp_parse_args( $args, array( - 'timeout' => 60 * 20, - 'blocking' => true + 'timeout' => $default_remote_post_timeout, + 'blocking' => true, + 'sslverify' => $sslverify, ) ); $args['method'] = 'POST'; - $args['body'] = $data; + $args['body'] = $this->array_to_multipart( $data ); + $args['headers']['Content-Type'] = 'multipart/form-data; boundary=' . $this->multipart_boundary; + $args['headers']['Referer'] = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ); + + $this->attempting_to_connect_to = $url; $response = wp_remote_post( $url, $args ); + if ( ! is_wp_error( $response ) ) { + $response['body'] = trim( $response['body'], "\xef\xbb\xbf" ); + } + if ( is_wp_error( $response ) ) { - if( isset( $response->errors['http_request_failed'][0] ) && strstr( $response->errors['http_request_failed'][0], 'timed out' ) ) { - $this->error = 'The connection to the remote server has timed out, the changes have been successfully rolled back. (#134 - scope: ' . $scope . ')'; + if( strpos( $url, 'https://' ) === 0 && $scope == 'ajax_prepare_remote_connection' ) { + $url = substr_replace( $url, 'http', 0, 5 ); + // needs testing + if( $response = $this->remote_post( $url, $data, $scope, $args, $expecting_serial ) ) { + return $response; + } + else { + return false; + } + } + else if( isset( $response->errors['http_request_failed'][0] ) && strstr( $response->errors['http_request_failed'][0], 'timed out' ) ) { + $this->error = 'The connection to the remote server has timed out, no changes have been committed. (#134 - scope: ' . $scope . ')'; + } + else if ( isset( $response->errors['http_request_failed'][0] ) && ( strstr( $response->errors['http_request_failed'][0], 'Could not resolve host' ) || strstr( $response->errors['http_request_failed'][0], 'couldn\'t connect to host' ) ) ) { + $this->error = 'We could not find: ' . $_POST['url'] . '. Are you sure this is the correct URL?'; + $url_bits = parse_url( $_POST['url'] ); + if( strstr( $_POST['url'], 'dev.' ) || strstr( $_POST['url'], '.dev' ) || ! strstr( $url_bits['host'], '.' ) ) { + $this->error .= '
    It appears that you might be trying to ' . $_POST['intent'] . ( $_POST['intent'] == 'pull' ? ' from' : ' to' ) . ' a local environment. This will not work if this website happens to be located on a remote server, it would be impossible for this server to contact your local environment.'; + } } else { - $this->error = 'The connection failed, please try connecting over http instead of https. (#121 - scope: ' . $scope . ')'; + $this->error = 'The connection failed, an unexpected error occurred, please contact support. (#121 - scope: ' . $scope . ')'; } $this->log_error( $this->error, $response ); return false; } elseif ( (int) $response['response']['code'] < 200 || (int) $response['response']['code'] > 399 ) { - $this->error = 'Unable to connect to the remote server, please check the connection details (#129 - scope: ' . $scope . ')'; + if( strpos( $url, 'https://' ) === 0 && $scope == 'ajax_prepare_remote_connection' ) { + $url = substr_replace( $url, 'http', 0, 5 ); + // needs testing + if( $response = $this->remote_post( $url, $data, $scope, $args, $expecting_serial ) ) { + return $response; + } + else { + return false; + } + } + else if( $response['response']['code'] == '401' ) { + $this->error = 'The remote site is protected with Basic Authentication. Please enter the username and password above to continue. (401 Unauthorized)'; + $this->log_error( $this->error, $response ); + return false; + } + else { + $this->error = 'Unable to connect to the remote server, please check the connection details - ' . $response['response']['code'] . ' ' . $response['response']['message'] . ' (#129 - scope: ' . $scope . ')'; + $this->log_error( $this->error, $response ); + return false; + } + } + elseif ( $expecting_serial && is_serialized( $response['body'] ) == false ) { + $this->error = 'There was a problem with the AJAX request, we were expecting a serialized response, instead we received:
    ' . htmlentities( $response['body'] ); $this->log_error( $this->error, $response ); return false; } @@ -317,14 +537,29 @@ function remote_post( $url, $data, $scope, $args = array() ) { function log_error( $wpmdb_error, $additional_error_var = false ){ $error_header = "********************************************\n****** Log date: " . date( 'Y/m/d H:i:s' ) . " ******\n********************************************\n\n"; $error = $error_header . "WPMDB Error: " . $wpmdb_error . "\n\n"; + if( ! empty( $this->attempting_to_connect_to ) ) { + $error .= "Attempted to connect to: " . $this->attempting_to_connect_to . "\n\n"; + } if( $additional_error_var !== false ){ $error .= print_r( $additional_error_var, true ) . "\n\n"; } - file_put_contents( $this->plugin_dir_path . 'debug.log', $error, FILE_APPEND ); + $log = get_option( 'wpmdb_error_log' ); + if( $log ) { + $log = $log . $error; + } + else { + $log = $error; + } + update_option( 'wpmdb_error_log', $log ); } - function get_sql_dump_file_name( $type = 'migrate' ) { - return $this->upload_dir . DS . sanitize_title_with_dashes( DB_NAME ) . '-' . $type . '-' . $_POST['datetime'] . '.sql'; + function get_sql_dump_info( $migration_type, $info_type ) { + if( empty( $this->session_salt ) ) { + $this->session_salt = strtolower( wp_generate_password( 5, false, false ) ); + } + $datetime = date('YmdHis'); + $ds = ( $info_type == 'path' ? DS : '/' ); + return sprintf( '%s%s%s-%s-%s-%s.sql', $this->get_upload_info( $info_type ), $ds, sanitize_title_with_dashes( DB_NAME ), $migration_type, $datetime, $this->session_salt ); } function parse_migration_form_data( $data ) { @@ -336,15 +571,13 @@ function parse_migration_form_data( $data ) { } function plugin_action_links( $links ) { - $link = sprintf( '%s', $this->plugin_base, __( 'Settings', 'wp-migrate-db-pro' ) ); + $link = sprintf( '%s', network_admin_url( $this->plugin_base ), __( 'Settings', 'wp-migrate-db-pro' ) ); array_unshift( $links, $link ); return $links; } function ajax_clear_log() { - if( file_exists( $this->plugin_dir_path . 'debug.log' ) ) { - file_put_contents( $this->plugin_dir_path . 'debug.log', '' ); - } + delete_option( 'wpmdb_error_log' ); exit; } @@ -355,12 +588,36 @@ function ajax_get_log() { } function output_log_file() { - if( file_exists( $this->plugin_dir_path . 'debug.log' ) ) { - echo file_get_contents( $this->plugin_dir_path . 'debug.log' ); + $log = get_option( 'wpmdb_error_log' ); + if( $log ) { + echo $log; + } + } + + function open_ssl_enabled() { + if ( defined( 'OPENSSL_VERSION_TEXT' ) ) { + return true; + } + else { + return false; } } function output_diagnostic_info() { + global $table_prefix; + + _e( 'site_url()', 'wp-app-store' ); echo ': '; + echo site_url(); + echo "\r\n"; + + _e( 'home_url()', 'wp-app-store' ); echo ': '; + echo home_url(); + echo "\r\n"; + + _e( 'Table Prefix', 'wp-app-store' ); echo ': '; + echo $table_prefix; + echo "\r\n"; + _e( 'WordPress', 'wp-app-store' ); echo ': '; if ( is_multisite() ) echo 'WPMU'; else echo 'WP'; echo bloginfo('version'); echo "\r\n"; @@ -376,35 +633,47 @@ function output_diagnostic_info() { _e( 'MySQL', 'wp-app-store' ); echo ': '; if ( function_exists( 'mysql_get_server_info' ) ) echo esc_html( mysql_get_server_info() ); echo "\r\n"; - - _e( 'max_allowed_packet_size', 'wp-app-store' ); echo ': '; - echo $this->get_max_allowed_packet_size(); - echo "\r\n"; _e( 'WP Memory Limit', 'wp-app-store' ); echo ': '; echo WP_MEMORY_LIMIT; echo "\r\n"; _e( 'WPMDB Bottleneck', 'wp-app-store' ); echo ': '; - echo $this->get_bottleneck(); + echo size_format( $this->get_bottleneck() ); echo "\r\n"; + if ( function_exists( 'ini_get' ) && $suhosin_limit = ini_get( 'suhosin.post.max_value_length' ) ) { + _e( 'Suhosin Post Max Value Length', 'wp-app-store' ); echo ': '; + echo is_numeric( $suhosin_limit ) ? size_format( $suhosin_limit ) : $suhosin_limit; + echo "\r\n"; + } + + if ( function_exists( 'ini_get' ) && $suhosin_limit = ini_get( 'suhosin.request.max_value_length' ) ) { + _e( 'Suhosin Request Max Value Length', 'wp-app-store' ); echo ': '; + echo is_numeric( $suhosin_limit ) ? size_format( $suhosin_limit ) : $suhosin_limit; + echo "\r\n"; + } + _e( 'Debug Mode', 'wp-app-store' ); echo ': '; if ( defined('WP_DEBUG') && WP_DEBUG ) { echo 'Yes'; } else { echo 'No'; } echo "\r\n"; _e( 'WP Max Upload Size', 'wp-app-store' ); echo ': '; - echo wp_convert_bytes_to_hr( wp_max_upload_size() ); + echo size_format( wp_max_upload_size() ); echo "\r\n"; _e( 'PHP Post Max Size', 'wp-app-store' ); echo ': '; - if ( function_exists( 'ini_get' ) ) echo ini_get('post_max_size'); + echo size_format( $this->get_post_max_size() ); echo "\r\n"; _e( 'PHP Time Limit', 'wp-app-store' ); echo ': '; if ( function_exists( 'ini_get' ) ) echo ini_get('max_execution_time'); echo "\r\n"; + _e( 'PHP Error Log', 'wp-app-store' ); echo ': '; + if ( function_exists( 'ini_get' ) ) echo ini_get('error_log'); + echo "\r\n"; + _e( 'fsockopen', 'wp-app-store' ); echo ': '; if ( function_exists( 'fsockopen' ) ) { _e('Enabled', 'wp-app-store' ); @@ -413,6 +682,15 @@ function output_diagnostic_info() { } echo "\r\n"; + _e( 'OpenSSL', 'wp-app-store' ); echo ': '; + if ( $this->open_ssl_enabled() ) { + echo OPENSSL_VERSION_TEXT; + + } else { + _e( 'Disabled', 'wp-app-store' ); + } + echo "\r\n"; + _e( 'cURL', 'wp-app-store' ); echo ': '; if ( function_exists( 'curl_init' ) ) { _e('Enabled', 'wp-app-store' ); @@ -426,8 +704,10 @@ function output_diagnostic_info() { $active_plugins = (array) get_option( 'active_plugins', array() ); - if ( is_multisite() ) - $active_plugins = array_merge( $active_plugins, get_site_option( 'active_sitewide_plugins', array() ) ); + if ( is_multisite() ) { + $network_active_plugins = wp_get_active_network_plugins(); + $active_plugins = array_map( array( $this, 'remove_wp_plugin_dir' ), $network_active_plugins ); + } foreach ( $active_plugins as $plugin ) { $plugin_data = @get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ); @@ -437,13 +717,43 @@ function output_diagnostic_info() { echo "\r\n"; } + + function remove_wp_plugin_dir( $name ) { + $plugin = str_replace( WP_PLUGIN_DIR, '', $name ); + return substr( $plugin, 1 ); + } + + function fire_migration_complete() { + $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'url' ) ); + if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { + echo $this->invalid_content_verification_error . ' (#123)'; + exit; + } + + do_action( 'wpmdb_migration_complete', 'pull', $_POST['url'] ); + exit; + } + + function get_alter_queries() { + global $wpdb; + $alter_table_name = $this->get_alter_table_name(); + $sql = ''; + $alter_queries = $wpdb->get_results( "SELECT * FROM `{$alter_table_name}`", ARRAY_A ); + if( ! empty( $alter_queries ) ) { + foreach( $alter_queries as $alter_query ) { + $sql .= $alter_query['query']; + } + } + return $sql; + } // After table migration, delete old tables and rename new tables removing the temporarily prefix function ajax_finalize_backup() { global $wpdb; // This particular function can be accessed by non logged in users AND logged in users if ( ! current_user_can( 'manage_options' ) ) { - if ( ! $this->verify_signature( $_POST, $this->settings['key'] ) ) { + $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent', 'url', 'key', 'form_data', 'stage', 'prefix', 'type', 'location' ) ); + if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { echo $this->invalid_content_verification_error . ' (#123)'; exit; } @@ -451,57 +761,124 @@ function ajax_finalize_backup() { if ( $_POST['intent'] == 'pull' ) { $temp_tables = $this->get_tables( 'temp' ); - $sql = ''; + $sql = "SET FOREIGN_KEY_CHECKS=0;\n"; + + $preserved_options = array( 'wpmdb_settings', 'wpmdb_error_log' ); + + $this->form_data = $this->parse_migration_form_data( $_POST['form_data'] ); + if( isset( $this->form_data['keep_active_plugins'] ) ) { + $preserved_options[] = 'active_plugins'; + } + + $preserved_options = apply_filters( 'wpmdb_preserved_options', $preserved_options ); + foreach ( $temp_tables as $table ) { $sql .= 'DROP TABLE IF EXISTS ' . $this->backquote( substr( $table, strlen( $this->temp_prefix ) ) ) . ';'; $sql .= "\n"; $sql .= 'RENAME TABLE ' . $this->backquote( $table ) . ' TO ' . $this->backquote( substr( $table, strlen( $this->temp_prefix ) ) ) . ';'; $sql .= "\n"; } - // reset the wpmdb options after everything has migrated - $sql .= 'UPDATE `' . $wpdb->prefix . 'options` SET `option_value` =\'' . serialize( $this->settings ) . '\' WHERE `option_name` = \'wpmdb_settings\';'; + + $preserved_options_data = $wpdb->get_results( sprintf( "SELECT * FROM %soptions WHERE `option_name` IN ('%s')", $wpdb->prefix, implode( "','", $preserved_options ) ), ARRAY_A ); + + foreach( $preserved_options_data as $option ) { + $sql .= $wpdb->prepare( "DELETE FROM `{$_POST['prefix']}options` WHERE `option_name` = %s;\n", $option['option_name'] ); + $sql .= $wpdb->prepare( "INSERT INTO `{$_POST['prefix']}options` ( `option_id`, `option_name`, `option_value`, `autoload` ) VALUES ( NULL , %s, %s, %s );\n", $option['option_name'], $option['option_value'], $option['autoload'] ); + } + + $alter_table_name = $this->get_alter_table_name(); + $sql .= $this->get_alter_queries(); + $sql .= "DROP TABLE IF EXISTS " . $this->backquote( $alter_table_name ) . ";\n"; + $this->process_chunk( $sql ); + + $type = ( isset( $_POST['type'] ) ? 'push' : 'pull' ); + $location = ( isset( $_POST['location'] ) ? $_POST['location'] : $_POST['url'] ); + + if( ! isset( $_POST['location'] ) ) { + $data = array(); + $data['action'] = 'wpmdb_fire_migration_complete'; + $data['url'] = home_url(); + $data['sig'] = $this->create_signature( $data, $_POST['key'] ); + $ajax_url = trailingslashit( $_POST['url'] ) . 'wp-admin/admin-ajax.php'; + $response = $this->remote_post( $ajax_url, $data, __FUNCTION__ ); + echo $response; + $this->display_errors(); + } + + do_action( 'wpmdb_migration_complete', $type, $location ); } else { + do_action( 'wpmdb_migration_complete', 'push', $_POST['url'] ); $data = $_POST; $data['intent'] = 'pull'; + $data['prefix'] = $wpdb->prefix; + $data['type'] = 'push'; + $data['location'] = home_url(); $data['sig'] = $this->create_signature( $data, $data['key'] ); $ajax_url = trailingslashit( $_POST['url'] ) . 'wp-admin/admin-ajax.php'; - $this->remote_post( $ajax_url, $data, __FUNCTION__ ); + $response = $this->remote_post( $ajax_url, $data, __FUNCTION__ ); + echo $response; $this->display_errors(); } exit; } function ajax_process_chunk() { - // We need to strip before signature verification, otherwise verification will fail - $_POST['chunk'] = stripslashes( $_POST['chunk'] ); + $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'table', 'chunk_gzipped' ) ); + $gzip = ( isset( $_POST['chunk_gzipped'] ) && $_POST['chunk_gzipped'] ); + + $tmp_file_name = 'chunk.txt'; + if( $gzip ) { + $tmp_file_name .= '.gz'; + } + + $tmp_file_path = wp_tempnam( $tmp_file_name ); + if ( !isset( $_FILES['chunk']['tmp_name'] ) || !move_uploaded_file( $_FILES['chunk']['tmp_name'], $tmp_file_path ) ) { + echo 'Could not upload the SQL to the server. (#135)'; + exit; + } - if ( !$this->verify_signature( $_POST, $this->settings['key'] ) ) { + if ( false === ( $chunk = file_get_contents( $tmp_file_path ) ) ) { + echo 'Could not read the SQL we\'ve uploaded to the server. (#136)'; + exit; + } + + @unlink( $tmp_file_path ); + + $filtered_post['chunk'] = $chunk; + + if ( !$this->verify_signature( $filtered_post, $this->settings['key'] ) ) { echo $this->invalid_content_verification_error . ' (#130)'; exit; } - $this->process_chunk( $_POST['chunk'] ); + if ( $this->settings['allow_push'] != true ) { + echo 'The connection succeeded but the remote site is configured to reject push connections. You can change this in the "settings" tab on the remote site. (#133)'; + exit; + } + + if( $gzip ) { + $filtered_post['chunk'] = gzuncompress( $filtered_post['chunk'] ); + } + + $this->process_chunk( $filtered_post['chunk'] ); exit; } function process_chunk( $chunk ) { // prepare db - set_time_limit( 0 ); - $db = $this->get_db_object(); - $i = 1; - if ( $db->multi_query( $chunk ) ) { - do { - $i++; - } while ( $db->next_result() ); - } - if ( $db->errno ) { - echo "Error executing statement $i in the following batch of queries.\n"; - echo $chunk . "\n"; - echo $db->error; + global $wpdb; + $this->set_time_limit(); + + $queries = array_filter( explode( ";\n", $chunk ) ); + + $wpdb->show_errors(); + foreach( $queries as $query ) { + if( false === $wpdb->query( $query ) ) { + exit; + } } - $db->close(); } function create_signature( $data, $key ) { @@ -513,6 +890,9 @@ function create_signature( $data, $key ) { } function verify_signature( $data, $key ) { + if( empty( $data['sig'] ) ) { + return false; + } $temp = $data; $computed_signature = $this->create_signature( $temp, $key ); return $computed_signature === $data['sig']; @@ -520,9 +900,12 @@ function verify_signature( $data, $key ) { // This the first AJAX end point when a table is about to be migrated / backed up function ajax_prepare_table_migration() { + global $wpdb; // Check that the user is valid and is allowed to perform a table migration if ( ! current_user_can( 'manage_options' ) ) { - if ( ! $this->verify_signature( $_POST, $this->settings['key'] ) ) { + $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent', 'url', 'key', 'table', 'form_data', 'stage', 'bottleneck', 'prefix', 'current_row', 'dump_filename', 'last_table', 'gzip', 'primary_keys' ) ); + $filtered_post['primary_keys'] = stripslashes( $filtered_post['primary_keys'] ); + if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { echo $this->invalid_content_verification_error . ' (#119)'; exit; } @@ -537,15 +920,19 @@ function ajax_prepare_table_migration() { // flip the intent so we can trigger the else statement below $data['intent'] = 'pull'; $ajax_url = trailingslashit( $_POST['url'] ) . 'wp-admin/admin-ajax.php'; + $data['primary_keys'] = stripslashes( $data['primary_keys'] ); $data['sig'] = $this->create_signature( $data, $data['key'] ); - $this->remote_post( $ajax_url, $data, __FUNCTION__ ); + $response = $this->remote_post( $ajax_url, $data, __FUNCTION__ ); $this->display_errors(); + echo $response; } else { - $sql_dump_file_name = $this->get_sql_dump_file_name( 'backup' ); if ( isset( $this->form_data['gzip_file'] ) ) { unset( $this->form_data['gzip_file'] ); } + $this->maximum_chunk_size = $this->get_bottleneck(); + $sql_dump_file_name = $this->get_upload_info( 'path' ) . DS; + $sql_dump_file_name .= $this->format_dump_name( $_POST['dump_filename'] ); $file_created = file_exists( $sql_dump_file_name ); $this->fp = $this->open( $sql_dump_file_name ); if ( $file_created == false ) { @@ -558,20 +945,18 @@ function ajax_prepare_table_migration() { exit; } - // Pull and push need to be handled differently for obvious reason, trigger different code depending on the migration intent (push or pull) + // Pull and push need to be handled differently for obvious reasons, trigger different code depending on the migration intent (push or pull) if ( $_POST['intent'] == 'push' || $_POST['intent'] == 'savefile' ) { + $this->maximum_chunk_size = $this->get_bottleneck(); if ( isset( $_POST['bottleneck'] ) ) { - $this->maximum_chunk_number = floor( $_POST['bottleneck'] / $this->max_insert_string_len ); + $this->maximum_chunk_size = (int) $_POST['bottleneck']; } if ( $_POST['intent'] == 'push' ) { $this->remote_key = $_POST['key']; $this->remote_url = $_POST['url']; } - $sql_dump_file_name = $this->get_sql_dump_file_name(); - - if ( $this->gzip() && isset( $this->form_data['gzip_file'] ) ) { - $sql_dump_file_name .= '.gz'; - } + $sql_dump_file_name = $this->get_upload_info( 'path' ) . DS; + $sql_dump_file_name .= $this->format_dump_name( $_POST['dump_filename'] ); if ( $_POST['intent'] == 'savefile' ) { $this->fp = $this->open( $sql_dump_file_name ); @@ -585,32 +970,39 @@ function ajax_prepare_table_migration() { else { $data = $_POST; $data['action'] = 'wpmdb_process_pull_request'; - $data['pull_limit'] = $this->get_max_allowed_packet_size(); + $data['pull_limit'] = $this->get_sensible_pull_limit(); + $data['prefix'] = $wpdb->prefix; if ( isset( $data['sig'] ) ) { unset( $data['sig'] ); } $ajax_url = trailingslashit( $data['url'] ) . 'wp-admin/admin-ajax.php'; - $row_tracker = ''; + $data['primary_keys'] = stripslashes( $data['primary_keys'] ); $data['sig'] = $this->create_signature( $data, $data['key'] ); - while ( $row_tracker != -1 ) { - $response = $this->remote_post( $ajax_url, $data, __FUNCTION__ ); - $this->display_errors(); - if ( is_serialized( $response ) ) { - $response = unserialize( $response ); - } - else { - echo $response; - break; - } - $row_tracker = $response['row_tracker']; - $chunk = $response['chunk']; - if ( ! empty( $chunk ) ) { - $this->process_chunk( $chunk ); - } - $data['current_row'] = ( empty( $response['row_tracker'] ) ? 0 : $response['row_tracker'] ); - $data['sig'] = $this->create_signature( $data, $data['key'] ); + $response = $this->remote_post( $ajax_url, $data, __FUNCTION__ ); + $this->display_errors(); + + if( strpos( $response, ';' ) === false ) { + echo $response; + exit; + } + + // returned data is just a big string like this query;query;query;33 + // need to split this up into a chunk and row_tracker + $row_information = trim( substr( strrchr( $response, "\n" ), 1 ) ); + $row_information = explode( ',', $row_information ); + $chunk = substr( $response, 0, strrpos( $response, ";\n" ) + 1 ); + + if ( ! empty( $chunk ) ) { + $this->process_chunk( $chunk ); } + + echo json_encode( + array( + 'current_row' => $row_information[0], + 'primary_keys' => $row_information[1] + ) + ); } exit; } @@ -618,26 +1010,32 @@ function ajax_prepare_table_migration() { // Occurs right before the first table is migrated / backed up during the migration process // Does a quick check to make sure the verification string is valid and also opens / creates files for writing to (if required) function ajax_initiate_migration() { - $datetime = date('YmdHis'); + $this->form_data = $this->parse_migration_form_data( $_POST['form_data'] ); if ( $_POST['intent'] == 'savefile' ) { - $this->form_data = $this->parse_migration_form_data( $_POST['form_data'] ); - $return = array( 'code' => 200, 'message' => 'OK', 'body' => json_encode( array( 'error' => 0 ) ), ); - $_POST['datetime'] = $datetime; - $sql_dump_file_name = $this->get_sql_dump_file_name(); + $return['dump_filename'] = basename( $this->get_sql_dump_info( 'migrate', 'path' ) ); + $return['dump_url'] = $this->get_sql_dump_info( 'migrate', 'url' ); + $dump_filename_no_extension = substr( $return['dump_filename'], 0, -4 ); + + $create_alter_table_query = $this->get_create_alter_table_query(); + // sets up our table to store 'ALTER' queries + $this->process_chunk( $create_alter_table_query ); if ( $this->gzip() && isset( $this->form_data['gzip_file'] ) ) { - $sql_dump_file_name .= '.gz'; + $return['dump_filename'] .= '.gz'; + $return['dump_url'] .= '.gz'; } - $this->fp = $this->open( $sql_dump_file_name ); + $this->fp = $this->open( $this->get_upload_info( 'path' ) . DS . $return['dump_filename'] ); $this->db_backup_header(); $this->close( $this->fp ); + + $return['dump_filename'] = $dump_filename_no_extension; } else { // does one last check that our verification string is valid @@ -656,13 +1054,28 @@ function ajax_initiate_migration() { } else{ $return = array( - 'body' => $response + 'body' => stripslashes( $response ), ); + $return = json_decode( $response, ARRAY_A ); + } + + if( $_POST['intent'] == 'pull' ) { + // sets up our table to store 'ALTER' queries + $create_alter_table_query = $this->get_create_alter_table_query(); + $this->process_chunk( $create_alter_table_query ); + } + + if( ! empty( $this->form_data['create_backup'] ) && $_POST['intent'] == 'pull' ) { + $return['dump_filename'] = basename( $this->get_sql_dump_info( 'backup', 'path' ) ); + $return['dump_filename'] = substr( $return['dump_filename'], 0, -4 ); + $return['dump_url'] = $this->get_sql_dump_info( 'backup', 'url' ); } } - $return['datetime'] = $datetime; + $return['dump_filename'] = ( empty( $return['dump_filename'] ) ? '' : $return['dump_filename'] ); + $return['dump_url'] = ( empty( $return['dump_url'] ) ? '' : $return['dump_url'] ); + echo json_encode( $return ); exit; @@ -671,7 +1084,8 @@ function ajax_initiate_migration() { // End point for the above AJAX call, ensures that the verification string is valid before continuing with the migration function ajax_respond_initiate_migration() { $return = array(); - if ( $this->verify_signature( $_POST, $this->settings['key'] ) ) { + $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent', 'form_data' ) ); + if ( $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { if ( isset( $this->settings['allow_' . $_POST['intent']] ) && $this->settings['allow_' . $_POST['intent']] == true ) { $return['error'] = 0; } @@ -684,8 +1098,22 @@ function ajax_respond_initiate_migration() { $return['error'] = 1; $return['message'] = $this->invalid_content_verification_error . ' (#111)'; } + + $this->form_data = $this->parse_migration_form_data( $_POST['form_data'] ); + if( ! empty( $this->form_data['create_backup'] ) && $_POST['intent'] == 'push' ) { + $return['dump_filename'] = basename( $this->get_sql_dump_info( 'backup', 'path' ) ); + $return['dump_filename'] = substr( $return['dump_filename'], 0, -4 ); + $return['dump_url'] = $this->get_sql_dump_info( 'backup', 'url' ); + } + echo json_encode( $return ); + if( $_POST['intent'] == 'push' ) { + // sets up our table to store 'ALTER' queries + $create_alter_table_query = $this->get_create_alter_table_query(); + $this->process_chunk( $create_alter_table_query ); + } + exit; } @@ -701,14 +1129,14 @@ function ajax_save_profile() { $this->settings['profiles'][$key] = $profile; $this->settings['profiles'][$key]['name'] = $name; } - update_site_option( 'wpmdb_settings', $this->settings ); + update_option( 'wpmdb_settings', $this->settings ); echo count( $this->settings['profiles'] ) - 1; exit; } function ajax_save_setting() { $this->settings[$_POST['setting']] = ( $_POST['checked'] == 'false' ? false : true ); - update_site_option( 'wpmdb_settings', $this->settings ); + update_option( 'wpmdb_settings', $this->settings ); exit; } @@ -716,7 +1144,7 @@ function ajax_delete_migration_profile() { $key = $_POST['profile_id']; if ( isset( $this->settings['profiles'][$key] ) ) { unset( $this->settings['profiles'][$key] ); - update_site_option( 'wpmdb_settings', $this->settings ); + update_option( 'wpmdb_settings', $this->settings ); } else { echo '-1'; @@ -726,7 +1154,7 @@ function ajax_delete_migration_profile() { function ajax_reset_api_key() { $this->settings['key'] = $this->generate_key(); - update_site_option( 'wpmdb_settings', $this->settings ); + update_option( 'wpmdb_settings', $this->settings ); printf( "%s\n%s", site_url( '', 'https' ), $this->settings['key'] ); exit; } @@ -741,49 +1169,76 @@ function ajax_prepare_remote_connection() { $data['sig'] = $this->create_signature( $data, $_POST['key'] ); $ajax_url = trailingslashit( $_POST['url'] ) . 'wp-admin/admin-ajax.php'; - $response = $this->remote_post( $ajax_url, $data, __FUNCTION__, array( 'timeout' => 5 ) ); - + $timeout = apply_filters( 'wpmdb_prepare_remote_connection_timeout', 10 ); + $response = $this->remote_post( $ajax_url, $data, __FUNCTION__, compact( 'timeout' ), true ); + $url_bits = parse_url( $this->attempting_to_connect_to ); $return = $response; + + $alt_action = ''; + if ( false === $response ) { - $return = array( 'wpmdb_error' => 1, 'body' => $this->error . ' Try again?' ); + $return = array( 'wpmdb_error' => 1, 'body' => $this->error ); + echo json_encode( $return ); + exit; } - $response = json_decode( $response, true ); + $response = unserialize( $response ); if ( isset( $response['error'] ) && $response['error'] == 1 ) { $return = array( 'wpmdb_error' => 1, 'body' => $response['message'] ); + echo json_encode( $return ); + exit; } - echo json_encode( $return ); + $response['scheme'] = $url_bits['scheme']; + $return = json_encode( $response ); + echo $return; exit; } + function format_table_sizes( $size ) { + $size *= 1024; + return size_format( $size ); + } + // AJAX end point for the above AJAX call, returns table information, absolute file path, table prefix, etc function ajax_establish_remote_connection() { global $wpdb; + $return = array(); - if ( $this->verify_signature( $_POST, $this->settings['key'] ) ) { - if ( isset( $this->settings['allow_' . $_POST['intent']] ) && $this->settings['allow_' . $_POST['intent']] == true ) { - $return['tables'] = $this->get_tables(); - $return['table_sizes'] = $this->get_table_sizes(); - $return['path'] = $this->absolute_root_file_path; - $return['url'] = home_url(); - $return['prefix'] = $wpdb->prefix; - $return['bottleneck'] = $this->get_bottleneck(); - $return['error'] = 0; - } - else { - $return['error'] = 1; - $return['message'] = 'The connection succeeded but the remote site is configured to reject ' . $_POST['intent'] . ' connections. You can change this in the "settings" tab on the remote site. (#122) Try again?'; - } - } - else { + + $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent' ) ); + if ( !$this->verify_signature( $filtered_post, $this->settings['key'] ) ) { $return['error'] = 1; $return['message'] = $this->invalid_content_verification_error . ' (#120) Try again?'; + echo serialize( $return ); + exit; + } + + if ( !isset( $this->settings['allow_' . $_POST['intent']] ) || $this->settings['allow_' . $_POST['intent']] != true ) { + $return['error'] = 1; + $return['message'] = 'The connection succeeded but the remote site is configured to reject ' . $_POST['intent'] . ' connections. You can change this in the "settings" tab on the remote site. (#122) Try again?'; + echo serialize( $return ); + exit; } - echo json_encode( $return ); + $plugin_info = get_plugin_data( $this->plugin_file_path, false, false ); + $return['tables'] = $this->get_tables(); + $return['prefixed_tables'] = $this->get_tables( 'prefix' ); + $return['table_sizes'] = $this->get_table_sizes(); + $return['table_rows'] = $this->get_table_row_count(); + $return['table_sizes_hr'] = array_map( array( $this, 'format_table_sizes' ), $this->get_table_sizes() ); + $return['path'] = $this->absolute_root_file_path; + $return['url'] = home_url(); + $return['prefix'] = $wpdb->prefix; + $return['bottleneck'] = $this->get_bottleneck(); + $return['error'] = 0; + $return['plugin_version'] = $plugin_info['Version']; + $return['domain'] = ( defined( 'DOMAIN_CURRENT_SITE' ) ? DOMAIN_CURRENT_SITE : '' ); + $return['uploads_dir'] = $this->get_short_uploads_dir(); + $return['gzip'] = ( $this->gzip() ? '1' : '0' ); + echo serialize( $return ); exit; } @@ -802,13 +1257,13 @@ function generate_key() { return $key; } - // Get only the table beginning with our DB prefix or emporary prefix, also skip views + // Get only the table beginning with our DB prefix or temporary prefix, also skip views function get_tables( $scope = 'regular' ) { global $wpdb; $prefix = ( $scope == 'temp' ? $this->temp_prefix : $wpdb->prefix ); $tables = $wpdb->get_results( 'SHOW FULL TABLES', ARRAY_N ); foreach ( $tables as $table ) { - if ( 0 !== strpos( $table[0], $prefix ) || $table[1] == 'VIEW' ) { + if ( ( ( $scope == 'temp' || $scope == 'prefix' ) && 0 !== strpos( $table[0], $prefix ) ) || $table[1] == 'VIEW' ) { continue; } $clean_tables[] = $table[0]; @@ -824,13 +1279,28 @@ function get_profile( $profile_id ) { return $this->settings['profiles'][$profile_id]; } - function get_table_sizes() { + function get_table_row_count() { global $wpdb; + $results = $wpdb->get_results( $wpdb->prepare( + 'SELECT table_name, TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = %s', DB_NAME + ), ARRAY_A + ); + $return = array(); + foreach( $results as $results ) { + $return[$results['table_name']] = ( $results['TABLE_ROWS'] == 0 ? 1 : $results['TABLE_ROWS'] ); + } + return $return; + } + + function get_table_sizes( $scope = 'regular' ) { + global $wpdb; + $prefix = ( $scope == 'temp' ? $this->temp_prefix : $wpdb->prefix ); $results = $wpdb->get_results( $wpdb->prepare( 'SELECT TABLE_NAME AS "table", ROUND((data_length + index_length)/1024,0) AS "size" FROM information_schema.TABLES - WHERE information_schema.TABLES.table_schema="%s"', DB_NAME + WHERE information_schema.TABLES.table_schema="%s" + AND information_schema.TABLES.table_type="%s"', DB_NAME, "BASE TABLE" ), ARRAY_A ); @@ -861,27 +1331,70 @@ function get_post_max_size() { return $val; } - function get_max_allowed_packet_size() { - global $wpdb; - $size = $wpdb->get_var( 'select VARIABLE_VALUE from information_schema.GLOBAL_VARIABLES where VARIABLE_NAME = \'max_allowed_packet\'' ); - return $size; + function get_sensible_pull_limit() { + return apply_filters( 'wpmdb_sensible_pull_limit', min( 26214400, $this->settings['max_request'] ) ); } - function get_bottleneck() { - return min( $this->get_post_max_size(), $this->get_max_allowed_packet_size() ); + function get_bottleneck( $type = 'regular' ) { + $suhosin_limit = false; + $suhosin_request_limit = false; + $suhosin_post_limit = false; + + if ( function_exists( 'ini_get' ) ) { + $suhosin_request_limit = ini_get( 'suhosin.request.max_value_length' ); + $suhosin_post_limit = ini_get( 'suhosin.post.max_value_length' ); + } + + if ( $suhosin_request_limit && $suhosin_post_limit ) { + $suhosin_limit = min( $suhosin_request_limit, $suhosin_post_limit ); + } + + // we have to account for HTTP headers and other bloating, here we minus 1kb for bloat + $post_max_upper_size = apply_filters( 'wpmdb_post_max_upper_size', 26214400 ); + $calculated_bottleneck = min( ( $this->get_post_max_size() - 1024 ), $post_max_upper_size ); + + if ( $suhosin_limit ) { + $calculated_bottleneck = min( $calculated_bottleneck, $suhosin_limit - 1024 ); + } + + if( $type != 'max' ) { + $calculated_bottleneck = min( $calculated_bottleneck, $this->settings['max_request'] ); + } + + return apply_filters( 'wpmdb_bottleneck', $calculated_bottleneck ); } function ajax_process_pull_request() { - if ( ! $this->verify_signature( $_POST, $this->settings['key'] ) ) { + $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent', 'url', 'key', 'table', 'form_data', 'stage', 'bottleneck', 'prefix', 'current_row', 'dump_filename', 'pull_limit', 'last_table', 'gzip', 'primary_keys' ) ); + + // verification will fail unless we strip slashes on primary_keys + $filtered_post['primary_keys'] = stripslashes( $filtered_post['primary_keys'] ); + + if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { echo $this->invalid_content_verification_error . ' (#124)'; exit; } - $this->maximum_chunk_number = floor( $_POST['pull_limit'] / $this->max_insert_string_len ); + + if ( $this->settings['allow_pull'] != true ) { + echo 'The connection succeeded but the remote site is configured to reject pull connections. You can change this in the "settings" tab on the remote site. (#132)'; + exit; + } + + $this->maximum_chunk_size = $_POST['pull_limit']; $this->backup_table( $_POST['table'] ); $this->display_errors(); exit; } + function format_dump_name( $dump_name ) { + $extension = '.sql'; + $dump_name = sanitize_file_name( $dump_name ); + if ( $this->gzip() && isset( $this->form_data['gzip_file'] ) ) { + $extension .= '.gz'; + } + return $dump_name . $extension; + } + function options_page() { ?> @@ -890,11 +1403,37 @@ function options_page() {

    Migrate DB Pro

    get_new_beta_version_msg() ) { - echo '

    ', $msg, '

    '; + $hide_warning = apply_filters( 'wpmdb_hide_safe_mode_warning', false ); + if ( function_exists( 'ini_get' ) && ini_get( 'safe_mode' ) && !$hide_warning ) { + ?> +
    +

    + PHP Safe Mode Enabled — + We do not officially support running this plugin in + safe mode because set_time_limit() + has no effect. Therefore we can't extend the run time of the + script and ensure it doesn't time out before the migration completes. + We haven't disabled the plugin however, so you're free to cross your + fingers and hope for the best. However, if you have trouble, + we can't help you until you turn off safe mode. + + Your current PHP run time limit is set to seconds. + +

    +
    + + +
    @@ -925,10 +1464,117 @@ function options_page() { function apply_replaces( $subject, $is_serialized = false ) { $search = $this->form_data['replace_old']; $replace = $this->form_data['replace_new']; - $new = str_replace( $search, $replace, $subject, $count ); + $new = str_ireplace( $search, $replace, $subject, $count ); return $new; } + function set_time_limit() { + if ( !function_exists( 'ini_get' ) || !ini_get( 'safe_mode' ) ) { + set_time_limit( 0 ); + } + } + + function process_sql_constraint( $create_query, $table, &$alter_table_query ) { + if( preg_match( '@CONSTRAINT|FOREIGN[\s]+KEY@', $create_query ) ) { + + $sql_constraints_query = ''; + + $nl_nix = "\n"; + $nl_win = "\r\n"; + $nl_mac = "\r"; + if( strpos( $create_query, $nl_win ) !== false ) { + $crlf = $nl_win; + } + elseif( strpos( $create_query, $nl_mac ) !== false ) { + $crlf = $nl_mac; + } + elseif( strpos( $create_query, $nl_nix ) !== false ) { + $crlf = $nl_nix; + } + + // Split the query into lines, so we can easily handle it. + // We know lines are separated by $crlf (done few lines above). + $sql_lines = explode( $crlf, $create_query ); + $sql_count = count( $sql_lines ); + + // lets find first line with constraints + for( $i = 0; $i < $sql_count; $i++ ) { + if (preg_match( + '@^[\s]*(CONSTRAINT|FOREIGN[\s]+KEY)@', + $sql_lines[$i] + )) { + break; + } + } + + // If we really found a constraint + if( $i != $sql_count ) { + + // remove, from the end of create statement + $sql_lines[$i - 1] = preg_replace( + '@,$@', + '', + $sql_lines[$i - 1] + ); + + // let's do the work + $sql_constraints_query .= 'ALTER TABLE ' + . $this->backquote( $table ) + . $crlf; + + $first = true; + for( $j = $i; $j < $sql_count; $j++ ) { + if( preg_match( + '@CONSTRAINT|FOREIGN[\s]+KEY@', + $sql_lines[$j] + )) { + if( strpos( $sql_lines[$j], 'CONSTRAINT' ) === false ) { + $tmp_str = preg_replace( + '/(FOREIGN[\s]+KEY)/', + 'ADD \1', + $sql_lines[$j] + ); + $sql_constraints_query .= $tmp_str; + } + else { + $tmp_str = preg_replace( + '/(CONSTRAINT)/', + 'ADD \1', + $sql_lines[$j] + ); + $sql_constraints_query .= $tmp_str; + preg_match( + '/(CONSTRAINT)([\s])([\S]*)([\s])/', + $sql_lines[$j], + $matches + ); + } + $first = false; + } + else { + break; + } + } + $sql_constraints_query .= ";\n"; + + $create_query = implode( + $crlf, + array_slice($sql_lines, 0, $i) + ) + . $crlf + . implode( + $crlf, + array_slice( $sql_lines, $j, $sql_count - 1 ) + ); + unset( $sql_lines ); + + $alter_table_query = $sql_constraints_query; + return $create_query; + } + } + return $create_query; + } + /** * Taken partially from phpMyAdmin and partially from * Alain Wolf, Zurich - Switzerland @@ -941,23 +1587,27 @@ function apply_replaces( $subject, $is_serialized = false ) { */ function backup_table( $table ) { global $wpdb; - set_time_limit( 0 ); + $this->set_time_limit(); if ( empty( $this->form_data ) ) { $this->form_data = $this->parse_migration_form_data( $_POST['form_data'] ); } $temp_prefix = $this->temp_prefix; + $remote_prefix = ( isset( $_POST['prefix'] ) ? $_POST['prefix'] : $wpdb->prefix ); - $table_structure = $wpdb->get_results( "DESCRIBE $table" ); + $table_structure = $wpdb->get_results( "DESCRIBE " . $this->backquote( $table ) ); if ( ! $table_structure ) { $this->error = 'Failed to retrieve table structure, please ensure your database is online. (#125)'; return false; } $current_row = -1; - if ( isset( $_POST['current_row'] ) ) { - $current_row = $_POST['current_row']; + if ( ! empty( $_POST['current_row'] ) ) { + $temp_current_row = trim( $_POST['current_row'] ); + if ( ! empty( $temp_current_row ) ) { + $current_row = (int) $temp_current_row; + } } if ( $current_row == -1 ) { @@ -984,7 +1634,7 @@ function backup_table( $table ) { $this->stow( "\n" ); } - $create_table = $wpdb->get_results( "SHOW CREATE TABLE $table", ARRAY_N ); + $create_table = $wpdb->get_results( "SHOW CREATE TABLE " . $this->backquote( $table ), ARRAY_N ); if ( false === $create_table ) { $this->error = 'Failed to generate the create table query, please ensure your database is online. (#126)'; return false; @@ -994,7 +1644,25 @@ function backup_table( $table ) { $create_table[0][1] = str_replace( 'CREATE TABLE `', 'CREATE TABLE `' . $temp_prefix, $create_table[0][1] ); } - $this->stow( $create_table[0][1] . ' ;' ); + $create_table[0][1] = str_replace( 'TYPE=', 'ENGINE=', $create_table[0][1] ); + + $alter_table_query = ''; + $create_table[0][1] = $this->process_sql_constraint( $create_table[0][1], $table, $alter_table_query ); + + $create_table[0][1] = apply_filters( 'wpmdb_create_table_query', $create_table[0][1], $table ); + + $this->stow( $create_table[0][1] . ";\n" ); + + if( ! empty( $alter_table_query ) ) { + $alter_table_name = $this->get_alter_table_name(); + $insert = sprintf( "INSERT INTO %s ( `query` ) VALUES ( '%s' );\n", $this->backquote( $alter_table_name ), esc_sql( $alter_table_query ) ); + if ( $this->form_data['action'] == 'savefile' || $_POST['stage'] == 'backup' ) { + $this->process_chunk( $insert ); + } + else { + $this->stow( $insert ); + } + } // Comment in SQL-file if ( $this->form_data['action'] == 'savefile' || $_POST['stage'] == 'backup' ) { @@ -1042,8 +1710,19 @@ function backup_table( $table ) { $table_name = $temp_prefix . $table; } + $this->primary_keys = array(); foreach( $table_structure as $col ){ $field_set[] = $this->backquote( $col->Field ); + if( false !== strpos( $col->Type, 'int' ) && $col->Key == 'PRI' ) { + $this->primary_keys[$col->Field] = 0; + } + } + + if( ! empty( $_POST['primary_keys'] ) ) { + $_POST['primary_keys'] = trim( $_POST['primary_keys'] ); + if( ! empty( $_POST['primary_keys'] ) && is_serialized( $_POST['primary_keys'] ) ) { + $this->primary_keys = unserialize( stripslashes( $_POST['primary_keys'] ) ); + } } $fields = implode( ', ', $field_set ); @@ -1052,17 +1731,65 @@ function backup_table( $table ) { do { $where = ''; - if ( isset( $this->form_data['exclude_spam'] ) && $wpdb->comments == $table ) { - $where = ' WHERE comment_approved != "spam"'; - } elseif ( isset( $this->form_data['exclude_revisions'] ) && $wpdb->posts == $table ) { - $where = ' WHERE post_type != "revision"'; + $order_by = ''; + // We need ORDER BY here because with LIMIT, sometimes it will return + // the same results from the previous query and we'll have duplicate insert statements + if ( isset( $this->form_data['exclude_spam'] ) ) { + if ( $wpdb->comments == $table ) { + $where = 'WHERE comment_approved != "spam"'; + } + elseif ( $wpdb->commentmeta == $table ) { + $where = sprintf( 'INNER JOIN %1$s + ON %1$s.comment_ID = %2$s.comment_id AND %1$s.comment_approved != \'spam\'', + $this->backquote( $wpdb->comments ), $this->backquote( $wpdb->commentmeta ) ); + } + } + elseif ( isset( $this->form_data['exclude_revisions'] ) && $wpdb->posts == $table ) { + $where = 'WHERE post_type != "revision"'; + } + + $limit = "LIMIT {$row_start}, {$row_inc}"; + + if( ! empty( $this->primary_keys ) ) { + $primary_keys_keys = array_keys( $this->primary_keys ); + $primary_keys_keys = array_map( array( $this, 'backquote' ), $primary_keys_keys ); + + $order_by = 'ORDER BY ' . implode( ',', $primary_keys_keys ); + $where .= ( empty( $where ) ? 'WHERE ' : ' AND ' ); + + $temp_primary_keys = $this->primary_keys; + + $primary_key_count = count( $temp_primary_keys ); + for( $j = 0; $j < $primary_key_count; $j++ ) { + $where .= ( $j == 0 ? '( ' : ' OR ( ' ); + $i = 0; + foreach( $temp_primary_keys as $primary_key => $value ) { + $where .= ( $i == 0 ? '' : ' AND ' ); + $operator = ( count( $temp_primary_keys ) - 1 == $i ? '>' : '=' ); + $where .= sprintf( '%s %s %s', $this->backquote( $primary_key ), $operator, $value ); + ++$i; + } + $tmp = $temp_primary_keys; + $keys = array_keys( $tmp ); + $end = end( $keys ); + unset( $temp_primary_keys[$end] ); + $where .= ' )'; + } + + $limit = "LIMIT $row_inc"; } - $table_data = $wpdb->get_results( "SELECT * FROM $table $where LIMIT {$row_start}, {$row_inc}" ); + $where = apply_filters( 'wpmdb_rows_where', $where, $table ); + $order_by = apply_filters( 'wpmdb_rows_order_by', $order_by, $table ); + $limit = apply_filters( 'wpmdb_rows_limit', $limit, $table ); + + $sql = "SELECT " . $this->backquote( $table ) . ".* FROM " . $this->backquote( $table ) . " $where $order_by $limit"; + $sql = apply_filters( 'wpmdb_rows_sql', $sql, $table ); + + $table_data = $wpdb->get_results( $sql ); if ( $table_data ) { foreach ( $table_data as $row ) { - ++$this->row_tracker; $values = array(); foreach ( $row as $key => $value ) { if ( isset( $ints[strtolower( $key )] ) && $ints[strtolower( $key )] ) { @@ -1075,27 +1802,13 @@ function backup_table( $table ) { $values[] = 'NULL'; } else { - if ( is_serialized( $value ) && false !== ( $data = @unserialize( $value ) ) ) { - if ( is_array( $data ) ) { - if ( $_POST['stage'] != 'backup' ) { - array_walk_recursive( $data, array( $this, 'replace_array_values' ) ); - } - } - elseif ( is_string( $data ) ) { - if ( $_POST['stage'] != 'backup' ) { - $data = $this->apply_replaces( $data, true ); - } - } - $value = serialize( $data ); - } - // Skip replacing GUID if the option is set - elseif ( 'guid' != $key || ( isset( $this->form_data['replace_guids'] ) && $wpdb->posts == $table ) ) { + if ( 'guid' != $key || ( isset( $this->form_data['replace_guids'] ) && ( $wpdb->posts == $table || preg_match( '/' . $wpdb->prefix . '[0-9]+_posts/', $table ) ) ) ) { if ( $_POST['stage'] != 'backup' ) { - $value = $this->apply_replaces( $value ); + $value = $this->recursive_unserialize_replace( $value ); } } - + $values[] = "'" . str_replace( $search, $replace, $this->sql_addslashes( $value ) ) . "'"; } } @@ -1104,20 +1817,35 @@ function backup_table( $table ) { $insert_line = '(' . implode( ', ', $values ) . '),'; $insert_line .= "\n"; + if ( ( strlen( $this->current_chunk ) + strlen( $insert_line ) + strlen( $insert_buffer ) + 10 ) > $this->maximum_chunk_size ) { + if( $insert_buffer != $insert_query_template ) { + $insert_buffer = rtrim( $insert_buffer, "\n," ); + $insert_buffer .= " ;\n"; + $this->stow( $insert_buffer ); + $insert_buffer = $insert_query_template; + $query_size = 0; + } + $this->transfer_chunk(); + } + if ( ( $query_size + strlen( $insert_line ) ) > $this->max_insert_string_len && $insert_buffer != $insert_query_template ) { $insert_buffer = rtrim( $insert_buffer, "\n," ); $insert_buffer .= " ;\n"; - $this->buffer_full = true; $this->stow( $insert_buffer ); $insert_buffer = $insert_query_template; $query_size = 0; } - $this->buffer_full = false; - $insert_buffer .= $insert_line; $query_size += strlen( $insert_line ); + ++$this->row_tracker; + + if( ! empty( $this->primary_keys ) ) { + foreach( $this->primary_keys as $primary_key => $value ) { + $this->primary_keys[$primary_key] = $row->$primary_key; + } + } } $row_start += $row_inc; @@ -1139,24 +1867,90 @@ function backup_table( $table ) { $this->stow( "# " . sprintf( __( 'End of data contents of table %s', 'wp-migrate-db-pro' ), $this->backquote( $table ) ) . "\n" ); $this->stow( "# --------------------------------------------------------\n" ); $this->stow( "\n" ); - } - // required for pull, tells the remote machine to stop sending pull requests - if ( isset( $_POST['intent'] ) && $_POST['intent'] == 'pull' && $_POST['stage'] != 'backup' ) { - $this->row_tracker = -1; - $this->transfer_chunk(); + if( $_POST['last_table'] == '1' ) { + $this->stow( "#\n" ); + $this->stow( "# Add constraints back in\n" ); + $this->stow( "#\n\n" ); + $this->stow( $this->get_alter_queries() ); + $alter_table_name = $this->get_alter_table_name(); + if ( $this->form_data['action'] == 'savefile' ) { + $wpdb->query( "DROP TABLE IF EXISTS " . $this->backquote( $alter_table_name ) . ";" ); + } + } } - // required for push, sends any remaining data left over in the current_chunk buffer to the remote machine - if ( $this->form_data['action'] != 'savefile' && ! empty( $this->current_chunk ) && $_POST['stage'] != 'backup' ) { - $this->transfer_chunk(); - } + $this->row_tracker = -1; + $this->transfer_chunk(); } // end backup_table() - function replace_array_values( &$value, $key ) { - if ( !is_string( $value ) ) return; - $value = $this->apply_replaces( $value, true ); + /** + * Take a serialized array and unserialize it replacing elements as needed and + * unserialising any subordinate arrays and performing the replace on those too. + * + * Mostly from https://github.com/interconnectit/Search-Replace-DB + * + * @param array $data Used to pass any subordinate arrays back to in. + * @param bool $serialized Does the array passed via $data need serialising. + * @param bool $parent_serialized Passes whether the original data passed in was serialized + * + * @return array The original array with all elements replaced as needed. + */ + function recursive_unserialize_replace( $data, $serialized = false, $parent_serialized = false ) { + + $is_json = false; + // some unseriliased data cannot be re-serialized eg. SimpleXMLElements + try { + + if ( is_string( $data ) && ( $unserialized = @unserialize( $data ) ) !== false ) { + $data = $this->recursive_unserialize_replace( $unserialized, true, true ); + } + elseif ( is_array( $data ) ) { + $_tmp = array( ); + foreach ( $data as $key => $value ) { + $_tmp[ $key ] = $this->recursive_unserialize_replace( $value, false, $parent_serialized ); + } + + $data = $_tmp; + unset( $_tmp ); + } + // Submitted by Tina Matter + elseif ( is_object( $data ) ) { + $_tmp = clone $data; + foreach ( $data as $key => $value ) { + $_tmp->$key = $this->recursive_unserialize_replace( $value, false, $parent_serialized ); + } + + $data = $_tmp; + unset( $_tmp ); + } + elseif ( $this->is_json( $data, true ) ) { + $_tmp = array( ); + $data = json_decode( $data, true ); + foreach ( $data as $key => $value ) { + $_tmp[ $key ] = $this->recursive_unserialize_replace( $value, false, $parent_serialized ); + } + + $data = $_tmp; + unset( $_tmp ); + $is_json = true; + } + elseif ( is_string( $data ) ) { + $data = $this->apply_replaces( $data, $parent_serialized ); + } + + if ( $serialized ) + return serialize( $data ); + + if ( $is_json ) + return json_encode( $data ); + + } catch( Exception $error ) { + + } + + return $data; } function db_backup_header() { @@ -1187,6 +1981,7 @@ function close( $fp ) { } function stow( $query_line, $replace = true ) { + $this->current_chunk .= $query_line; if ( $this->form_data['action'] == 'savefile' || $_POST['stage'] == 'backup' ) { if ( $this->gzip() && isset( $this->form_data['gzip_file'] ) ) { if ( ! @gzwrite( $this->fp, $query_line ) ) { @@ -1201,44 +1996,61 @@ function stow( $query_line, $replace = true ) { } } } - else { - $this->current_chunk .= $query_line; - ++$this->current_chunk_number; - if ( $this->current_chunk_number == $this->maximum_chunk_number ) { - $this->transfer_chunk(); - } + else if ( $_POST['intent'] == 'pull' ) { + echo $query_line; } } // Called in the $this->stow function once our chunk buffer is full, will transfer the SQL to the remote server for importing function transfer_chunk() { - if ( $_POST['intent'] == 'pull' ) { - if ( $this->buffer_full === true ) { - --$this->row_tracker; - } - $return = array( - 'row_tracker' => $this->row_tracker, - 'chunk' => $this->current_chunk, + + if( $_POST['intent'] == 'savefile' || $_POST['stage'] == 'backup' ) { + $this->close( $this->fp ); + echo json_encode( + array( + 'current_row' => $this->row_tracker, + 'primary_keys' => serialize( $this->primary_keys ) + ) ); - echo serialize( $return ); exit; } + if ( $_POST['intent'] == 'pull' ) { + echo $this->row_tracker . ',' . serialize( $this->primary_keys ); + exit; + } + + $chunk_gzipped = '0'; + if( isset( $_POST['gzip'] ) && $_POST['gzip'] == '1' && $this->gzip() ) { + $this->current_chunk = gzcompress( $this->current_chunk ); + $chunk_gzipped = '1'; + } + $data = array( 'action' => 'wpmdb_process_chunk', - 'chunk' => $this->current_chunk, - 'table' => $_POST['table'] + 'table' => $_POST['table'], + 'chunk_gzipped' => $chunk_gzipped, + 'chunk' => $this->current_chunk // NEEDS TO BE the last element in this array because of adding it back into the array in ajax_process_chunk() ); $data['sig'] = $this->create_signature( $data, $_POST['key'] ); $ajax_url = trailingslashit( $this->remote_url ) . 'wp-admin/admin-ajax.php'; - $this->remote_post( $ajax_url, $data, __FUNCTION__ ); + $response = $this->remote_post( $ajax_url, $data, __FUNCTION__ ); $this->display_errors(); + $response = trim( $response ); + if( ! empty( $response ) ) { + echo $response; + exit; + } - // reset our chunk values back to the default - $this->current_chunk_number = 0; - $this->current_chunk = ''; + echo json_encode( + array( + 'current_row' => $this->row_tracker, + 'primary_keys' => serialize( $this->primary_keys ) + ) + ); + exit; } /** @@ -1271,23 +2083,41 @@ function sql_addslashes( $a_string = '', $is_like = false ) { return str_replace( '\'', '\\\'', $a_string ); } + function network_admin_menu() { + $hook_suffix = add_submenu_page( 'settings.php', 'Migrate DB Pro', 'Migrate DB Pro', 'manage_network_options', 'wp-migrate-db-pro', array( $this, 'options_page' ) ); + $this->after_admin_menu( $hook_suffix ); + } + function admin_menu() { - if ( function_exists( 'add_management_page' ) ) { - $hook_suffix = add_management_page( 'Migrate DB Pro', 'Migrate DB Pro', 'update_core', 'wp-migrate-db-pro', array( $this, 'options_page' ) ); - } + $hook_suffix = add_management_page( 'Migrate DB Pro', 'Migrate DB Pro', 'export', 'wp-migrate-db-pro', array( $this, 'options_page' ) ); + $this->after_admin_menu( $hook_suffix ); + } + function after_admin_menu( $hook_suffix ) { + add_action( 'admin_head-' . $hook_suffix, array( $this, 'admin_head_connection_info' ) ); add_action( 'load-' . $hook_suffix , array( $this, 'load_assets' ) ); + + // Remove licence from the database if constant is set + if ( $this->is_licence_constant() && !empty( $this->settings['licence'] ) ) { + $this->settings['licence'] = ''; + $this->settings['licence_email'] = ''; + update_option( 'wpmdb_settings', $this->settings ); + } } function load_assets() { - if ( isset( $_GET['download'] ) && $_GET['download'] ) { + if ( ! empty( $_GET['download'] ) ) { $this->download_file(); } $src = plugins_url( 'asset/css/styles.css', dirname( __FILE__ ) ); - wp_enqueue_style( 'wp-migrate-db-pro-styles', $src ); + wp_enqueue_style( 'wp-migrate-db-pro-styles', $src, array(), $this->get_installed_version() ); $src = plugins_url( 'asset/js/script.js', dirname( __FILE__ ) ); - wp_enqueue_script( 'wp-migrate-db-pro-script', $src, array( 'jquery' ), false, true ); + wp_enqueue_script( 'wp-migrate-db-pro-script', $src, array( 'jquery' ), $this->get_installed_version(), true ); + + wp_enqueue_script('jquery'); + wp_enqueue_script('jquery-ui-core'); + wp_enqueue_script('jquery-ui-slider'); // PressTrends $this->presstrends(); @@ -1295,25 +2125,23 @@ function load_assets() { function download_file() { // dont need to check for user permissions as our 'add_management_page' already takes care of this - set_time_limit( 0 ); + $this->set_time_limit(); - if ( ! is_numeric( $_GET['download'] ) ){ - exit; - } - - $filename = sanitize_title_with_dashes( DB_NAME ) . '-migrate-' . $_GET['download'] . '.sql'; - $diskfile = $this->upload_dir . DS . $filename ; - - if ( isset( $_GET['gzip'] ) ) { - $diskfile .= '.gz'; - $filename .= '.gz'; + $dump_name = $this->format_dump_name( $_GET['download'] ); + if( isset( $_GET['gzip'] ) ) { + $dump_name .= '.gz'; } + $diskfile = $this->get_upload_info( 'path' ) . DS . $dump_name; + $filename = basename( $diskfile ); + $last_dash = strrpos( $filename, '-' ); + $salt = substr( $filename, $last_dash, 6 ); + $filename_no_salt = str_replace( $salt, '', $filename ); if ( file_exists( $diskfile ) ) { header( 'Content-Description: File Transfer' ); header( 'Content-Type: application/octet-stream' ); header( 'Content-Length: ' . filesize( $diskfile ) ); - header( 'Content-Disposition: attachment; filename=' . $filename ); + header( 'Content-Disposition: attachment; filename=' . $filename_no_salt ); $success = readfile( $diskfile ); unlink( $diskfile ); exit; @@ -1325,18 +2153,28 @@ function download_file() { function admin_head_connection_info() { global $table_prefix; + $plugin_info = get_plugin_data( $this->plugin_file_path, false, false ); ?> get_beta_version_data(); - if ( !isset( $latest['version'] ) || !isset( $latest['msg'] ) ) return false; - - $plugin = get_plugin_data( $this->plugin_file_path, false, false ); - - if ( !isset( $plugin['Version'] ) ) return false; - - if ( version_compare( $plugin['Version'], $latest['version'], '>=' ) ) { - return false; - } - - return $latest['msg']; - } - - function get_beta_version_data() { - $key = 'wpmdb_beta_notice'; - $info = get_site_transient( $key ); - if ( $info ) return $info; - - $url = 'http://cdn.deliciousbrains.com/beta/data.json'; - $data = wp_remote_get( $url, array( 'timeout' => 30 ) ); - - if ( !is_wp_error( $data ) && 200 == $data['response']['code'] ) { - if ( $info = json_decode( $data['body'], true ) ) { - set_site_transient( $key, $info, $this->transient_timeout ); - return $info; - } - } - - return false; - } - function get_installed_version() { if ( !is_admin() ) return false; // get_themes & get_plugins throw an error on the frontend @@ -1448,9 +2253,18 @@ function get_latest_version() { return $data['version']; } + function is_licence_constant() { + return defined( 'WPMDB_LICENCE' ); + } + + function get_licence_key() { + return $this->is_licence_constant() ? WPMDB_LICENCE : $this->settings['licence']; + } + function is_licence_expired( $skip_transient_check = false ) { - if( empty( $this->settings['licence'] ) ) { - $settings_link = sprintf( '%s', $this->plugin_base . '#settings', __( 'Settings', 'wp-migrate-db-pro' ) ); + $licence = $this->get_licence_key(); + if( empty( $licence ) ) { + $settings_link = sprintf( '%s', network_admin_url( $this->plugin_base ) . '#settings', __( 'Settings', 'wp-migrate-db-pro' ) ); $message = 'To finish activating WP Migrate DB Pro, please go to ' . $settings_link . ' and enter your licence key. If you don\'t have a licence key, you may purchase one.'; @@ -1462,7 +2276,7 @@ function is_licence_expired( $skip_transient_check = false ) { if ( false !== $trans ) return json_decode( $trans, true ); } - return json_decode( $this->check_licence( $this->settings['licence'] ), true ); + return json_decode( $this->check_licence( $licence ), true ); } /* @@ -1473,6 +2287,7 @@ function is_licence_expired( $skip_transient_check = false ) { * TODO: Implement "Check my license again" link */ function plugin_row() { + $licence = $this->get_licence_key(); $licence_response = $this->is_licence_expired(); $licence_problem = isset( $licence_response['errors'] ); @@ -1486,12 +2301,12 @@ function plugin_row() { $new_version .= sprintf( __( 'View version %s details', 'wp-migrate-db-pro' ), $latest_version ) . '.'; } - if ( !$new_version && !empty( $this->settings['licence'] ) ) { + if ( !$new_version && !empty( $licence ) ) { return; } - if( empty( $this->settings['licence'] ) ) { - $settings_link = sprintf( '%s', $this->plugin_base . '#settings', __( 'Settings', 'wp-migrate-db-pro' ) ); + if( empty( $licence ) ) { + $settings_link = sprintf( '%s', network_admin_url( $this->plugin_base ) . '#settings', __( 'Settings', 'wp-migrate-db-pro' ) ); if ( $new_version ) { $message = 'To update, '; } @@ -1612,9 +2427,10 @@ function site_transient_update_plugins( $trans ) { } function get_plugin_update_download_url() { + $licence = $this->get_licence_key(); $query_args = array( 'request' => 'download', - 'licence_key' => $this->settings['licence'], + 'licence_key' => $licence, 'site_url' => home_url( '', 'http') ); return add_query_arg( $query_args, $this->dbrains_api_url ); diff --git a/template/help.php b/template/help.php index cc12c59..64c9d5a 100644 --- a/template/help.php +++ b/template/help.php @@ -1,9 +1,31 @@ + array( + 'title' => 'Feature Walkthrough', + 'desc' => 'A brief walkthrough of the WP Migrate DB plugin + showing all of the different options and explaining them.' + ), + 'IFdHIpf6jjc' => array( + 'title' => 'Pulling Live Data Into Your Local Development Environment', + 'desc' => 'This screencast demonstrates how you can pull data from a remote, live + WordPress install and update the data in your local development + environment.' + ), + 'FjTzNqAlQE0' => array( + 'title' => 'Pushing Local Development Data to a Staging Environment', + 'desc' => 'This screencast demonstrates how you can push a local WordPress database + you\'ve been using for development to a staging environment.' + ) +); +$licence = $this->get_licence_key(); +?> +

    Email Support

    - settings['licence'] ) && ! empty( $this->settings['licence'] ) ) : ?> +

    Fetching licence details, please wait...

    We couldn't find your licence information. Please switch to the settings tab and enter your licence.

    @@ -12,26 +34,11 @@
    - array( - 'title' => 'Feature Walkthrough', - 'desc' => 'A brief walkthrough of the WP Migrate DB plugin - showing all of the different options and explaining them.' - ), - 'IFdHIpf6jjc' => array( - 'title' => 'Pulling Live Data Into Your Local Development Environment', - 'desc' => 'This screencast demonstrates how you can pull data from a remote, live - WordPress install and update the data in your local development - environment.' - ), - 'FjTzNqAlQE0' => array( - 'title' => 'Pushing Local Development Data to a Staging Environment', - 'desc' => 'This screencast demonstrates how you can push a local WordPress database - you\'ve been using for development to a staging environment.' - ) - ); - ?> +
    +

    Diagnostic Info & Error Log

    + + Clear Error Log +

    Videos

    @@ -53,10 +60,4 @@
    -
    -

    Diagnostic Info & Error Log

    - - Clear Error Log -
    -
    \ No newline at end of file diff --git a/template/migrate.php b/template/migrate.php index 43b415d..093fa90 100644 --- a/template/migrate.php +++ b/template/migrate.php @@ -17,7 +17,7 @@ var wpmdb_loaded_tables = ''; - +
    @@ -74,8 +74,16 @@

    +
    + + +
    + +
    +

    SSL Disabled — We couldn't connect over SSL but regular http (no SSL) appears to be working so we've switched to that. If you run a push or pull, your data will be transmitted unencrypted. Most people are fine with this, but just a heads up.

    +
    @@ -84,6 +92,13 @@

    Please enter the connection information above to continue.

    + +
    + plugin_file_path ); + ?> +

    Version Mismatch — We've detected you have version of WP Migrate DB Pro at but are using here. Please go to the Plugins page on both installs and check for updates.

    +
    @@ -112,7 +127,7 @@ - + @@ -125,7 +140,7 @@ - + @@ -136,6 +151,21 @@ + + + + + + + + + + + + + + + @@ -161,7 +191,7 @@
    - get_tables(); ?> + get_table_sizes(); ?>
    @@ -228,9 +259,9 @@ Replace GUIDs - + -
    +
    Although the WordPress Codex emphasizes that GUIDs should not be changed, this is limited to sites that are already live. If the site has never been live, I recommend replacing the GUIDs. For example, you may be @@ -253,7 +284,13 @@
  • +
  • +
  • +
  • @@ -291,6 +328,22 @@
    +
    +

    Whoa! We've detected that the database table prefix differs between installations. Clicking the Migrate DB button below will create new database tables in your local database with prefix "".

    + +

    However, your local install is configured to use table prefix "prefix; ?>" and will ignore the migrated tables. So, AFTER migration is complete, you will need to edit your local install's wp-config.php and change the "prefix; ?>" variable to "".

    + +

    This will allow your local install the use the migrated tables. Once you do this, you shouldn't have to do it again.

    +
    + +
    +

    Whoa! We've detected that the database table prefix differs between installations. Clicking the Migrate DB button below will create new database tables in the remote database with prefix "prefix; ?>".

    + +

    However, your remote install is configured to use table prefix "" and will ignore the migrated tables. So, AFTER migration is complete, you will need to edit your remote install's wp-config.php and change the "" variable to "prefix; ?>".

    + +

    This will allow your remote install the use the migrated tables. Once you do this, you shouldn't have to do it again.

    +
    +

    diff --git a/template/settings.php b/template/settings.php index eeef804..72c4211 100644 --- a/template/settings.php +++ b/template/settings.php @@ -4,14 +4,15 @@ $connection_info = sprintf( "%s\r%s", site_url( '', 'https' ), $this->settings['key'] ); $pull_checked = ( $this->settings['allow_pull'] ? ' checked="checked"' : '' ); $push_checked = ( $this->settings['allow_push'] ? ' checked="checked"' : '' ); + $verify_ssl_checked = ( $this->settings['verify_ssl'] ? ' checked="checked"' : '' ); $licence_email = ( isset( $this->settings['licence_email'] ) && ! empty( $this->settings['licence_email'] ) ? 'Registered To: ' . $this->settings['licence_email'] : '' ); - $licence = ( isset( $this->settings['licence'] ) && ! empty( $this->settings['licence'] ) ? $this->settings['licence'] : '' ); + $licence = $this->get_licence_key(); ?> -

    +
    • +
    • + + +
      + We disable SSL verification by default because a lot of people's environments are not setup for it to work. For example, with XAMPP, you have to manually enable OpenSSL by editing the php.ini. Without SSL verification, an HTTPS connection is vulnerable to a man-in-the-middle attack, so we do recommend you configure your environment and enable this. +
      +
    @@ -32,14 +43,34 @@
    +
    +
    +
    Maximum Request Size + +
    + We've detected that your server supports requests up to get_bottleneck( 'max' ) ); ?>, but it's possible that your server has limitations that we could not detect. To be on the safe side, we set the default to 1 MB, but you can try throttling it up to get better performance. If you're getting a 413 error or having trouble with time outs, try throttling this setting down. +
    +
    +
    + Saved +
    +
    +
    +

    Your License

    + is_licence_constant() ) : ?> +

    + +

    +

    +
    \ No newline at end of file diff --git a/wp-migrate-db-pro.php b/wp-migrate-db-pro.php index 18654ea..4b2c252 100644 --- a/wp-migrate-db-pro.php +++ b/wp-migrate-db-pro.php @@ -4,7 +4,7 @@ Plugin URI: http://deliciousbrains.com/wp-migrate-db-pro/ Description: Export, push, and pull to migrate your WordPress databases. Author: Delicious Brains -Version: 1.0 +Version: 1.2 Author URI: http://deliciousbrains.com */ @@ -47,4 +47,4 @@ function wp_migrate_db_pro_init() { $wpmdbpro = new WP_Migrate_DB_Pro( __FILE__ ); } -add_action( 'init', 'wp_migrate_db_pro_init' ); \ No newline at end of file +add_action( 'init', 'wp_migrate_db_pro_init' ); From 1702ebbb564c945134310bf5e3dc9c8778f16405 Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Sun, 29 Dec 2013 11:50:31 -0600 Subject: [PATCH 03/52] another big update --- asset/css/styles.css | 413 ++++++- asset/img/icon-media-files.svg | 13 + asset/js/common.js | 42 + asset/js/hook.js | 63 + asset/js/plugin-update.js | 2 +- asset/js/script.js | 473 +++++--- asset/sass/_mp6.scss | 344 ++++++ asset/sass/styles.scss | 194 ++- class/wpmdbpro-addon.php | 50 + class/wpmdbpro-base.php | 573 +++++++++ class/{wp-migrate-db.php => wpmdbpro.php} | 1314 ++++++++++----------- template/addons.php | 18 + template/migrate.php | 149 ++- template/settings.php | 20 +- wp-migrate-db-pro.php | 32 +- 15 files changed, 2668 insertions(+), 1032 deletions(-) create mode 100644 asset/img/icon-media-files.svg create mode 100644 asset/js/common.js create mode 100644 asset/js/hook.js create mode 100644 asset/sass/_mp6.scss create mode 100644 class/wpmdbpro-addon.php create mode 100644 class/wpmdbpro-base.php rename class/{wp-migrate-db.php => wpmdbpro.php} (69%) create mode 100644 template/addons.php diff --git a/asset/css/styles.css b/asset/css/styles.css index be1b9c5..078b76f 100644 --- a/asset/css/styles.css +++ b/asset/css/styles.css @@ -1,3 +1,11 @@ +#wpmdb-main { + width: 742px; +} + +#overlay { + background-color: rgba(255, 255, 255, 0.9); +} + .wpmdb { /* ============================================================================= Common & Global @@ -21,9 +29,16 @@ /* ============================================================================= Help Tab ========================================================================== */ + /* ============================================================================= + Addons Tab + ========================================================================== */ } -.wpmdb > .warning { - max-width: 750px; +.wpmdb > div.updated.warning { + max-width: 742px; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + margin: 10px 0; } .wpmdb a { text-decoration: none; @@ -45,6 +60,10 @@ .wpmdb input[type=password] { padding: 5px; } +.wpmdb label.disabled { + color: #888; + cursor: default; +} .wpmdb .option-section { border-bottom: 1px solid #ccc; padding-bottom: 20px; @@ -69,7 +88,7 @@ display: none; } .wpmdb .indent-wrap { - margin-left: 25px; + margin-left: 24px; } .wpmdb .expandable-content { display: none; @@ -115,7 +134,7 @@ .wpmdb .licence-input { clear: both; display: block; - font-family: "Courier New",Courier,monospace; + font-family: Consolas, Monaco, monospace; font-size: 14px; margin-bottom: 7px; padding: 10px; @@ -123,6 +142,7 @@ } .wpmdb .register-licence { float: left; + outline: none; } .wpmdb .licence-status { color: #A21B1B; @@ -134,9 +154,6 @@ .wpmdb .licence-status.success { color: #333; } -.wpmdb .licence-information { - margin-bottom: 5px; -} .wpmdb .register-licence-ajax-spinner { margin: 4px 0 0 8px; } @@ -150,7 +167,7 @@ .wpmdb h2.nav-tab-wrapper { margin-top: 10px; margin-bottom: 20px; - padding-left: 10px; + padding-left: 5px; } .wpmdb h2.nav-tab-wrapper a { margin-right: 4px; @@ -163,10 +180,6 @@ display: inline-block; clear: both; } -.wpmdb .saved-migration-profile-label { - font-weight: bold; - font-size: 14px; -} .wpmdb .migration-profile-options li { position: relative; width: 520px; @@ -222,10 +235,15 @@ color: #999; font-style: italic; } -.wpmdb .option-heading { +.wpmdb .option-heading, .wpmdb .checkbox-label { font-size: 14px; font-weight: bold; } +.wpmdb .checkbox-label input[type=checkbox] { + margin-right: 7px; + position: relative; + top: -1px; +} .wpmdb .expand-collapse-arrow { margin-right: 9px; } @@ -237,7 +255,7 @@ width: 418px; height: 65px; color: #333; - font-family: "Courier New",Courier,monospace; + font-family: Consolas, Monaco, monospace; font-size: 15px; line-height: 21px; padding: 10px; @@ -263,7 +281,7 @@ .wpmdb .temp-disabled { background-color: #EEEEEE; color: #888888; - font-family: "Courier New",Courier,monospace; + font-family: Consolas, Monaco, monospace; text-shadow: 0 1px 0 #FFFFFF; } .wpmdb .push-list ul { @@ -371,11 +389,11 @@ .wpmdb .select-deselect-divider { margin: 0 6px; } -.wpmdb .select-tables-wrap { +.wpmdb .select-wrap { display: none; margin-top: 12px; } -.wpmdb #select-tables { +.wpmdb .multiselect { min-width: 420px; min-height: 180px; margin-bottom: 10px; @@ -423,13 +441,18 @@ display: none; box-shadow: 0px 0px 5px #ccc; } -.wpmdb .ssl-verify-message { - left: 182px; - top: -10px; +.wpmdb .inline-message { + padding: 10px; + border-radius: 3px; + margin-top: 5px; } -.wpmdb .replace-guids-info { - left: 140px; - top: -10px; +.wpmdb .inline-message.error { + border: 1px solid #CC0000; + background-color: #FFEBE8; +} +.wpmdb .inline-message.warning { + background-color: #FFFFE0; + border: 1px solid #E6DB55; } .wpmdb .helper-message:after { content: ''; @@ -458,40 +481,32 @@ .wpmdb .label-disabled { color: #888; } -.wpmdb .prefix-notice, .wpmdb .ssl-notice, .wpmdb .different-plugin-version-notice, .wpmdb .mysqli-notice { +.wpmdb .prefix-notice, .wpmdb .ssl-notice, .wpmdb .different-plugin-version-notice, .wpmdb .directory-permission-notice { background-color: #FFFFE0; border: 1px solid #E6DB55; padding: 15px; border-radius: 3px; margin-bottom: 15px; display: none; - width: 710px; } -.wpmdb .prefix-notice p, .wpmdb .ssl-notice p, .wpmdb .different-plugin-version-notice p, .wpmdb .mysqli-notice p { +.wpmdb .prefix-notice p, .wpmdb .ssl-notice p, .wpmdb .different-plugin-version-notice p, .wpmdb .directory-permission-notice p { margin-top: 0px; } -.wpmdb .prefix-notice p:last-child, .wpmdb .ssl-notice p:last-child, .wpmdb .different-plugin-version-notice p:last-child, .wpmdb .mysqli-notice p:last-child { +.wpmdb .prefix-notice p:last-child, .wpmdb .ssl-notice p:last-child, .wpmdb .different-plugin-version-notice p:last-child, .wpmdb .directory-permission-notice p:last-child { margin: 0px; } -.wpmdb .different-plugin-version-notice, .wpmdb .mysqli-notice { +.wpmdb .different-plugin-version-notice, .wpmdb .directory-permission-notice { background-color: #FFEBE8; border-color: #CC0000; } -.wpmdb .different-plugin-version-notice a, .wpmdb .mysqli-notice a { +.wpmdb .different-plugin-version-notice a, .wpmdb .directory-permission-notice a { color: #CC0000; text-decoration: underline; } -.wpmdb .mysqli-notice { - display: block; -} .wpmdb .ssl-notice { margin-bottom: 0; margin-top: 15px; } -.wpmdb .save-migration-profile { - font-size: 14px; - font-weight: bold; -} .wpmdb .save-migration-profile-wrap li label { font-size: 12px; font-weight: normal; @@ -573,10 +588,6 @@ text-align: right; float: left; } -.wpmdb .settings-tab .slider-message { - top: -11px; - left: 164px; -} .wpmdb .settings-tab .slider-spinner { position: absolute; right: -35px; @@ -652,11 +663,9 @@ } .wpmdb .connection-info { clear: both; - background-color: #eee; - color: #888; font-size: 15px; line-height: 21px; - font-family: "Courier New", Courier, monospace; + font-family: Consolas, Monaco, monospace; padding: 10px 10px; height: 67px; text-shadow: 0px 1px 0px #fff; @@ -674,6 +683,14 @@ float: left; margin: 4px 7px; } +.wpmdb .masked-licence { + margin-top: 0px; +} +.wpmdb .bull { + font-size: 22px; + position: relative; + top: 4px; +} .wpmdb .help-tab { display: none; } @@ -772,7 +789,7 @@ .wpmdb .help-tab .debug textarea { width: 100%; min-height: 200px; - font-family: "Courier New",Courier,monospace; + font-family: Consolas, Monaco, monospace; margin-bottom: 5px; } .wpmdb .help-tab h4 { @@ -784,6 +801,63 @@ .wpmdb .help-tab iframe { display: none; } +.wpmdb .addons-tab { + display: none; +} +.wpmdb .addons-tab .addon { + position: relative; + width: 100%; + min-height: 138px; + padding: 25px 30px 30px 165px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + color: #fff; +} +.wpmdb .addons-tab .addon .actions { + float: right; + font-size: 14px; +} +.wpmdb .addons-tab .addon .actions > * { + margin-right: 10px; +} +.wpmdb .addons-tab .addon .actions *:last-child { + margin-right: 0; +} +.wpmdb .addons-tab .addon .actions .action { + background-color: #fff; + font-weight: bold; + display: inline-block; + padding: 0.2em 0.4em; +} +.wpmdb .addons-tab .addon .actions .action:hover { + background-color: rgba(255, 255, 255, 0.92); +} +.wpmdb .addons-tab .addon .actions .status { + border-bottom: 2px solid #fff; + padding-bottom: 0.1em; +} +.wpmdb .addons-tab .addon h1 { + font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", sans-serif; + font-weight: normal; + float: left; + margin: 0; + margin-top: 5px; +} +.wpmdb .addons-tab .addon p { + font-size: 16px; + line-height: 1.2em; + clear: both; + padding-top: 15px; + margin: 0; +} +.wpmdb .addons-tab .addon.wp-migrate-db-pro-media-files { + background: #3fab3f url(../img/icon-media-files.svg) no-repeat 30px 30px; + background-size: 110px 85px; +} +.wpmdb .addons-tab .addon.wp-migrate-db-pro-media-files .action { + color: #3fab3f; +} /* Progress Information */ /* Contain floats: h5bp.com/q */ @@ -857,6 +931,7 @@ .progress-content .progress-text { clear: left; float: left; + width: 100%; } .progress-content .timer { float: right; @@ -907,7 +982,7 @@ position: relative; text-align: center; } -.progress-content .progress-chunk span { +.progress-content .progress-chunk > span { padding: 0px 3px; white-space: nowrap; text-overflow: ellipsis; @@ -919,7 +994,7 @@ border: 1px solid #ccc; border-radius: 3px; background-color: #fff; - font-family: "Courier New",Courier,monospace; + font-family: Consolas, Monaco, monospace; font-size: 12px; display: inline-block; top: -35px; @@ -981,3 +1056,249 @@ color: #666; border-color: #aaa; } + +body.mp6 input[type=checkbox]:disabled { + opacity: 1; + border-color: #ccc; +} +body.mp6 #wpmdb-main { + margin-top: 15px; + font-size: 14px; +} +body.mp6 p { + font-size: 14px; +} +body.mp6 .wrap h2 { + float: left; +} +body.mp6 .wpmdb input[type=checkbox], +body.mp6 .wpmdb input[type=radio] { + vertical-align: middle; + margin-top: -4px; +} +body.mp6 .wpmdb input[type=text], +body.mp6 .wpmdb input[type=password] { + padding: 3px 5px; +} +body.mp6 .wpmdb input.code { + padding-top: 6px; +} +body.mp6 .wpmdb label { + font-size: 14px; +} +body.mp6 .wpmdb h2.nav-tab-wrapper { + float: none; + margin-bottom: 0; + width: 722px; +} +body.mp6 .wpmdb .help-tab h3 { + margin-top: 0; +} +body.mp6 .wpmdb .temp-disabled { + background-color: #f9f9f9; +} +body.mp6 .wpmdb .migration-profile-options li a { + border-color: #ccc; + color: #555; + background-color: #e4e4e4; +} +body.mp6 .wpmdb .migration-profile-options li a:hover { + background-color: #fff; + color: #464646; +} +body.mp6 .wpmdb .settings-tab .slider-label span { + vertical-align: middle; +} +body.mp6 .wpmdb .settings-tab .slider-label-wrapper { + font-size: 14px; +} +body.mp6 .wpmdb .settings-tab .ui-slider { + border-color: #ccc; + background-color: #fff; +} +body.mp6 .wpmdb .settings-tab .ui-slider-range { + background-color: #d8fcd1; +} +body.mp6 .wpmdb .settings-tab .option-section li label { + font-size: 14px; +} +body.mp6 .wpmdb .connection-info, +body.mp6 .wpmdb .migrate-tab .pull-push-connection-info { + font-weight: bold; + font-size: 14px; +} +body.mp6 .wpmdb .general-helper { + border: 0; + width: auto; + height: auto; + top: auto; + margin: 0; +} +body.mp6 .wpmdb .general-helper:after { + content: "\f223"; + display: inline-block; + -webkit-font-smoothing: antialiased; + font: normal 22px/1 'dashicons'; + vertical-align: top; + top: auto; + left: auto; + position: relative; +} +body.mp6 .wpmdb .helper-message { + font-size: 14px; + line-height: 1.4em; +} +body.mp6 .wpmdb .right-arrow { + display: none; +} +body.mp6 .wpmdb .arrow-col { + width: 75px; +} +body.mp6 .wpmdb .arrow-col:after { + content: "\f344"; + display: inline-block; + -webkit-font-smoothing: antialiased; + font: normal 22px/1 'dashicons'; + vertical-align: top; + color: #999; +} +body.mp6 .wpmdb .find-heading { + width: 388px; +} +body.mp6 .wpmdb .replace-fields input { + width: 304px; +} +body.mp6 .wpmdb .replace-right-col span { + border-color: #999; +} +body.mp6 .wpmdb .replace-right-col span:hover { + border-color: #666; +} +body.mp6 .wpmdb .replace-remove-row:after, body.mp6 .wpmdb .replace-remove-row:before, body.mp6 .wpmdb .replace-add-row:after, body.mp6 .wpmdb .replace-add-row:before { + background-color: #999; +} +body.mp6 .wpmdb .replace-remove-row:hover:after, body.mp6 .wpmdb .replace-remove-row:hover:before, body.mp6 .wpmdb .replace-add-row:hover:after, body.mp6 .wpmdb .replace-add-row:hover:before { + background-color: #666; +} +body.mp6 .wpmdb .option-group.migrate-selection > li > label { + font-size: 16px; +} +body.mp6 .wpmdb .saved-migration-profile-label { + font-size: 16px; +} +body.mp6 .wpmdb .option-heading, body.mp6 .wpmdb .checkbox-label { + font-size: 16px; +} +body.mp6 .wpmdb .checkbox-label input[type=checkbox] { + top: auto; +} +body.mp6 .wpmdb .return-to-profile-selection { + font-size: 14px; +} +body.mp6 .wpmdb .option-description { + font-size: 13px; +} +body.mp6 .wpmdb .save-migration-profile-wrap li { + position: relative; +} +body.mp6 .wpmdb .delete-profile { + border: 0; + border-radius: 0; + height: auto; + width: auto; + left: 0; + top: 50%; + margin-left: 0; +} +body.mp6 .wpmdb .delete-profile:after { + content: "\f153"; + display: inline-block; + -webkit-font-smoothing: antialiased; + font: normal 18px/1 'dashicons'; + vertical-align: middle; + color: #999; +} +body.mp6 .wpmdb .delete-profile:hover:after { + color: #666; +} +body.mp6 .wpmdb .addons-tab .addon h1 { + font-family: 'Open Sans', sans-serif; + font-weight: 200; + font-size: 24px; + margin-top: 2px; +} +body.mp6 .wpmdb .addons-tab .addon p { + font-size: 14px; + line-height: 1.4em; +} +body.mp6 .wpmdb .help-tab .support p, body.mp6 .wpmdb .help-tab .support .email a { + font-size: 14px; +} +body.mp6 .wpmdb .help-tab .videos h4, body.mp6 .wpmdb .help-tab .videos p { + font-size: 14px; +} +body.mp6 .wpmdb .inline-message, body.mp6 .wpmdb .notification-message { + border-radius: 0; + border: 0; + box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1); + padding: 10px 14px; + font-size: 13px; +} +body.mp6 .wpmdb .notification-message { + margin-bottom: 20px; + background-color: #fff; +} +body.mp6 .wpmdb .notification-message p { + font-size: 13px; + margin-top: 0; +} +body.mp6 .wpmdb .notification-message p:last-child { + margin: 0; +} +body.mp6 .wpmdb .notification-message h4 { + margin-top: 0; +} +body.mp6 .wpmdb .notification-message a { + color: #0074a2; + text-decoration: none; +} +body.mp6 .wpmdb .notification-message a:hover { + color: #2ea2cc; +} +body.mp6 .wpmdb .inline-message.error, body.mp6 .wpmdb .notification-message.error-notice { + border-left: 4px solid #dd3d36; + background-color: #fff; +} +body.mp6 .wpmdb .inline-message.warning, body.mp6 .wpmdb .notification-message.warning-notice { + background-color: #fff; + border-left: 4px solid #ffba00; +} +body.mp6 .wpmdb .inline-message.success, body.mp6 .wpmdb .notication-message.success-notice { + border-left: 4px solid #7ad03a; +} +body.mp6 .wpmdb .ssl-notice { + margin-bottom: 0; +} +body.mp6 .wpmdb .different-plugin-version-notice, body.mp6 .wpmdb .directory-permission-notice { + margin-bottom: 10px; +} +body.mp6 .progress-content { + font-size: 14px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); + background-color: #eee; +} +body.mp6 .progress-content .progress-title { + font-family: 'Open Sans', sans-serif; + font-weight: normal; + font-size: 22px; +} +body.mp6 .progress-content .progress-bar { + background-image: none; + background-color: #0074a2; +} +body.mp6 #overlay { + background-color: rgba(0, 0, 0, 0.5); +} +body.mp6 .migration-progress-ajax-spinner { + top: 20px; +} diff --git a/asset/img/icon-media-files.svg b/asset/img/icon-media-files.svg new file mode 100644 index 0000000..80a6ca2 --- /dev/null +++ b/asset/img/icon-media-files.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/asset/js/common.js b/asset/js/common.js new file mode 100644 index 0000000..abbdbb5 --- /dev/null +++ b/asset/js/common.js @@ -0,0 +1,42 @@ +// global vars +var hooks = []; +var call_stack = []; +var non_fatal_errors = ''; +var migration_error = false; + +function wpmdb_call_next_hook() { + if( ! call_stack.length ) { + call_stack = hooks; + } + + var func = call_stack[0]; + call_stack.shift(); + window[func](); // Uses the string from the array to call the function of the same name +} + +function wpmdb_add_commas( number_string ) { + number_string += ''; + x = number_string.split('.'); + x1 = x[0]; + x2 = x.length > 1 ? '.' + x[1] : ''; + var rgx = /(\d+)(\d{3})/; + while (rgx.test(x1)) { + x1 = x1.replace(rgx, '$1' + ',' + '$2'); + } + return x1 + x2; +} + +function wpmdb_parse_json( maybe_json ) { + try { + var json_object = jQuery.parseJSON( maybe_json ); + } + catch(e){ + // we simply return false here because the json data itself will never just contain a value of "false" + return false; + } + return json_object; +} + +(function($) { + // jQuery code here +})(jQuery); \ No newline at end of file diff --git a/asset/js/hook.js b/asset/js/hook.js new file mode 100644 index 0000000..5b5a073 --- /dev/null +++ b/asset/js/hook.js @@ -0,0 +1,63 @@ +(function($) { + + $.wpmdb = { + /** + * Implement a WordPress-link Hook System for Javascript + * TODO: Change 'tag' to 'args', allow number (priority), string (tag), object (priority+tag) + */ + hooks: { action: {}, filter: {} }, + add_action: function( action, callable, tag ) { + jQuery.wpmdb.add_hook( 'action', action, callable, tag ); + }, + add_filter: function( action, callable, tag ) { + jQuery.wpmdb.add_hook( 'filter', action, callable, tag ); + }, + do_action: function( action, args ) { + jQuery.wpmdb.do_hook( 'action', action, null, args ); + }, + apply_filters: function( action, value, args ) { + return jQuery.wpmdb.do_hook( 'filter', action, value, args ); + }, + remove_action: function( action, tag ) { + jQuery.wpmdb.remove_hook( 'action', action, tag ); + }, + remove_filter: function( action, tag ) { + jQuery.wpmdb.remove_hook( 'filter', action, tag ); + }, + add_hook: function( hook_type, action, callable, tag ) { + if ( undefined == jQuery.wpmdb.hooks[hook_type][action] ) { + jQuery.wpmdb.hooks[hook_type][action] = []; + } + var hooks = jQuery.wpmdb.hooks[hook_type][action]; + if ( undefined == tag ) { + tag = action + '_' + hooks.length; + } + jQuery.wpmdb.hooks[hook_type][action].push( { tag:tag, callable:callable } ); + }, + do_hook: function( hook_type, action, value, args ) { + if ( undefined != jQuery.wpmdb.hooks[hook_type][action] ) { + var hooks = jQuery.wpmdb.hooks[hook_type][action]; + for( var i=0; i=0; i--) { + if (undefined==tag||tag==hooks[i].tag) + hooks.splice(i,1); + } + } + } + } + +})(jQuery); \ No newline at end of file diff --git a/asset/js/plugin-update.js b/asset/js/plugin-update.js index f0e60b8..6ae5cd7 100644 --- a/asset/js/plugin-update.js +++ b/asset/js/plugin-update.js @@ -21,7 +21,7 @@ doing_check_licence = true; - $('.check-my-licence-again').after( '' ); + $(this).after( '' ); var check_again_link = ' Check my license again'; diff --git a/asset/js/script.js b/asset/js/script.js index fec119d..6dde3df 100644 --- a/asset/js/script.js +++ b/asset/js/script.js @@ -1,21 +1,32 @@ +// global functions +var migration_complete; +var migration_complete_events; + (function($) { var connection_established = false; - var connection_data = ''; var last_replace_switch = ''; var doing_ajax = false; var doing_licence_registration_ajax = false; var doing_reset_api_key_ajax = false; var doing_save_profile = false; - var form_data = ''; - var migration_completed = false; - var interval; - var currently_migrating = false; var profile_name_edited = false; var checked_licence = false; var show_prefix_notice = false; var show_ssl_notice = false; var show_version_notice = false; + var migration_completed = false; + var currently_migrating = false; + var dump_filename = ''; + var migration_intent; + var remote_site; + var secret_key; + var form_data; + var stage; + var connection_data; + var elapsed_interval; + var completed_msg; + var tables_to_migrate = ''; var admin_url = ajaxurl.replace( '/admin-ajax.php', '' ), spinner_url = admin_url + '/images/wpspin_light'; @@ -50,28 +61,6 @@ return typeof n === 'number' && n % 1 == 0; } - function is_json( maybe_json ) { - try { - var json_object = jQuery.parseJSON( maybe_json ); - } - catch(e){ - return false; - } - return true; - } - - function add_commas( number_string ) { - number_string += ''; - x = number_string.split('.'); - x1 = x[0]; - x2 = x.length > 1 ? '.' + x[1] : ''; - var rgx = /(\d+)(\d{3})/; - while (rgx.test(x1)) { - x1 = x1.replace(rgx, '$1' + ',' + '$2'); - } - return x1 + x2; - } - function setup_counter() { var c = 0, counter_display = $('.timer'), @@ -89,7 +78,7 @@ display_count(); } - interval = setInterval(count,1000); + elapsed_interval = setInterval(count,1000); } function get_intersect(arr1, arr2) { @@ -107,6 +96,13 @@ return r; } + function get_query_var( name ){ + name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]"); + var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"), + results = regex.exec(location.search); + return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); + } + function maybe_show_ssl_warning( url, key, remote_scheme ) { var scheme = url.substr(0, url.indexOf(':')); if( remote_scheme != scheme ) { @@ -162,6 +158,7 @@ } $(document).ready(function() { + if( navigator.appName.indexOf('Internet Explorer') != -1 ) { $('.ie-warning').show(); } @@ -173,7 +170,7 @@ max: wpmdb_bottleneck / 1024, step: 512, slide: function( event, ui ) { - $('.amount').html( add_commas( ui.value ) + ' kB' ); + $('.amount').html( wpmdb_add_commas( ui.value ) + ' kB' ); }, change: function( event, ui ) { $('.amount').after( '' ); @@ -203,7 +200,7 @@ }); } }); - $('.amount').html( add_commas( $('.slider').slider('value') ) + ' kB' ); + $('.amount').html( wpmdb_add_commas( $('.slider').slider('value') ) + ' kB' ); var progress_content_original = $('.progress-content').clone(); $('.progress-content').remove(); @@ -212,6 +209,8 @@ var this_prefixed_tables = $.parseJSON(wpmdb_this_prefixed_tables); var push_select = $('#select-tables').clone(); var pull_select = $('#select-tables').clone(); + var push_post_type_select = $('#select-post-types').clone(); + var pull_post_type_select = $('#select-post-types').clone(); $('.help-tab .video').each(function() { var $container = $(this), @@ -253,9 +252,11 @@ msg += data.errors[key]; } $('.support-content').empty().html( msg ); + $('.addons-content').empty().html( msg ); } else { $('.support-content').empty().html(data.message); + $('.addons-content').empty().html(data.addon_content); } } }); @@ -285,13 +286,13 @@ dataType: 'json', cache: false, data: { - action: 'wpmdb_prepare_remote_connection', + action: 'wpmdb_verify_connection_to_remote_site', url: connection_info[0], key: connection_info[1], intent: intent, }, error: function(jqXHR, textStatus, errorThrown){ - $('.connection-status').html( 'A problem occurred when attempting to connect to the remote server, please check the details and try again. (#102)' ); + $('.connection-status').html( 'A problem occurred when attempting to connect to the local server, please check the details and try again. (#102)' ); $('.connection-status').addClass( 'migration-error' ); $('.ajax-spinner').remove(); doing_ajax = false; @@ -331,7 +332,7 @@ } var table_select = document.createElement('select'); - $(table_select).attr('multiple', 'multiple').attr('name','select-tables[]').attr('id','select-tables'); + $(table_select).attr('multiple', 'multiple').attr('name','select_tables[]').attr('id','select-tables').attr('class','multiselect'); $.each(connection_data.tables, function(index, value) { var selected = $.inArray( value, loaded_tables ); @@ -341,17 +342,42 @@ else{ selected = ' '; } - $(table_select).append('' + value + ''); + $(table_select).append('' + value + ' (' + connection_data.table_sizes_hr[value] + ')'); }); pull_select = table_select; + var loaded_post_prefixes = ''; + if( wpmdb_default_profile == false && wpmdb_migrate_all_post_types == false ){ + loaded_post_prefixes = $.parseJSON( wpmdb_loaded_post_types ); + } + + var post_type_select = document.createElement('select'); + $(post_type_select).attr('multiple', 'multiple').attr('name','select_post_types[]').attr('id','select-post-types').attr('class','multiselect'); + + $.each(connection_data.post_types, function(index, value) { + var selected = $.inArray( value, loaded_post_prefixes ); + if( selected != -1 || ( wpmdb_convert_exclude_revisions == true && value != 'revision' ) ){ + selected = ' selected="selected" '; + } + else{ + selected = ' '; + } + $(post_type_select).append('' + value + ''); + }); + + pull_post_type_select = post_type_select; + if( $('#pull').is(':checked') ){ $('#select-tables').remove(); $('.select-tables-wrap').prepend(pull_select); + $('#select-post-types').remove(); + $('.select-post-types-wrap').prepend(pull_post_type_select); $('.table-prefix').html(data.prefix); $('.uploads-dir').html(wpmdb_this_uploads_dir); } + + $.wpmdb.do_action( 'verify_connection_to_remote_site', connection_data ); } @@ -360,7 +386,7 @@ } // add to tags which act as JS event buttons, will not jump page to top and will deselect the button - $('.js-action-link').click(function(){ + $('.js-action-link').click(function(event){ $(this).blur(); return false; }); @@ -408,8 +434,9 @@ $('.licence-status').html( msg ); } else { - $('.licence-information').html('Registered To: ' + data.email); - $('.licence-status').html( 'Your licence has been activated. You will now receive automatic updates and access to email support.'); + $('.licence-input, .register-licence').remove(); + $('.licence-not-entered').prepend( data.masked_licence ); + $('.licence-status').html( 'Your licence has been activated. You will now receive automatic updates and access to email support.').delay(5000).fadeOut(1000); $('.licence-status').addClass('success'); $('.support-content').empty().html('

    Fetching licence details, please wait...

    '); check_licence( licence_key ); @@ -432,7 +459,7 @@ action : 'wpmdb_clear_log', }, error: function(jqXHR, textStatus, errorThrown){ - alert('An error occurred when trying to clear the debug log. You can clear it manually by accessing the file system. (#132)'); + alert('An error occurred when trying to clear the debug log. Please contact support. (#132)'); }, success: function(data){ } @@ -459,21 +486,24 @@ } // select all tables - $('.tables-select-all').click(function(){ - $('#select-tables').focus(); - $('#select-tables option').attr('selected',1); + $('.multiselect-select-all').click(function(){ + var multiselect = $(this).parents('.select-wrap').children('.multiselect'); + $(multiselect).focus(); + $('option', multiselect).attr('selected',1); }); // deselect all tables - $('.tables-deselect-all').click(function(){ - $('#select-tables').focus(); - $('#select-tables option').removeAttr('selected'); + $('.multiselect-deselect-all').click(function(){ + var multiselect = $(this).parents('.select-wrap').children('.multiselect'); + $(multiselect).focus(); + $('option', multiselect).removeAttr('selected'); }); // invert table selection - $('.tables-invert-selection').click(function(){ - $('#select-tables').focus(); - $('#select-tables option').each(function(){ + $('.multiselect-invert-selection').click(function(){ + var multiselect = $(this).parents('.select-wrap').children('.multiselect'); + $(multiselect).focus(); + $('option', multiselect).each(function(){ $(this).attr('selected', ! $(this).attr('selected')); }); }); @@ -507,27 +537,39 @@ $(this).next().hide(); } }); + + $('.checkbox-label input[type=checkbox]').change(function() { + if( $(this).is(':checked') ){ + $(this).parent().next().show(); + } + else { + $(this).parent().next().hide(); + } + }); // special expand and collapse content on click for save migration profile $('#save-migration-profile').change(function() { if( $(this).is(':checked') ){ - $(this).parent().next().show(); $('.save-settings-button').show(); $('.migrate-db .button-primary').val('Migrate DB & Save'); } else{ - $(this).parent().next().hide(); $('.save-settings-button').hide(); $('.migrate-db .button-primary').val('Migrate DB'); } }); if( $('#save-migration-profile').is(':checked') ){ - $('#save-migration-profile').parent().next().show(); $('.save-settings-button').show(); $('.migrate-db .button-primary').val('Migrate DB & Save'); }; + $('.checkbox-label input[type=checkbox]').each(function(){ + if( $(this).is(':checked') ){ + $(this).parent().next().show(); + } + }); + // AJAX migrate button $('.migrate-db-button').click(function(event){ $(this).blur(); @@ -592,16 +634,15 @@ 'position': 'fixed', 'top': 0, 'left': 0, - 'background-color': 'rgba(255,255,255,0.9)', 'width': '100%', 'z-index': 99999, 'display': 'none', }); $progress_content = progress_content_original.clone(); - var migration_intent = $('input[name=action]:checked').val(); + migration_intent = $('input[name=action]:checked').val(); - var stage = 'backup'; + stage = 'backup'; if( migration_intent == 'savefile' ){ stage = 'migrate'; @@ -613,16 +654,16 @@ var table_intent = $('input[name=table_migrate_option]:checked').val(); var connection_info = $.trim( $('.pull-push-connection-info').val() ).split("\n"); - var remote_site = connection_info[0]; - var secret_key = connection_info[1]; - var tables_to_migrate = ''; var table_rows = ''; + remote_site = connection_info[0]; + secret_key = connection_info[1]; + var static_migration_label = ''; $('#overlay').after($progress_content); - var completed_msg = 'Exporting complete.'; + completed_msg = 'Exporting complete.'; if( migration_intent == 'savefile' ){ static_migration_label = 'Exporting, please wait...'; @@ -769,9 +810,8 @@ } var dump_url = data.dump_url; - var dump_filename = data.dump_filename; + dump_filename = data.dump_filename; - var table_migration_error = false; var i = 0; var progress_size = 0; var overall_percent = 0; @@ -818,7 +858,10 @@ } else { - migration_complete(); + hooks.push( 'migration_complete' ); + hooks = $.wpmdb.apply_filters( 'wpmdb_migration_complete_hooks', hooks ); + hooks.push( 'migration_complete_events' ); + wpmdb_call_next_hook(); return; } } @@ -836,9 +879,33 @@ } gzip = 0; - if( parseInt( connection_data.gzip ) == 1 ) { + if( migration_intent != 'savefile' && parseInt( connection_data.gzip ) == 1 ) { gzip = 1; } + + var request_data = { + action : 'wpmdb_migrate_table', + intent : migration_intent, + url : remote_site, + key : secret_key, + table : tables_to_migrate[i], + form_data : form_data, + stage : stage, + current_row : current_row, + dump_filename : dump_filename, + last_table : last_table, + primary_keys : primary_keys, + gzip : gzip, + }; + + if( migration_intent != 'savefile' ) { + request_data.bottleneck = connection_data.bottleneck; + request_data.prefix = connection_data.prefix; + } + + if( connection_data && connection_data.path_current_site ) { + request_data.path_current_site = connection_data.path_current_site; + } $.ajax({ url: ajaxurl, @@ -846,22 +913,7 @@ dataType: 'text', cache: false, timeout: 0, - data: { - action : 'wpmdb_prepare_table_migration', - intent : migration_intent, - url : remote_site, - key : secret_key, - table : tables_to_migrate[i], - form_data : form_data, - stage : stage, - bottleneck : connection_data.bottleneck, - prefix : connection_data.prefix, - current_row : current_row, - dump_filename : dump_filename, - last_table : last_table, - primary_keys : primary_keys, - gzip : gzip, - }, + data: request_data, error: function(jqXHR, textStatus, errorThrown){ $('.progress-title').html('Migration failed'); $('.progress-text').html( 'A problem occurred when processing the ' + tables_to_migrate[i] + ' table. (#113)' ); @@ -869,23 +921,22 @@ console.log( jqXHR ); console.log( textStatus ); console.log( errorThrown ); - table_migration_error = true; + migration_error = true; migration_complete_events(); return; }, success: function(data){ data = $.trim( data ); - if( ! is_json( data ) ){ + row_information = wpmdb_parse_json( data ); + if( false == row_information ){ $('.progress-title').html('Migration failed'); $('.progress-text').html(data); $('.progress-text').addClass('migration-error'); - table_migration_error = true; + migration_error = true; migration_complete_events(); return; } - row_information = $.parseJSON( data ); - if( row_information.current_row == '-1' ) { progress_size -= overall_table_progress; overall_table_progress = 0; @@ -911,68 +962,6 @@ } - function migration_complete(){ - if( migration_intent == 'savefile' ){ - currently_migrating = false; - var migrate_complete_text = 'Migration complete'; - if( $('#save_computer').is(':checked') ){ - var url = wpmdb_this_download_url + encodeURIComponent( dump_filename ); - if( $('#gzip_file').is(':checked') ){ - url += '&gzip=1'; - } - window.location = url; - } - else{ - migrate_complete_text = 'Migration complete, your backup is located at:
    ' + dump_url + '.'; - } - - if( table_migration_error == false ){ - $('.progress-text').html(migrate_complete_text); - migration_complete_events(); - $('.progress-title').html(completed_msg); - } - - } - else{ // rename temp tables, delete old tables - $('.progress-text').html('Finalizing migration'); - $.ajax({ - url: ajaxurl, - type: 'POST', - dataType: 'text', - cache: false, - data: { - action : 'wpmdb_finalize_backup', - intent : migration_intent, - url : remote_site, - key : secret_key, - form_data : form_data, - stage : stage, - prefix : connection_data.prefix, - }, - error: function(jqXHR, textStatus, errorThrown){ - $('.progress-title').html('Migration failed'); - $('.progress-text').html('A problem occurred when finalizing the backup. (#132)'); - $('.progress-text').addClass('migration-error'); - alert( jqXHR + ' : ' + textStatus + ' : ' + errorThrown ); - table_migration_error = true; - }, - success: function(data){ - if( $.trim( data ) != '' ){ - $('.progress-title').html('Migration failed'); - $('.progress-text').html(data); - $('.progress-text').addClass('migration-error'); - table_migration_error = true; - migration_complete_events(); - return; - } - $('.progress-text').html('Migration complete'); - $('.progress-title').html(completed_msg); - } - }); - migration_complete_events(); - } - } - migrate_table_recursive( '-1', '' ); } @@ -981,14 +970,91 @@ }); - function migration_complete_events(){ + migration_complete_events = function() { + if( false == migration_error ) { + if( non_fatal_errors == '' ) { + $('.progress-text').html('Migration complete'); + $('.progress-title').html(completed_msg); + } + else { + $('.progress-text').html(non_fatal_errors); + $('.progress-text').addClass('migration-error'); + $('.progress-title').html('Migration completed with some errors'); + } + } + migration_completed = true; $('.progress-label').remove(); $('.migration-progress-ajax-spinner').remove(); $('.close-progress-content').show(); $('#overlay').css('cursor','pointer'); - clearInterval( interval ); + clearInterval( elapsed_interval ); currently_migrating = false; + non_fatal_errors = ''; + } + + migration_complete = function() { + if( migration_intent == 'savefile' ){ + currently_migrating = false; + var migrate_complete_text = 'Migration complete'; + if( $('#save_computer').is(':checked') ){ + var url = wpmdb_this_download_url + encodeURIComponent( dump_filename ); + if( $('#gzip_file').is(':checked') ){ + url += '&gzip=1'; + } + window.location = url; + } + else{ + migrate_complete_text = 'Migration complete, your backup is located at: ' + dump_url + '.'; + } + + if( migration_error == false ){ + $('.progress-text').html(migrate_complete_text); + migration_complete_events(); + $('.progress-title').html(completed_msg); + } + + } + else{ // rename temp tables, delete old tables + $('.progress-text').html('Finalizing migration'); + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action : 'wpmdb_finalize_migration', + intent : migration_intent, + url : remote_site, + key : secret_key, + form_data : form_data, + stage : stage, + prefix : connection_data.prefix, + tables : tables_to_migrate.join(','), + }, + error: function(jqXHR, textStatus, errorThrown){ + $('.progress-title').html('Migration failed'); + $('.progress-text').html('A problem occurred when finalizing the backup. (#132)'); + $('.progress-text').addClass('migration-error'); + alert( jqXHR + ' : ' + textStatus + ' : ' + errorThrown ); + migration_error = true; + migration_complete_events(); + return; + }, + success: function(data){ + if( $.trim( data ) != '' ){ + $('.progress-title').html('Migration failed'); + $('.progress-text').html(data); + $('.progress-text').addClass('migration-error'); + migration_error = true; + migration_complete_events(); + return; + } + wpmdb_call_next_hook(); + } + }); + } + } // close progress pop up once migration is completed @@ -1124,6 +1190,10 @@ $('.step-two').show(); $('.backup-options').show(); $('.keep-active-plugins').show(); + $('.directory-permission-notice').hide(); + $('#create-backup').removeAttr('disabled'); + $('#create-backup-label').removeClass('disabled'); + $('.backup-option-disabled').hide(); var connection_info = $.trim( $('.pull-push-connection-info').val() ).split("\n"); if( $('#pull').is(':checked') ){ $('.pull-list li').append( connection_info_box ); @@ -1147,6 +1217,14 @@ $('.different-plugin-version-notice').show(); $('.step-two').hide(); } + if( false == wpmdb_write_permission ) { + $('#create-backup').prop('checked',false); + $('#create-backup').attr('disabled','disabled'); + $('#create-backup-label').addClass('disabled'); + $('.backup-option-disabled').show(); + $('.directory-scope').html('local'); + $('.upload-directory-location').html(wpmdb_this_upload_dir_long); + } } else{ $('.connection-status').show(); @@ -1175,6 +1253,14 @@ $('.different-plugin-version-notice').show(); $('.step-two').hide(); } + if( '0' == connection_data.write_permissions ) { + $('#create-backup').prop('checked',false); + $('#create-backup').attr('disabled','disabled'); + $('#create-backup-label').addClass('disabled'); + $('.backup-option-disabled').show(); + $('.directory-scope').html('remote'); + $('.upload-directory-location').html(connection_data.upload_dir_long); + } } else{ $('.connection-status').show(); @@ -1190,7 +1276,12 @@ } $('.backup-options').hide(); $('.keep-active-plugins').hide(); + if( false == wpmdb_write_permission ) { + $('.directory-permission-notice').show(); + $('.step-two').hide(); + } } + $.wpmdb.do_action( 'move_connection_info_box' ); } function change_replace_values(){ @@ -1204,6 +1295,8 @@ } $('#select-tables').remove(); $('.select-tables-wrap').prepend(push_select); + $('#select-post-types').remove(); + $('.select-post-types-wrap').prepend(push_post_type_select); last_replace_switch = 'push'; } else if( $('#pull').is(':checked') ){ @@ -1216,18 +1309,22 @@ } $('#select-tables').remove(); $('.select-tables-wrap').prepend(pull_select); + $('#select-post-types').remove(); + $('.select-post-types-wrap').prepend(pull_post_type_select); last_replace_switch = 'pull'; } } - // keep a copy of the table select box when making changes + // keep a copy of select boxes when making changes $('#select-tables').change(function(){ if( $('#push').is(':checked') || $('#savefile').is(':checked') ){ push_select = $('#select-tables').clone(); + push_post_type_select = $('#select-post-types').clone(); } else if( $('#pull').is(':checked') ){ pull_select = $('#select-tables').clone(); + pull_post_type_select = $('#select-post-types').clone(); } }); @@ -1239,7 +1336,19 @@ // show / hide GUID helper description $('.general-helper').click(function(){ - $(this).next().toggle(); + var $icon = $(this), + $bubble = $(this).next(); + + // Close any that are already open + $('.helper-message').not($bubble).hide(); + + var position = $icon.position(); + $bubble.css({ + 'left': (position.left + $icon.width() + 8) + 'px', + 'top': (position.top + $icon.height()/2 - 18) + 'px' + }); + + $bubble.toggle(); }); $('body').click(function(){ @@ -1270,6 +1379,14 @@ } } + if( $(this).hasClass('addons') ) { + if( checked_licence == false && wpmdb_has_licence == '1' ) { + $('.addons-content p').append( '' ); + check_licence(); + checked_licence = true; + } + } + }); // repeatable fields @@ -1307,12 +1424,20 @@ // check for hash in url (settings || migrate) switch tabs accordingly if(window.location.hash) { var hash = window.location.hash.substring(1); - if( hash == 'settings' || hash == 'help' ){ - $('.nav-tab').removeClass('nav-tab-active'); - $('.nav-tab.' + hash).addClass('nav-tab-active'); - $('.content-tab').hide(); - $('.' + hash + '-tab').show(); - } + switch_to_plugin_tab(hash, false); + } + + if( get_query_var( 'install-plugin' ) != '' ) { + hash = 'addons'; + checked_licence = true; + switch_to_plugin_tab(hash, true); + } + + function switch_to_plugin_tab( hash, skip_addons_check ) { + $('.nav-tab').removeClass('nav-tab-active'); + $('.nav-tab.' + hash).addClass('nav-tab-active'); + $('.content-tab').hide(); + $('.' + hash + '-tab').show(); if ( hash == 'help' ) { refresh_debug_log(); @@ -1322,6 +1447,14 @@ checked_licence = true; } } + + if ( hash == 'addons' && true != skip_addons_check ) { + if( wpmdb_has_licence == '1' ) { + $('.addons-content p').append( '' ); + check_licence(); + checked_licence = true; + } + } } // regenerates the saved secret key @@ -1360,13 +1493,17 @@ var this_connection_info = $.parseJSON( wpmdb_connection_info ); // show / hide table select box when specific settings change - $('input[name=table_migrate_option]').change(function(){ - $('.select-tables-wrap').toggle(); + $('input.multiselect-toggle').change(function(){ + $(this).parents('.expandable-content').children('.select-wrap').toggle(); }); - if( $('#migrate-selected').is(':checked') ){ - $('.select-tables-wrap').toggle(); - } + $('.show-multiselect').each(function(){ + if( $(this).is(':checked') ){ + $(this).parents('.option-section').children('.header-expand-collapse').children('.expand-collapse-arrow').removeClass('collapsed'); + $(this).parents('.expandable-content').show(); + $(this).parents('.expandable-content').children('.select-wrap').toggle(); + } + }); // delete a profile from the migrate form area $('body').delegate('.delete-profile', 'click', function(){ @@ -1605,7 +1742,7 @@ dataType: 'json', cache: false, data: { - action: 'wpmdb_prepare_remote_connection', + action: 'wpmdb_verify_connection_to_remote_site', url: connection_info[0], key: connection_info[1], intent: intent, @@ -1649,7 +1786,7 @@ maybe_show_prefix_notice( data.prefix ); var table_select = document.createElement('select'); - $(table_select).attr('multiple', 'multiple').attr('name','select-tables[]').attr('id','select-tables'); + $(table_select).attr('multiple', 'multiple').attr('name','select_tables[]').attr('id','select-tables').attr('class','multiselect'); $.each(connection_data.tables, function(index, value) { $(table_select).append(''); @@ -1657,6 +1794,15 @@ pull_select = table_select; + var post_type_select = document.createElement('select'); + $(post_type_select).attr('multiple', 'multiple').attr('name','select_post_types[]').attr('id','select-post-types').attr('class','multiselect'); + + $.each(connection_data.post_types, function(index, value) { + $(post_type_select).append(''); + }); + + pull_post_type_select = post_type_select; + if( $('#pull').is(':checked') ){ $('#new-url').val( wpmdb_this_url ); $('#new-path').val( wpmdb_this_path ); @@ -1668,6 +1814,8 @@ $('#old-domain').val( data.domain ); $('#select-tables').remove(); $('.select-tables-wrap').prepend(pull_select); + $('#select-post-types').remove(); + $('.select-post-types-wrap').prepend(pull_post_type_select); $('.table-prefix').html(data.prefix); $('.uploads-dir').html(wpmdb_this_uploads_dir); } @@ -1676,7 +1824,8 @@ $('#new-path').val( data.path ); $('#new-domain').val( data.domain ); } - + + $.wpmdb.do_action( 'verify_connection_to_remote_site', connection_data ); } }); diff --git a/asset/sass/_mp6.scss b/asset/sass/_mp6.scss new file mode 100644 index 0000000..64e5c37 --- /dev/null +++ b/asset/sass/_mp6.scss @@ -0,0 +1,344 @@ +body.mp6 { + + input[type=checkbox]:disabled { + opacity: 1; + border-color: #ccc; + } + + #wpmdb-main { + margin-top: 15px; + font-size: 14px; + } + + p { + font-size: 14px; + } + + .wrap h2 { + float: left; + } + + .wpmdb { + + input[type=checkbox], + input[type=radio]{ + vertical-align: middle; + margin-top: -4px; + } + + input[type=text], + input[type=password] { + padding: 3px 5px; + } + + input.code { + padding-top: 6px; + } + + label { + font-size: 14px; + } + + h2.nav-tab-wrapper { + float: none; + margin-bottom: 0; + width: 722px; + } + + .help-tab { + h3 { + margin-top: 0; + } + } + + .temp-disabled { + background-color: #f9f9f9; + } + + .migration-profile-options li a{ + border-color: #ccc; + color: #555; + background-color: #e4e4e4; + } + + .migration-profile-options li a:hover{ + background-color: #fff; + color: #464646; + } + + .settings-tab { + .slider-label { + span { + vertical-align: middle; + } + } + + .slider-label-wrapper { + font-size: 14px; + } + + .ui-slider { + border-color: #ccc; + background-color: #fff; + } + + .ui-slider-range { + background-color: #d8fcd1; + } + + .option-section { + li label { + font-size: 14px; + } + } + } + + .connection-info, + .migrate-tab .pull-push-connection-info { + font-weight: bold; + font-size: 14px; + } + + .general-helper { + border: 0; + width: auto; + height: auto; + top: auto; + margin: 0; + } + + .general-helper:after { + content: "\f223"; + display: inline-block; + -webkit-font-smoothing: antialiased; + font: normal 22px/1 'dashicons'; + vertical-align: top; + top: auto; + left: auto; + position: relative; + } + + .helper-message { + font-size: 14px; + line-height: 1.4em; + } + + .right-arrow { + display: none; + } + + .arrow-col { + width: 75px; + } + + .arrow-col:after { + content: "\f344"; + display: inline-block; + -webkit-font-smoothing: antialiased; + font: normal 22px/1 'dashicons'; + vertical-align: top; + color: #999; + } + + .find-heading { + width: 388px; + } + + .replace-fields { + input { + width: 304px; + } + } + + .replace-right-col { + span { + border-color: #999; + + &:hover { + border-color: #666; + } + } + } + + .replace-remove-row, .replace-add-row { + &:after, &:before { + background-color: #999; + } + + &:hover:after, &:hover:before { + background-color: #666; + } + } + + .option-group.migrate-selection { + > li > label { + font-size: 16px; + } + } + + .saved-migration-profile-label { + font-size: 16px; + } + + .option-heading, .checkbox-label { + font-size: 16px; + } + + .checkbox-label { + input[type=checkbox] { + top: auto; + } + } + + .return-to-profile-selection { + font-size: 14px; + } + + .option-description{ + font-size: 13px; + } + + .save-migration-profile-wrap { + li { + position: relative; + } + } + + .delete-profile { + border: 0; + border-radius: 0; + height: auto; + width: auto; + left: 0; + top: 50%; + margin-left: 0; + + &:after { + content: "\f153"; + display: inline-block; + -webkit-font-smoothing: antialiased; + font: normal 18px/1 'dashicons'; + vertical-align: middle; + color: #999; + } + + &:hover:after { + color: #666; + } + } + + .addons-tab { + .addon { + h1 { + font-family: 'Open Sans', sans-serif; + font-weight: 200; + font-size: 24px; + margin-top: 2px; + } + + p { + font-size: 14px; + line-height: 1.4em; + } + } + } + + .help-tab { + .support { + p, .email a { + font-size: 14px; + } + } + + .videos { + h4, p { + font-size: 14px; + } + } + } + + .inline-message, .notification-message { + border-radius: 0; + border: 0; + box-shadow: 0 1px 1px 0 rgba(0,0,0,.1); + padding: 10px 14px; + font-size: 13px; + } + + .notification-message { + margin-bottom: 20px; + background-color: #fff; + + p { + font-size: 13px; + margin-top: 0; + } + + p:last-child { + margin: 0; + } + + h4 { + margin-top: 0; + } + + a { + color: #0074a2; + text-decoration: none; + + &:hover { + color: #2ea2cc; + } + } + } + + .inline-message.error, .notification-message.error-notice { + border-left: 4px solid #dd3d36; + background-color: #fff; + } + + .inline-message.warning, .notification-message.warning-notice { + background-color: #fff; + border-left: 4px solid #ffba00; + } + + .inline-message.success, .notication-message.success-notice { + border-left: 4px solid #7ad03a; + } + + .ssl-notice { + margin-bottom: 0; + } + + .different-plugin-version-notice, .directory-permission-notice { + margin-bottom: 10px; + } + + } + + .progress-content { + font-size: 14px; + box-shadow: 0 0 10px rgba(0,0,0,0.5); + background-color: #eee; + + .progress-title { + font-family: 'Open Sans', sans-serif; + font-weight: normal; + font-size: 22px; + } + + .progress-bar { + background-image: none; + background-color: #0074a2; + } + } + + #overlay { + background-color: rgba(0,0,0,0.5); + } + + .migration-progress-ajax-spinner { + top: 20px; + } + +} \ No newline at end of file diff --git a/asset/sass/styles.scss b/asset/sass/styles.scss index dc470e1..ccea88a 100644 --- a/asset/sass/styles.scss +++ b/asset/sass/styles.scss @@ -1,8 +1,20 @@ @import "compass"; +#wpmdb-main { + width: 742px; +} + +#overlay { + background-color: rgba(255,255,255,0.9); +} + .wpmdb{ - > .warning { - max-width: 750px; + > div.updated.warning { + max-width: 742px; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + margin: 10px 0; } /* ============================================================================= @@ -33,10 +45,16 @@ padding: 5px; } + label.disabled { + color: #888; + cursor: default; + } + .option-section { border-bottom: 1px solid #ccc; padding-bottom: 20px; margin-bottom: 20px; + h3 { font-size: 18px; font-weight: normal; @@ -62,7 +80,7 @@ } .indent-wrap { - margin-left: 25px; + margin-left: 24px; } .expandable-content{ @@ -120,7 +138,7 @@ .licence-input { clear: both; display: block; - font-family: "Courier New",Courier,monospace; + font-family: Consolas, Monaco, monospace; font-size: 14px; margin-bottom: 7px; padding: 10px; @@ -129,6 +147,7 @@ .register-licence { float: left; + outline: none; } .licence-status { @@ -143,10 +162,6 @@ color: #333; } - .licence-information { - margin-bottom: 5px; - } - .register-licence-ajax-spinner { margin: 4px 0 0 8px; } @@ -171,8 +186,8 @@ h2.nav-tab-wrapper { margin-top: 10px; margin-bottom: 20px; - padding-left: 10px; - + padding-left: 5px; + a { margin-right: 4px; } @@ -190,11 +205,6 @@ /* Saved migration profile selection */ - .saved-migration-profile-label{ - font-weight: bold; - font-size: 14px; - } - .migration-profile-options li{ position: relative; width: 520px; @@ -274,11 +284,19 @@ } } - .option-heading { + .option-heading, .checkbox-label { font-size: 14px; font-weight: bold; } + .checkbox-label { + input[type=checkbox] { + margin-right: 7px; + position: relative; + top: -1px; + } + } + .expand-collapse-arrow { margin-right: 9px; } @@ -292,7 +310,7 @@ width: 418px; height: 65px; color: #333; - font-family: "Courier New",Courier,monospace; + font-family: Consolas, Monaco, monospace; font-size: 15px; line-height: 21px; padding: 10px; @@ -324,7 +342,7 @@ .temp-disabled { background-color: #EEEEEE; color: #888888; - font-family: "Courier New",Courier,monospace; + font-family: Consolas, Monaco, monospace; text-shadow: 0 1px 0 #FFFFFF; } @@ -459,12 +477,12 @@ margin: 0 6px; } - .select-tables-wrap{ + .select-wrap{ display: none; margin-top: 12px; } - #select-tables { + .multiselect { min-width: 420px; min-height: 180px; margin-bottom: 10px; @@ -521,14 +539,20 @@ box-shadow: 0px 0px 5px #ccc; } - .ssl-verify-message { - left: 182px; - top: -10px; + .inline-message { + padding: 10px; + border-radius: 3px; + margin-top: 5px; + } + + .inline-message.error { + border: 1px solid #CC0000; + background-color: #FFEBE8; } - .replace-guids-info { - left: 140px; - top: -10px; + .inline-message.warning { + background-color: #FFFFE0; + border: 1px solid #E6DB55; } .helper-message:after { @@ -561,14 +585,13 @@ color: #888; } - .prefix-notice, .ssl-notice, .different-plugin-version-notice, .mysqli-notice { + .prefix-notice, .ssl-notice, .different-plugin-version-notice, .directory-permission-notice { background-color: #FFFFE0; border: 1px solid #E6DB55; padding: 15px; border-radius: 3px; margin-bottom: 15px; display: none; - width: 710px; p{ margin-top: 0px; } @@ -577,7 +600,7 @@ } } - .different-plugin-version-notice, .mysqli-notice { + .different-plugin-version-notice, .directory-permission-notice { background-color: #FFEBE8; border-color: #CC0000; a { @@ -586,10 +609,6 @@ } } - .mysqli-notice { - display: block; - } - .ssl-notice { margin-bottom: 0; margin-top: 15px; @@ -597,11 +616,6 @@ /* Save migration profile */ - .save-migration-profile { - font-size: 14px; - font-weight: bold; - } - .save-migration-profile-wrap { li label{ @@ -709,11 +723,6 @@ float: left; } - .slider-message { - top: -11px; - left: 164px; - } - .slider-spinner { position: absolute; right: -35px; @@ -809,11 +818,9 @@ .connection-info{ clear: both; - background-color: #eee; - color: #888; font-size: 15px; line-height: 21px; - font-family: "Courier New", Courier, monospace; + font-family: Consolas, Monaco, monospace; padding: 10px 10px; height: 67px; text-shadow: 0px 1px 0px #fff; @@ -835,6 +842,16 @@ margin: 4px 7px; } + .masked-licence { + margin-top: 0px; + } + + .bull { + font-size: 22px; + position: relative; + top: 4px; + } + /* ============================================================================= Help Tab ========================================================================== */ @@ -954,7 +971,7 @@ textarea{ width: 100%; min-height: 200px; - font-family: "Courier New",Courier,monospace; + font-family: Consolas, Monaco, monospace; margin-bottom: 5px; } } @@ -973,6 +990,80 @@ } + /* ============================================================================= + Addons Tab + ========================================================================== */ + + .addons-tab { + display: none; + + .addon { + position: relative; + width: 100%; + min-height: 138px; + padding: 25px 30px 30px 165px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + color: #fff; + + .actions { + float: right; + font-size: 14px; + + > * { + margin-right: 10px; + } + + *:last-child { + margin-right: 0; + } + + .action { + background-color: #fff; + font-weight: bold; + display: inline-block; + padding: 0.2em 0.4em; + + &:hover { + background-color: rgba(255,255,255,0.92); + } + } + + .status { + border-bottom: 2px solid #fff; + padding-bottom: 0.1em; + } + } + + h1 { + font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", sans-serif; + font-weight: normal; + float: left; + margin: 0; + margin-top: 5px; + } + + p { + font-size: 16px; + line-height: 1.2em; + clear: both; + padding-top: 15px; + margin: 0; + } + + &.wp-migrate-db-pro-media-files { + $bgcolor: #3fab3f; + background: $bgcolor url(../img/icon-media-files.svg) no-repeat 30px 30px; + background-size: 110px 85px; + + .action { + color: $bgcolor; + } + } + } + } + } /* Progress Information */ @@ -1039,6 +1130,7 @@ .progress-text { clear: left; float: left; + width: 100%; } .timer { @@ -1096,7 +1188,7 @@ position: relative; text-align: center; - span { + > span { padding: 0px 3px; white-space: nowrap; text-overflow: ellipsis; @@ -1110,7 +1202,7 @@ border: 1px solid #ccc; border-radius: 3px; background-color: #fff; - font-family: "Courier New",Courier,monospace; + font-family: Consolas, Monaco, monospace; font-size: 12px; display: inline-block; top: -35px; @@ -1179,4 +1271,6 @@ border-color: #aaa; } -} \ No newline at end of file +} + +@import "mp6"; \ No newline at end of file diff --git a/class/wpmdbpro-addon.php b/class/wpmdbpro-addon.php new file mode 100644 index 0000000..7571d9e --- /dev/null +++ b/class/wpmdbpro-addon.php @@ -0,0 +1,50 @@ +get_installed_version( 'wp-migrate-db-pro/wp-migrate-db-pro.php' ); + $result = version_compare( $wpmdb_pro_version, $version_required, '>=' ); + $this->version_required = $version_required; + if( false == $result ) $this->hook_version_requirement_actions(); + return $result; + } + + function hook_version_requirement_actions() { + add_action( 'wpmdb_notices', array( $this, 'version_requirement_actions' ) ); + } + + function version_requirement_actions() { + $addon_requirement_check = get_option( 'wpmdb_addon_requirement_check', array() ); + // we only want to delete the transients once, here we keep track of which versions we've checked + if( ! isset( $addon_requirement_check[$this->plugin_slug] ) || $addon_requirement_check[$this->plugin_slug] != $this->get_installed_version() ) { + delete_site_transient( 'wpmdb_upgrade_data' ); + delete_site_transient( 'update_plugins' ); + $addon_requirement_check[$this->plugin_slug] = $this->get_installed_version(); + update_option( 'wpmdb_addon_requirement_check', $addon_requirement_check ); + } + $this->version_requirement_warning(); + } + + function version_requirement_warning() { ?> +
    +

    + Update Required — + get_plugin_name(); + $required = $this->version_required; + $installed = $this->get_installed_version( $wpmdb_basename ); + $update = wp_nonce_url( network_admin_url( 'update.php?action=upgrade-plugin&plugin=wp-migrate-db-pro%2Fwp-migrate-db-pro.php' ), 'upgrade-plugin_' . $wpmdb_basename ); + echo sprintf( 'The version of %s you have installed, requires version %s of WP Migrate DB Pro. You currently have %s installed. Update Now', $addon_name, $required, $installed, $update ); + ?> +

    +
    + settings = get_option( 'wpmdb_settings' ); + + $this->transient_timeout = 60 * 60 * 12; + $this->transient_retry_timeout = 60 * 60 * 2; + + $this->plugin_file_path = $plugin_file_path; + $this->plugin_dir_path = plugin_dir_path( $plugin_file_path ); + $this->plugin_slug = basename( $this->plugin_dir_path ); + $this->plugin_basename = plugin_basename( $plugin_file_path ); + $this->template_dir = $this->plugin_dir_path . 'template' . DS; + $this->plugin_title = ucwords( str_ireplace( '-', ' ', $this->plugin_slug ) ); + $this->plugin_title = str_ireplace( array( 'db', 'wp' ), array( 'DB', 'WP' ), $this->plugin_title ); + + if ( defined( 'DBRAINS_API_BASE' ) ) { + $this->dbrains_api_base = DBRAINS_API_BASE; + } + + if( $this->open_ssl_enabled() == false ) { + $this->dbrains_api_base = str_replace( 'https://', 'http://', $this->dbrains_api_base ); + } + + $this->dbrains_api_url = $this->dbrains_api_base . '/?wc-api=delicious-brains'; + + if ( is_multisite() ) { + $this->plugin_base = 'settings.php?page=wp-migrate-db-pro'; + } + else { + $this->plugin_base = 'tools.php?page=wp-migrate-db-pro'; + } + + // Seen when the user clicks "view details" on the plugin listing page + add_action( 'install_plugins_pre_plugin-information', array( $this, 'plugin_update_popup' ) ); + + // Add an extra row to the plugin screen + add_action( 'after_plugin_row_' . $this->plugin_basename, array( $this, 'plugin_row' ), 11 ); + + // Adds a custom error message to the plugin install page if required (licence expired / invalid) + add_filter( 'http_response', array( $this, 'verify_download' ), 10, 3 ); + } + + function printer( $debug ) { + echo '
    ' . print_r( $debug, true ) . '
    '; + } + + function template( $template ) { + include $this->template_dir . $template . '.php'; + } + + function get_installed_version( $plugin = false ) { + if ( !is_admin() ) return false; + + $plugin_basename = ( false !== $plugin ? $plugin : $this->plugin_basename ); + + $plugins = get_plugins(); + + if ( !isset( $plugins[$plugin_basename]['Version'] ) ) { + return false; + } + + return $plugins[$plugin_basename]['Version']; + } + + function open_ssl_enabled() { + if ( defined( 'OPENSSL_VERSION_TEXT' ) ) { + return true; + } + else { + return false; + } + } + + function set_time_limit() { + if ( !function_exists( 'ini_get' ) || !ini_get( 'safe_mode' ) ) { + set_time_limit( 0 ); + } + } + + function remote_post( $url, $data, $scope, $args = array(), $expecting_serial = false ) { + $this->set_time_limit(); + + if( function_exists( 'fsockopen' ) && strpos( $url, 'https://' ) === 0 && $scope == 'ajax_verify_connection_to_remote_site' ) { + $url_parts = parse_url( $url ); + $host = $url_parts['host']; + if( $pf = @fsockopen( $host, 443, $err, $err_string, 1 ) ) { + // worked + fclose( $pf ); + } + else { + // failed + $url = substr_replace( $url, 'http', 0, 5 ); + } + } + + $sslverify = ( $this->settings['verify_ssl'] == 1 ? true : false ); + + $default_remote_post_timeout = apply_filters( 'wpmdb_default_remote_post_timeout', 60 * 20 ); + + $args = wp_parse_args( $args, array( + 'timeout' => $default_remote_post_timeout, + 'blocking' => true, + 'sslverify' => $sslverify, + ) ); + + $args['method'] = 'POST'; + $args['body'] = $this->array_to_multipart( $data ); + $args['headers']['Content-Type'] = 'multipart/form-data; boundary=' . $this->multipart_boundary; + $args['headers']['Referer'] = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ); + + $this->attempting_to_connect_to = $url; + + $response = wp_remote_post( $url, $args ); + + if ( ! is_wp_error( $response ) ) { + $response['body'] = trim( $response['body'], "\xef\xbb\xbf" ); + } + + if ( is_wp_error( $response ) ) { + if( strpos( $url, 'https://' ) === 0 && $scope == 'ajax_verify_connection_to_remote_site' ) { + $url = substr_replace( $url, 'http', 0, 5 ); + if( $response = $this->remote_post( $url, $data, $scope, $args, $expecting_serial ) ) { + return $response; + } + else { + return false; + } + } + else if( isset( $response->errors['http_request_failed'][0] ) && strstr( $response->errors['http_request_failed'][0], 'timed out' ) ) { + $this->error = 'The connection to the remote server has timed out, no changes have been committed. (#134 - scope: ' . $scope . ')'; + } + else if ( isset( $response->errors['http_request_failed'][0] ) && ( strstr( $response->errors['http_request_failed'][0], 'Could not resolve host' ) || strstr( $response->errors['http_request_failed'][0], 'couldn\'t connect to host' ) ) ) { + $this->error = 'We could not find: ' . $_POST['url'] . '. Are you sure this is the correct URL?'; + $url_bits = parse_url( $_POST['url'] ); + if( strstr( $_POST['url'], 'dev.' ) || strstr( $_POST['url'], '.dev' ) || ! strstr( $url_bits['host'], '.' ) ) { + $this->error .= '
    It appears that you might be trying to ' . $_POST['intent'] . ( $_POST['intent'] == 'pull' ? ' from' : ' to' ) . ' a local environment. This will not work if this website happens to be located on a remote server, it would be impossible for this server to contact your local environment.'; + } + } + else { + $this->error = 'The connection failed, an unexpected error occurred, please contact support. (#121 - scope: ' . $scope . ')'; + } + $this->log_error( $this->error, $response ); + return false; + } + elseif ( (int) $response['response']['code'] < 200 || (int) $response['response']['code'] > 399 ) { + if( strpos( $url, 'https://' ) === 0 && $scope == 'ajax_verify_connection_to_remote_site' ) { + $url = substr_replace( $url, 'http', 0, 5 ); + if( $response = $this->remote_post( $url, $data, $scope, $args, $expecting_serial ) ) { + return $response; + } + else { + return false; + } + } + else if( $response['response']['code'] == '401' ) { + $this->error = 'The remote site is protected with Basic Authentication. Please enter the username and password above to continue. (401 Unauthorized)'; + $this->log_error( $this->error, $response ); + return false; + } + else { + $this->error = 'Unable to connect to the remote server, please check the connection details - ' . $response['response']['code'] . ' ' . $response['response']['message'] . ' (#129 - scope: ' . $scope . ')'; + $this->log_error( $this->error, $response ); + return false; + } + } + elseif ( $expecting_serial && is_serialized( $response['body'] ) == false ) { + $this->error = 'There was a problem with the AJAX request, we were expecting a serialized response, instead we received:
    ' . htmlentities( $response['body'] ); + $this->log_error( $this->error, $response ); + return false; + } + elseif ( $response['body'] === '0' ) { + $this->error = 'WP Migrate DB Pro does not seem to be installed or active on the remote site. (#131 - scope: ' . $scope . ')'; + $this->log_error( $this->error, $response ); + return false; + } + + return $response['body']; + } + + function array_to_multipart( $data ) { + if ( !$data || !is_array( $data ) ) { + return $data; + } + + $result = ''; + + foreach ( $data as $key => $value ) { + $result .= '--' . $this->multipart_boundary . "\r\n" . + sprintf( 'Content-Disposition: form-data; name="%s"', $key ); + + if ( 'chunk' == $key ) { + if ( $data['chunk_gzipped'] ) { + $result .= "; filename=\"chunk.txt.gz\"\r\nContent-Type: application/x-gzip"; + } + else { + $result .= "; filename=\"chunk.txt\"\r\nContent-Type: text/plain;"; + } + } + else { + $result .= "\r\nContent-Type: text/plain; charset=" . get_option( 'blog_charset' ); + } + + $result .= "\r\n\r\n" . $value . "\r\n"; + } + + $result .= "--" . $this->multipart_boundary . "--\r\n"; + + return $result; + } + + function log_error( $wpmdb_error, $additional_error_var = false ){ + $error_header = "********************************************\n****** Log date: " . date( 'Y/m/d H:i:s' ) . " ******\n********************************************\n\n"; + $error = $error_header . "WPMDB Error: " . $wpmdb_error . "\n\n"; + if( ! empty( $this->attempting_to_connect_to ) ) { + $error .= "Attempted to connect to: " . $this->attempting_to_connect_to . "\n\n"; + } + if( $additional_error_var !== false ){ + $error .= print_r( $additional_error_var, true ) . "\n\n"; + } + $log = get_option( 'wpmdb_error_log' ); + if( $log ) { + $log = $log . $error; + } + else { + $log = $error; + } + update_option( 'wpmdb_error_log', $log ); + } + + function display_errors() { + if ( ! empty( $this->error ) ) { + echo $this->error; + $this->error = ''; + return true; + } + return false; + } + + function filter_post_elements( $post_array, $accepted_elements ) { + $accepted_elements[] = 'sig'; + return array_intersect_key( $post_array, array_flip( $accepted_elements ) ); + } + + function create_signature( $data, $key ) { + if ( isset( $data['sig'] ) ) { + unset( $data['sig'] ); + } + $flat_data = implode( '', $data ); + return base64_encode( hash_hmac( 'sha1', $flat_data, $key, true ) ); + } + + function verify_signature( $data, $key ) { + if( empty( $data['sig'] ) ) { + return false; + } + $temp = $data; + $computed_signature = $this->create_signature( $temp, $key ); + return $computed_signature === $data['sig']; + } + + function get_dbrains_api_url( $request, $args = array() ) { + $url = $this->dbrains_api_url; + $args['request'] = $request; + $url = add_query_arg( $args, $url ); + return $url; + } + + function dbrains_api_request( $request, $args = array() ) { + $sslverify = ( $this->settings['verify_ssl'] == 1 ? true : false ); + + $url = $this->get_dbrains_api_url( $request, $args ); + $response = wp_remote_get( $url, array( + 'timeout' => 30, + 'blocking' => true, + 'sslverify' => $sslverify + ) ); + + if ( is_wp_error( $response ) || (int) $response['response']['code'] < 200 || (int) $response['response']['code'] > 399 ) { + return json_encode( array( 'errors' => array( 'connection_failed' => $url . 'Could not connect to deliciousbrains.com.' ) ) ); + } + + return $response['body']; + } + + function plugin_update_popup() { + if ( $this->plugin_slug != $_GET['plugin'] ) return; + + $filename = $this->plugin_slug; + $latest_version = $this->get_latest_version( $this->plugin_slug ); + if ( $this->is_beta_version( $latest_version ) ) { + $filename .= '-beta'; + } + + $url = $this->dbrains_api_base . '/content/themes/delicious-brains/update-popup/' . $filename . '.html'; + $data = wp_remote_get( $url, array( 'timeout' => 30 ) ); + + if ( is_wp_error( $data ) || 200 != $data['response']['code'] ) { + echo '

    Could not retrieve version details. Please try again.

    '; + } + else { + echo $data['body']; + } + + exit; + } + + /* + * Shows a message below the plugin on the plugins page when: + * 1. the license hasn't been activated + * 2. when there's an update available but the license is expired + * + * TODO: Implement "Check my license again" link + */ + function plugin_row() { + $licence = $this->get_licence_key(); + $licence_response = $this->is_licence_expired(); + $licence_problem = isset( $licence_response['errors'] ); + + $installed_version = $this->get_installed_version( $this->plugin_basename ); + $latest_version = $this->get_latest_version( $this->plugin_slug ); + + $new_version = ''; + if ( version_compare( $installed_version, $latest_version, '<' ) ) { + $new_version = __( 'There is a new version of ' . $this->plugin_title . ' available.', 'wp-migrate-db-pro' ); + $new_version .= ' '; + $new_version .= sprintf( __( 'View version %s details', 'wp-migrate-db-pro' ), $latest_version ) . '.'; + } + + if ( !$new_version && !empty( $licence ) ) { + return; + } + + if( empty( $licence ) ) { + $settings_link = sprintf( '%s', network_admin_url( $this->plugin_base ) . '#settings', __( 'Settings', 'wp-migrate-db-pro' ) ); + if ( $new_version ) { + $message = 'To update, '; + } + else { + $message = 'To finish activating ' . $this->plugin_title . ', please '; + } + + $message .= 'go to ' . $settings_link . ' and enter your licence key. + If you don\'t have a licence key, you may + purchase one.'; + } + elseif ( $licence_problem ) { + $message = array_shift( $licence_response['errors'] ) . ' Check my license again'; + } + else { + return; + } + ?> + + + +
    + + + + + + + + get_plugin_update_download_url( $this->plugin_slug ); + + if ( 0 === strpos( $url, $download_url ) || 402 != $response['response']['code'] ) { + return $response; + } + + // The $response['body'] is blank but output is actually saved to a file in this case + $data = @file_get_contents( $response['filename'] ); + + if ( !$data ) { + return new WP_Error( 'wpmdbpro_download_error_empty', 'Error retrieving download from deliciousbrain.com. Please try again or download manually from My Account.' ); + } + + $decoded_data = json_decode( $data, true ); + + // Can't decode the JSON errors, so just barf it all out + if ( !isset( $decoded_data['errors'] ) || !$decoded_data['errors'] ) { + return new WP_Error( 'wpmdbpro_download_error_raw', $data ); + } + + foreach ( $decoded_data['errors'] as $key => $msg ) { + return new WP_Error( 'wpmdbpro_' . $key, $msg ); + } + } + + function is_licence_constant() { + return defined( 'WPMDB_LICENCE' ); + } + + function get_licence_key() { + return $this->is_licence_constant() ? WPMDB_LICENCE : $this->settings['licence']; + } + + function is_licence_expired( $skip_transient_check = false ) { + $licence = $this->get_licence_key(); + if( empty( $licence ) ) { + $settings_link = sprintf( '%s', network_admin_url( $this->plugin_base ) . '#settings', __( 'Settings', 'wp-migrate-db-pro' ) ); + $message = 'To finish activating WP Migrate DB Pro, please go to ' . $settings_link . ' and enter your licence key. + If you don\'t have a licence key, you may + purchase one.'; + return array( 'errors' => array( 'no_licence' => $message ) ); + } + + if( ! $skip_transient_check ) { + $trans = get_site_transient( 'wpmdb_licence_response' ); + if ( false !== $trans ) return json_decode( $trans, true ); + } + + return json_decode( $this->check_licence( $licence ), true ); + } + + function check_licence( $licence_key ) { + // testing only 1st line = valid licence 2nd line = not valid licence + // return json_encode( array( 'ok' => 'ok' ) ); + // return json_encode( array( 'errors' => array( 'standard' => 'oh no! licence is not working.') ) ); + if( empty( $licence_key ) ) { + return false; + } + $args = array( + 'licence_key' => $licence_key, + 'site_url' => site_url( '', 'http' ), + ); + + $response = $this->dbrains_api_request( 'check_support_access', $args ); + set_site_transient( 'wpmdb_licence_response', $response, $this->transient_timeout ); + return $response; + } + + function is_beta_version( $ver ) { + if ( preg_match( '@b[0-9]+$@', $ver ) ) { + return true; + } + + return false; + } + + function get_latest_version( $slug ) { + $data = $this->get_upgrade_data(); + + // Return the latest beta version if the installed version is beta + // and the API returned a beta version and it's newer than the latest stable version + $installed_version = $this->get_installed_version( sprintf( '%1$s/%1$s.php', $slug ) ); + + if ( $installed_version && $this->is_beta_version( $installed_version ) + && isset( $data[$slug]['beta_version'] ) + && version_compare( $data[$slug]['version'], $data[$slug]['beta_version'], '<' ) + ) { + return $data[$slug]['beta_version']; + } + + return $data[$slug]['version']; + } + + function get_upgrade_data() { + $info = get_site_transient( 'wpmdb_upgrade_data' ); + + if( isset( $info['version'] ) ) { + delete_site_transient( 'wpmdb_licence_response' ); + delete_site_transient( 'wpmdb_upgrade_data' ); + $info = false; + } + + if ( $info ) return $info; + + $data = $this->dbrains_api_request( 'upgrade_data' ); + + $data = json_decode( $data, true ); + + /* + We need to set the transient even when there's an error, + otherwise we'll end up making API requests over and over again + and slowing things down big time. + */ + $default_upgrade_data = array( 'wp-migrate-db-pro' => array( 'version' => $this->get_installed_version() ) ); + + if ( !$data ) { + set_site_transient( 'wpmdb_upgrade_data', $default_upgrade_data, $this->transient_retry_timeout ); + $this->log_error( 'Error trying to decode JSON upgrade data.' ); + return false; + } + + if ( isset( $data['errors'] ) ) { + set_site_transient( 'wpmdb_upgrade_data', $default_upgrade_data, $this->transient_retry_timeout ); + $this->log_error( 'Error trying to get upgrade data.', $data['errors'] ); + return false; + } + + set_site_transient( 'wpmdb_upgrade_data', $data, $this->transient_timeout ); + + return $data; + } + + function get_plugin_update_download_url( $plugin_slug, $is_beta = false ) { + $licence = $this->get_licence_key(); + $query_args = array( + 'request' => 'download', + 'licence_key' => $licence, + 'slug' => $plugin_slug, + 'site_url' => home_url( '', 'http') + ); + + if ( $is_beta ) { + $query_args['beta'] = '1'; + } + + return add_query_arg( $query_args, $this->dbrains_api_url ); + } + + function set_time_limit_available() { + if ( ! function_exists( 'set_time_limit' ) || ! function_exists( 'ini_get' ) ) return false; + $current_max_execution_time = ini_get( 'max_execution_time' ); + $proposed_max_execution_time = ( $current_max_execution_time == 30 ) ? 31 : 30; + @set_time_limit( $proposed_max_execution_time ); + $current_max_execution_time = ini_get( 'max_execution_time' ); + return ( $proposed_max_execution_time == $current_max_execution_time ); + } + + function get_plugin_name( $plugin = false ) { + if ( !is_admin() ) return false; + + $plugin_basename = ( false !== $plugin ? $plugin : $this->plugin_basename ); + + $plugins = get_plugins(); + + if ( !isset( $plugins[$plugin_basename]['Name'] ) ) { + return false; + } + + return $plugins[$plugin_basename]['Name']; + } + +} \ No newline at end of file diff --git a/class/wp-migrate-db.php b/class/wpmdbpro.php similarity index 69% rename from class/wp-migrate-db.php rename to class/wpmdbpro.php index f136a6c..357388d 100644 --- a/class/wp-migrate-db.php +++ b/class/wpmdbpro.php @@ -1,64 +1,27 @@ plugin_file_path = $plugin_file_path; - $this->plugin_dir_path = plugin_dir_path( $plugin_file_path ); - $this->plugin_slug = basename( $this->plugin_dir_path ); - $this->plugin_basename = plugin_basename( $plugin_file_path ); - - $this->replaced['serialized']['count'] = 0; - $this->replaced['serialized']['strings'] = ''; - $this->replaced['nonserialized']['count'] = 0; - - if ( defined( 'DBRAINS_API_BASE' ) ) { - $this->dbrains_api_base = DBRAINS_API_BASE; - } - - if( $this->open_ssl_enabled() == false ) { - $this->dbrains_api_base = str_replace( 'https://', 'http://', $this->dbrains_api_base ); - } - - $this->transient_timeout = 60 * 60 * 12; - $this->transient_retry_timeout = 60 * 60 * 2; - - $this->dbrains_api_url = $this->dbrains_api_base . '/?wc-api=delicious-brains'; - - $this->settings = get_option( 'wpmdb_settings' ); + parent::__construct( $plugin_file_path ); $this->max_insert_string_len = 50000; // 50000 is the default as defined by phphmyadmin @@ -68,7 +31,6 @@ function __construct( $plugin_file_path ) { 'allow_push' => false, 'profiles' => array(), 'licence' => '', - 'licence_email' => '', 'verify_ssl' => false, ); @@ -103,24 +65,15 @@ function __construct( $plugin_file_path ) { add_filter( 'plugin_action_links_' . $this->plugin_basename, array( $this, 'plugin_action_links' ) ); add_filter( 'network_admin_plugin_action_links_' . $this->plugin_basename, array( $this, 'plugin_action_links' ) ); - if ( is_multisite() ) { - add_action( 'network_admin_menu', array( $this, 'network_admin_menu' ) ); - $this->plugin_base = 'settings.php?page=wp-migrate-db-pro'; - } - else { - add_action( 'admin_menu', array( $this, 'admin_menu' ) ); - $this->plugin_base = 'tools.php?page=wp-migrate-db-pro'; - } - // internal AJAX handlers - add_action( 'wp_ajax_wpmdb_prepare_remote_connection', array( $this, 'ajax_prepare_remote_connection' ) ); + add_action( 'wp_ajax_wpmdb_verify_connection_to_remote_site', array( $this, 'ajax_verify_connection_to_remote_site' ) ); add_action( 'wp_ajax_wpmdb_reset_api_key', array( $this, 'ajax_reset_api_key' ) ); add_action( 'wp_ajax_wpmdb_delete_migration_profile', array( $this, 'ajax_delete_migration_profile' ) ); add_action( 'wp_ajax_wpmdb_save_setting', array( $this, 'ajax_save_setting' ) ); add_action( 'wp_ajax_wpmdb_save_profile', array( $this, 'ajax_save_profile' ) ); add_action( 'wp_ajax_wpmdb_initiate_migration', array( $this, 'ajax_initiate_migration' ) ); - add_action( 'wp_ajax_wpmdb_prepare_table_migration', array( $this, 'ajax_prepare_table_migration' ) ); - add_action( 'wp_ajax_wpmdb_finalize_backup', array( $this, 'ajax_finalize_backup' ) ); + add_action( 'wp_ajax_wpmdb_migrate_table', array( $this, 'ajax_migrate_table' ) ); + add_action( 'wp_ajax_wpmdb_finalize_migration', array( $this, 'ajax_finalize_migration' ) ); add_action( 'wp_ajax_wpmdb_clear_log', array( $this, 'ajax_clear_log' ) ); add_action( 'wp_ajax_wpmdb_get_log', array( $this, 'ajax_get_log' ) ); add_action( 'wp_ajax_wpmdb_activate_licence', array( $this, 'ajax_activate_licence' ) ); @@ -129,33 +82,25 @@ function __construct( $plugin_file_path ) { add_action( 'wp_ajax_wpmdb_update_max_request_size', array( $this, 'ajax_update_max_request_size' ) ); // external AJAX handlers - add_action( 'wp_ajax_nopriv_wpmdb_establish_remote_connection', array( $this, 'ajax_establish_remote_connection' ) ); - add_action( 'wp_ajax_nopriv_wpmdb_respond_initiate_migration', array( $this, 'ajax_respond_initiate_migration' ) ); - add_action( 'wp_ajax_nopriv_wpmdb_process_chunk', array( $this, 'ajax_process_chunk' ) ); - add_action( 'wp_ajax_nopriv_wpmdb_prepare_table_migration', array( $this, 'ajax_prepare_table_migration' ) ); - add_action( 'wp_ajax_nopriv_wpmdb_finalize_backup', array( $this, 'ajax_finalize_backup' ) ); - add_action( 'wp_ajax_nopriv_wpmdb_process_pull_request', array( $this, 'ajax_process_pull_request' ) ); + add_action( 'wp_ajax_nopriv_wpmdb_verify_connection_to_remote_site', array( $this, 'respond_to_verify_connection_to_remote_site' ) ); + add_action( 'wp_ajax_nopriv_wpmdb_remote_initiate_migration', array( $this, 'respond_to_remote_initiate_migration' ) ); + add_action( 'wp_ajax_nopriv_wpmdb_process_chunk', array( $this, 'ajax_process_chunk' ) ); + add_action( 'wp_ajax_nopriv_wpmdb_process_pull_request', array( $this, 'respond_to_process_pull_request' ) ); add_action( 'wp_ajax_nopriv_wpmdb_fire_migration_complete', array( $this, 'fire_migration_complete' ) ); + add_action( 'wp_ajax_nopriv_wpmdb_backup_remote_table', array( $this, 'respond_to_backup_remote_table' ) ); + add_action( 'wp_ajax_nopriv_wpmdb_remote_finalize_migration', array( $this, 'respond_to_remote_finalize_migration' ) ); // Take over the update check add_filter( 'site_transient_update_plugins', array( $this, 'site_transient_update_plugins' ) ); - // Add an extra row to the plugin screen - add_action( 'after_plugin_row_' . $this->plugin_basename, array( $this, 'plugin_row' ), 11 ); - - // Seen when the user clicks "view details" on the plugin listing page - add_action( 'install_plugins_pre_plugin-information', array( $this, 'plugin_update_popup' ) ); - - // Adds a custom error message to the plugin install page if required (licence expired / invalid) - add_filter( 'http_response', array( $this, 'verify_download' ), 10, 3 ); - // Add some custom JS into the WP admin pages add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_plugin_update_script' ) ); // Add some custom CSS into the WP admin pages add_action( 'admin_head-plugins.php', array( $this, 'add_plugin_update_styles' ) ); - $this->template_dir = $this->plugin_dir_path . 'template' . DS; + // Hook into the plugin install process, inject addon download url + add_action( 'plugins_api', array( $this, 'inject_addon_install_resource' ), 10, 3 ); $absolute_path = rtrim( ABSPATH, '\\/' ); $site_url = rtrim( site_url( '', 'http' ), '\\/' ); @@ -179,32 +124,53 @@ function __construct( $plugin_file_path ) { 'select_tables', 'replace_guids', 'exclude_spam', - 'exclude_revisions', 'save_migration_profile', 'save_migration_profile_option', 'create_new_profile', 'create_backup', 'remove_backup', 'keep_active_plugins', + 'post_type_migrate_option', + 'select_post_types', ); $this->default_profile = array( - 'action' => 'savefile', + 'action' => 'savefile', 'save_computer' => '1', - 'gzip_file' => '1', + 'gzip_file' => '1', 'table_migrate_option' => 'migrate_only_with_prefix', 'replace_guids' => '1', - 'default_profile' => true, - 'name' => '', + 'default_profile' => true, + 'name' => '', 'select_tables' => array(), + 'post_type_migrate_option' => 'migrate_all_post_types', + 'select_post_types' => array(), ); + if ( is_multisite() ) { + add_action( 'network_admin_menu', array( $this, 'network_admin_menu' ) ); + } + else { + add_action( 'admin_menu', array( $this, 'admin_menu' ) ); + } + + add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) ); + // this is how many DB rows are processed at a time, allow devs to change this value $this->rows_per_segment = apply_filters( 'wpmdb_rows_per_segment', $this->rows_per_segment ); // allow devs to change the temporary prefix applied to the tables $this->temp_prefix = apply_filters( 'wpmdb_temporary_prefix', $this->temp_prefix ); + if ( is_multisite() ) { + add_action( 'network_admin_menu', array( $this, 'network_admin_menu' ) ); + $this->plugin_base = 'settings.php?page=wp-migrate-db-pro'; + } + else { + add_action( 'admin_menu', array( $this, 'admin_menu' ) ); + $this->plugin_base = 'tools.php?page=wp-migrate-db-pro'; + } + // testing only - if uncommented, will always check for plugin updates //delete_site_transient( 'update_plugins' ); //delete_site_transient( 'wpmdb_upgrade_data' ); @@ -258,12 +224,12 @@ function get_upload_info( $type = 'path' ) { if( ! file_exists( $upload_dir['basedir'] . DS . $upload_dir_name ) ) { $url = wp_nonce_url( $this->plugin_base, 'wp-migrate-db-pro-nonce' ); - if( false === mkdir( $upload_dir['basedir'] . DS . $upload_dir_name, 0755 ) ) { + if( false === @mkdir( $upload_dir['basedir'] . DS . $upload_dir_name, 0755 ) ) { return $upload_info[$type]; } $filename = $upload_dir['basedir'] . DS . $upload_dir_name . DS . 'index.php'; - if( false === file_put_contents( $filename, "" ) ) { + if( false === @file_put_contents( $filename, "" ) ) { return $upload_info[$type]; } } @@ -280,57 +246,72 @@ function ajax_update_max_request_size() { exit; } - function filter_post_elements( $post_array, $accepted_elements ) { - $accepted_elements[] = 'sig'; - return array_intersect_key( $post_array, array_flip( $accepted_elements ) ); - } + function ajax_check_licence() { + $licence = ( empty( $_POST['licence'] ) ? $this->get_licence_key() : $_POST['licence'] ); + $response = $this->check_licence( $licence ); + $decoded_response = json_decode( $response, ARRAY_A ); - function verify_download( $response, $args, $url ) { - $download_url = $this->get_plugin_update_download_url(); + ob_start(); - if ( $url != $download_url || 402 != $response['response']['code'] ) { - return $response; + // Test out what the addons tab would look like with a full page of addons + /* + $first_addon = key( $decoded_response['addon_list'] ); + for( $i = 0; $i < 12; $i++ ) { + $list_of_addons[$first_addon . $i] = $decoded_response['addon_list'][$first_addon]; } + $decoded_response['addon_list'] = $list_of_addons; + */ - // The $response['body'] is blank but output is actually saved to a file in this case - $data = @file_get_contents( $response['filename'] ); - - if ( !$data ) { - return new WP_Error( 'wpmdbpro_download_error_empty', 'Error retrieving download from deliciousbrain.com. Please try again or download manually from My Account.' ); + $addons_available = ( $decoded_response['addons_available'] == '1' ); + if( ! $addons_available ) { ?> +

    Addons Unavailable – Addons are not included with + the Personal license. Visit My Account + to upgrade in just a few clicks.

    + $addon ) { + $plugin_file = sprintf( '%1$s/%1$s.php', $key ); + $plugin_ids = array_keys( get_plugins() ); - foreach ( $decoded_data['errors'] as $key => $msg ) { - return new WP_Error( 'wpmdbpro_' . $key, $msg ); - } - } + if ( in_array( $plugin_file, $plugin_ids ) ) { + $actions = 'Installed'; + if ( is_plugin_active( $plugin_file ) ) { + $actions .= ' & Activated'; + } + else { + $activate_url = wp_nonce_url( network_admin_url( 'plugins.php?action=activate&plugin=' . $plugin_file ), 'activate-plugin_' . $plugin_file ); + $actions .= sprintf( ' Activate', $activate_url ); + } + } + else { + $install_url = wp_nonce_url( network_admin_url( 'update.php?action=install-plugin&plugin=' . $key ), 'install-plugin_' . $key ); + $actions = sprintf( 'Install', $install_url ); - function check_licence( $licence_key ) { - // testing only 1st line = valid licence 2nd line = not valid licence - // return json_encode( array( 'ok' => 'ok' ) ); - // return json_encode( array( 'errors' => array( 'standard' => 'oh no! licence is not working.') ) ); - if( empty( $licence_key ) ) { - return false; + $download_url = $this->get_plugin_update_download_url( $key ); + $actions .= sprintf( 'Download', $download_url ); + } + ?> +
    +
    + +
    + + +

    +

    +
    +
    + $licence_key, - 'site_url' => site_url( '', 'http' ), - ); + $addon_content = ob_get_clean(); + $decoded_response['addon_content'] = $addon_content; + $response = json_encode( $decoded_response ); - $response = $this->dbrains_api_request( 'check_support_access', $args ); - set_site_transient( 'wpmdb_licence_response', $response, $this->transient_timeout ); - return $response; - } - - function ajax_check_licence() { - $licence = ( empty( $_POST['licence'] ) ? $this->get_licence_key() : $_POST['licence'] ); - $response = $this->check_licence( $licence ); echo $response; exit; } @@ -346,213 +327,26 @@ function ajax_activate_licence() { } $response = $this->dbrains_api_request( 'activate_licence', $args ); - - echo $response; - $response = json_decode( $response, true ); - if ( $response && !isset( $response['errors'] ) ) { + if ( ! isset( $response['errors'] ) ) { if ( !$this->is_licence_constant() ) { $this->settings['licence'] = $_POST['licence_key']; } - $this->settings['licence_email'] = $response['email']; update_option( 'wpmdb_settings', $this->settings ); + $response['masked_licence'] = $this->get_formatted_masked_licence(); } + echo json_encode( $response ); exit; } - function get_dbrains_api_url( $request, $args = array() ) { - $url = $this->dbrains_api_url; - $args['request'] = $request; - $url = add_query_arg( $args, $url ); - return $url; - } - - function dbrains_api_request( $request, $args = array() ) { - $sslverify = ( $this->settings['verify_ssl'] == 1 ? true : false ); - - $url = $this->get_dbrains_api_url( $request, $args ); - $response = wp_remote_get( $url, array( - 'timeout' => 30, - 'blocking' => true, - 'sslverify' => $sslverify - ) ); - - if ( is_wp_error( $response ) || (int) $response['response']['code'] < 200 || (int) $response['response']['code'] > 399 ) { - return json_encode( array( 'errors' => array( 'connection_failed' => $url . 'Could not connect to deliciousbrains.com.' ) ) ); - } - - return $response['body']; - } - - function display_errors() { - if ( ! empty( $this->error ) ) { - echo $this->error; - $this->error = ''; - return true; - } - return false; - } - - function array_to_multipart( $data ) { - if ( !$data || !is_array( $data ) ) { - return $data; - } - - $result = ''; - - foreach ( $data as $key => $value ) { - $result .= '--' . $this->multipart_boundary . "\r\n" . - sprintf( 'Content-Disposition: form-data; name="%s"', $key ); - - if ( 'chunk' == $key ) { - if ( $data['chunk_gzipped'] ) { - $result .= "; filename=\"chunk.txt.gz\"\r\nContent-Type: application/x-gzip"; - } - else { - $result .= "; filename=\"chunk.txt\"\r\nContent-Type: text/plain;"; - } - } - else { - $result .= "\r\nContent-Type: text/plain; charset=" . get_option( 'blog_charset' ); - } - - $result .= "\r\n\r\n" . $value . "\r\n"; - } - - $result .= "--" . $this->multipart_boundary . "--\r\n"; - - return $result; - } - function is_json( $string, $strict = false ) { $json = @json_decode( $string, true ); if( $strict == true && ! is_array( $json ) ) return false; return ! ( $json == NULL || $json == false ); } - function remote_post( $url, $data, $scope, $args = array(), $expecting_serial = false ) { - $this->set_time_limit(); - - if( function_exists( 'fsockopen' ) && strpos( $url, 'https://' ) === 0 && $scope == 'ajax_prepare_remote_connection' ) { - $url_parts = parse_url( $url ); - $host = $url_parts['host']; - if( $pf = @fsockopen( $host, 443, $err, $err_string, 1 ) ) { - // worked - fclose( $pf ); - } - else { - // failed - $url = substr_replace( $url, 'http', 0, 5 ); - } - } - - $sslverify = ( $this->settings['verify_ssl'] == 1 ? true : false ); - - $default_remote_post_timeout = apply_filters( 'wpmdb_default_remote_post_timeout', 60 * 20 ); - - $args = wp_parse_args( $args, array( - 'timeout' => $default_remote_post_timeout, - 'blocking' => true, - 'sslverify' => $sslverify, - ) ); - - $args['method'] = 'POST'; - $args['body'] = $this->array_to_multipart( $data ); - $args['headers']['Content-Type'] = 'multipart/form-data; boundary=' . $this->multipart_boundary; - $args['headers']['Referer'] = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ); - - $this->attempting_to_connect_to = $url; - - $response = wp_remote_post( $url, $args ); - - if ( ! is_wp_error( $response ) ) { - $response['body'] = trim( $response['body'], "\xef\xbb\xbf" ); - } - - if ( is_wp_error( $response ) ) { - if( strpos( $url, 'https://' ) === 0 && $scope == 'ajax_prepare_remote_connection' ) { - $url = substr_replace( $url, 'http', 0, 5 ); - // needs testing - if( $response = $this->remote_post( $url, $data, $scope, $args, $expecting_serial ) ) { - return $response; - } - else { - return false; - } - } - else if( isset( $response->errors['http_request_failed'][0] ) && strstr( $response->errors['http_request_failed'][0], 'timed out' ) ) { - $this->error = 'The connection to the remote server has timed out, no changes have been committed. (#134 - scope: ' . $scope . ')'; - } - else if ( isset( $response->errors['http_request_failed'][0] ) && ( strstr( $response->errors['http_request_failed'][0], 'Could not resolve host' ) || strstr( $response->errors['http_request_failed'][0], 'couldn\'t connect to host' ) ) ) { - $this->error = 'We could not find: ' . $_POST['url'] . '. Are you sure this is the correct URL?'; - $url_bits = parse_url( $_POST['url'] ); - if( strstr( $_POST['url'], 'dev.' ) || strstr( $_POST['url'], '.dev' ) || ! strstr( $url_bits['host'], '.' ) ) { - $this->error .= '
    It appears that you might be trying to ' . $_POST['intent'] . ( $_POST['intent'] == 'pull' ? ' from' : ' to' ) . ' a local environment. This will not work if this website happens to be located on a remote server, it would be impossible for this server to contact your local environment.'; - } - } - else { - $this->error = 'The connection failed, an unexpected error occurred, please contact support. (#121 - scope: ' . $scope . ')'; - } - $this->log_error( $this->error, $response ); - return false; - } - elseif ( (int) $response['response']['code'] < 200 || (int) $response['response']['code'] > 399 ) { - if( strpos( $url, 'https://' ) === 0 && $scope == 'ajax_prepare_remote_connection' ) { - $url = substr_replace( $url, 'http', 0, 5 ); - // needs testing - if( $response = $this->remote_post( $url, $data, $scope, $args, $expecting_serial ) ) { - return $response; - } - else { - return false; - } - } - else if( $response['response']['code'] == '401' ) { - $this->error = 'The remote site is protected with Basic Authentication. Please enter the username and password above to continue. (401 Unauthorized)'; - $this->log_error( $this->error, $response ); - return false; - } - else { - $this->error = 'Unable to connect to the remote server, please check the connection details - ' . $response['response']['code'] . ' ' . $response['response']['message'] . ' (#129 - scope: ' . $scope . ')'; - $this->log_error( $this->error, $response ); - return false; - } - } - elseif ( $expecting_serial && is_serialized( $response['body'] ) == false ) { - $this->error = 'There was a problem with the AJAX request, we were expecting a serialized response, instead we received:
    ' . htmlentities( $response['body'] ); - $this->log_error( $this->error, $response ); - return false; - } - elseif ( $response['body'] === '0' ) { - $this->error = 'WP Migrate DB Pro does not seem to be installed or active on the remote site. (#131 - scope: ' . $scope . ')'; - $this->log_error( $this->error, $response ); - return false; - } - - return $response['body']; - } - - function log_error( $wpmdb_error, $additional_error_var = false ){ - $error_header = "********************************************\n****** Log date: " . date( 'Y/m/d H:i:s' ) . " ******\n********************************************\n\n"; - $error = $error_header . "WPMDB Error: " . $wpmdb_error . "\n\n"; - if( ! empty( $this->attempting_to_connect_to ) ) { - $error .= "Attempted to connect to: " . $this->attempting_to_connect_to . "\n\n"; - } - if( $additional_error_var !== false ){ - $error .= print_r( $additional_error_var, true ) . "\n\n"; - } - $log = get_option( 'wpmdb_error_log' ); - if( $log ) { - $log = $log . $error; - } - else { - $log = $error; - } - update_option( 'wpmdb_error_log', $log ); - } - function get_sql_dump_info( $migration_type, $info_type ) { if( empty( $this->session_salt ) ) { $this->session_salt = strtolower( wp_generate_password( 5, false, false ) ); @@ -564,6 +358,7 @@ function get_sql_dump_info( $migration_type, $info_type ) { function parse_migration_form_data( $data ) { parse_str( $data, $form_data ); + $this->accepted_fields = apply_filters( 'wpmdb_accepted_profile_fields', $this->accepted_fields ); $form_data = array_intersect_key( $form_data, array_flip( $this->accepted_fields ) ); unset( $form_data['replace_old'][0] ); unset( $form_data['replace_new'][0] ); @@ -594,15 +389,6 @@ function output_log_file() { } } - function open_ssl_enabled() { - if ( defined( 'OPENSSL_VERSION_TEXT' ) ) { - return true; - } - else { - return false; - } - } - function output_diagnostic_info() { global $table_prefix; @@ -697,6 +483,15 @@ function output_diagnostic_info() { } else { _e( 'Disabled', 'wp-app-store' ); } + echo "\r\n"; + + _e( 'set_time_limit()', 'wp-app-store' ); echo ': '; + if ( $this->set_time_limit_available() ) { + _e('Enabled', 'wp-app-store' ); + } else { + _e( 'Disabled', 'wp-app-store' ); + } + echo "\r\n"; echo "\r\n"; @@ -726,7 +521,7 @@ function remove_wp_plugin_dir( $name ) { function fire_migration_complete() { $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'url' ) ); if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { - echo $this->invalid_content_verification_error . ' (#123)'; + echo $this->invalid_content_verification_error . ' (#138)'; exit; } @@ -748,80 +543,96 @@ function get_alter_queries() { } // After table migration, delete old tables and rename new tables removing the temporarily prefix - function ajax_finalize_backup() { + function ajax_finalize_migration() { global $wpdb; - // This particular function can be accessed by non logged in users AND logged in users - if ( ! current_user_can( 'manage_options' ) ) { - $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent', 'url', 'key', 'form_data', 'stage', 'prefix', 'type', 'location' ) ); - if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { - echo $this->invalid_content_verification_error . ' (#123)'; - exit; - } + if ( $_POST['intent'] == 'pull' ) { + $this->finalize_migration(); } + else { + do_action( 'wpmdb_migration_complete', 'push', $_POST['url'] ); + $data = $_POST; + $data['action'] = 'wpmdb_remote_finalize_migration'; + $data['intent'] = 'pull'; + $data['prefix'] = $wpdb->prefix; + $data['type'] = 'push'; + $data['location'] = home_url(); + $data['sig'] = $this->create_signature( $data, $data['key'] ); + $ajax_url = trailingslashit( $_POST['url'] ) . 'wp-admin/admin-ajax.php'; + $response = $this->remote_post( $ajax_url, $data, __FUNCTION__ ); + echo $response; + $this->display_errors(); + } + exit; + } - if ( $_POST['intent'] == 'pull' ) { - $temp_tables = $this->get_tables( 'temp' ); - $sql = "SET FOREIGN_KEY_CHECKS=0;\n"; + function respond_to_remote_finalize_migration() { + $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent', 'url', 'key', 'form_data', 'stage', 'prefix', 'type', 'location', 'tables' ) ); + if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { + echo $this->invalid_content_verification_error . ' (#123)'; + exit; + } + $this->finalize_migration(); + exit; + } - $preserved_options = array( 'wpmdb_settings', 'wpmdb_error_log' ); + function finalize_migration() { + global $wpdb; - $this->form_data = $this->parse_migration_form_data( $_POST['form_data'] ); - if( isset( $this->form_data['keep_active_plugins'] ) ) { - $preserved_options[] = 'active_plugins'; - } + $tables = explode( ',', $_POST['tables'] ); + $temp_tables = array(); + foreach( $tables as $table ) { + $temp_tables[] = $this->temp_prefix . $table; + } - $preserved_options = apply_filters( 'wpmdb_preserved_options', $preserved_options ); + $sql = "SET FOREIGN_KEY_CHECKS=0;\n"; - foreach ( $temp_tables as $table ) { - $sql .= 'DROP TABLE IF EXISTS ' . $this->backquote( substr( $table, strlen( $this->temp_prefix ) ) ) . ';'; - $sql .= "\n"; - $sql .= 'RENAME TABLE ' . $this->backquote( $table ) . ' TO ' . $this->backquote( substr( $table, strlen( $this->temp_prefix ) ) ) . ';'; - $sql .= "\n"; - } + $preserved_options = array( 'wpmdb_settings', 'wpmdb_error_log' ); - $preserved_options_data = $wpdb->get_results( sprintf( "SELECT * FROM %soptions WHERE `option_name` IN ('%s')", $wpdb->prefix, implode( "','", $preserved_options ) ), ARRAY_A ); + $this->form_data = $this->parse_migration_form_data( $_POST['form_data'] ); + if( isset( $this->form_data['keep_active_plugins'] ) ) { + $preserved_options[] = 'active_plugins'; + } - foreach( $preserved_options_data as $option ) { - $sql .= $wpdb->prepare( "DELETE FROM `{$_POST['prefix']}options` WHERE `option_name` = %s;\n", $option['option_name'] ); - $sql .= $wpdb->prepare( "INSERT INTO `{$_POST['prefix']}options` ( `option_id`, `option_name`, `option_value`, `autoload` ) VALUES ( NULL , %s, %s, %s );\n", $option['option_name'], $option['option_value'], $option['autoload'] ); - } + $preserved_options = apply_filters( 'wpmdb_preserved_options', $preserved_options ); - $alter_table_name = $this->get_alter_table_name(); - $sql .= $this->get_alter_queries(); - $sql .= "DROP TABLE IF EXISTS " . $this->backquote( $alter_table_name ) . ";\n"; + foreach ( $temp_tables as $table ) { + $sql .= 'DROP TABLE IF EXISTS ' . $this->backquote( substr( $table, strlen( $this->temp_prefix ) ) ) . ';'; + $sql .= "\n"; + $sql .= 'RENAME TABLE ' . $this->backquote( $table ) . ' TO ' . $this->backquote( substr( $table, strlen( $this->temp_prefix ) ) ) . ';'; + $sql .= "\n"; + } - $this->process_chunk( $sql ); + $preserved_options_data = $wpdb->get_results( sprintf( "SELECT * FROM %soptions WHERE `option_name` IN ('%s')", $wpdb->prefix, implode( "','", $preserved_options ) ), ARRAY_A ); - $type = ( isset( $_POST['type'] ) ? 'push' : 'pull' ); - $location = ( isset( $_POST['location'] ) ? $_POST['location'] : $_POST['url'] ); + foreach( $preserved_options_data as $option ) { + $sql .= $wpdb->prepare( "DELETE FROM `{$_POST['prefix']}options` WHERE `option_name` = %s;\n", $option['option_name'] ); + $sql .= $wpdb->prepare( "INSERT INTO `{$_POST['prefix']}options` ( `option_id`, `option_name`, `option_value`, `autoload` ) VALUES ( NULL , %s, %s, %s );\n", $option['option_name'], $option['option_value'], $option['autoload'] ); + } - if( ! isset( $_POST['location'] ) ) { - $data = array(); - $data['action'] = 'wpmdb_fire_migration_complete'; - $data['url'] = home_url(); - $data['sig'] = $this->create_signature( $data, $_POST['key'] ); - $ajax_url = trailingslashit( $_POST['url'] ) . 'wp-admin/admin-ajax.php'; - $response = $this->remote_post( $ajax_url, $data, __FUNCTION__ ); - echo $response; - $this->display_errors(); - } + $alter_table_name = $this->get_alter_table_name(); + $sql .= $this->get_alter_queries(); + $sql .= "DROP TABLE IF EXISTS " . $this->backquote( $alter_table_name ) . ";\n"; - do_action( 'wpmdb_migration_complete', $type, $location ); - } - else { - do_action( 'wpmdb_migration_complete', 'push', $_POST['url'] ); - $data = $_POST; - $data['intent'] = 'pull'; - $data['prefix'] = $wpdb->prefix; - $data['type'] = 'push'; - $data['location'] = home_url(); - $data['sig'] = $this->create_signature( $data, $data['key'] ); + $this->process_chunk( $sql ); + + $type = ( isset( $_POST['type'] ) ? 'push' : 'pull' ); + $location = ( isset( $_POST['location'] ) ? $_POST['location'] : $_POST['url'] ); + + if( ! isset( $_POST['location'] ) ) { + $data = array(); + $data['action'] = 'wpmdb_fire_migration_complete'; + $data['url'] = home_url(); + $data['sig'] = $this->create_signature( $data, $_POST['key'] ); $ajax_url = trailingslashit( $_POST['url'] ) . 'wp-admin/admin-ajax.php'; $response = $this->remote_post( $ajax_url, $data, __FUNCTION__ ); echo $response; $this->display_errors(); } - exit; + + // flush rewrite rules to prevent 404s and other oddities + flush_rewrite_rules( true ); // true = hard refresh, recreates the .htaccess file + + do_action( 'wpmdb_migration_complete', $type, $location ); } function ajax_process_chunk() { @@ -874,6 +685,11 @@ function process_chunk( $chunk ) { $queries = array_filter( explode( ";\n", $chunk ) ); $wpdb->show_errors(); + if( empty( $wpdb->charset ) ) { + $charset = ( defined( 'DB_CHARSET' ) ? DB_CHARSET : 'utf8' ); + $wpdb->charset = $charset; + $wpdb->set_charset( $wpdb->dbh, $wpdb->charset ); + } foreach( $queries as $query ) { if( false === $wpdb->query( $query ) ) { exit; @@ -881,43 +697,17 @@ function process_chunk( $chunk ) { } } - function create_signature( $data, $key ) { - if ( isset( $data['sig'] ) ) { - unset( $data['sig'] ); - } - $flat_data = implode( '', $data ); - return base64_encode( hash_hmac( 'sha1', $flat_data, $key, true ) ); - } - - function verify_signature( $data, $key ) { - if( empty( $data['sig'] ) ) { - return false; - } - $temp = $data; - $computed_signature = $this->create_signature( $temp, $key ); - return $computed_signature === $data['sig']; - } - - // This the first AJAX end point when a table is about to be migrated / backed up - function ajax_prepare_table_migration() { + function ajax_migrate_table() { global $wpdb; - // Check that the user is valid and is allowed to perform a table migration - if ( ! current_user_can( 'manage_options' ) ) { - $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent', 'url', 'key', 'table', 'form_data', 'stage', 'bottleneck', 'prefix', 'current_row', 'dump_filename', 'last_table', 'gzip', 'primary_keys' ) ); - $filtered_post['primary_keys'] = stripslashes( $filtered_post['primary_keys'] ); - if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { - echo $this->invalid_content_verification_error . ' (#119)'; - exit; - } - } $this->form_data = $this->parse_migration_form_data( $_POST['form_data'] ); + // checks if we're performing a backup, if so, continue with the backup and exit immediately after if ( $_POST['stage'] == 'backup' && $_POST['intent'] != 'savefile' ) { // if performing a push we need to backup the REMOTE machine's DB if ( $_POST['intent'] == 'push' ) { $data = $_POST; - // flip the intent so we can trigger the else statement below + $data['action'] = 'wpmdb_backup_remote_table'; $data['intent'] = 'pull'; $ajax_url = trailingslashit( $_POST['url'] ) . 'wp-admin/admin-ajax.php'; $data['primary_keys'] = stripslashes( $data['primary_keys'] ); @@ -927,21 +717,8 @@ function ajax_prepare_table_migration() { echo $response; } else { - if ( isset( $this->form_data['gzip_file'] ) ) { - unset( $this->form_data['gzip_file'] ); - } - $this->maximum_chunk_size = $this->get_bottleneck(); - $sql_dump_file_name = $this->get_upload_info( 'path' ) . DS; - $sql_dump_file_name .= $this->format_dump_name( $_POST['dump_filename'] ); - $file_created = file_exists( $sql_dump_file_name ); - $this->fp = $this->open( $sql_dump_file_name ); - if ( $file_created == false ) { - $this->db_backup_header(); + $this->handle_table_backup(); } - $this->backup_table( $_POST['table'] ); - $this->display_errors(); - $this->close( $this->fp ); - } exit; } @@ -961,7 +738,7 @@ function ajax_prepare_table_migration() { if ( $_POST['intent'] == 'savefile' ) { $this->fp = $this->open( $sql_dump_file_name ); } - $this->backup_table( $_POST['table'] ); + $this->export_table( $_POST['table'] ); $this->display_errors(); if ( $_POST['intent'] == 'savefile' ) { $this->close( $this->fp ); @@ -971,6 +748,9 @@ function ajax_prepare_table_migration() { $data = $_POST; $data['action'] = 'wpmdb_process_pull_request'; $data['pull_limit'] = $this->get_sensible_pull_limit(); + if( is_multisite() ) { + $data['path_current_site'] = $this->get_path_current_site(); + } $data['prefix'] = $wpdb->prefix; if ( isset( $data['sig'] ) ) { unset( $data['sig'] ); @@ -1007,6 +787,61 @@ function ajax_prepare_table_migration() { exit; } + function respond_to_backup_remote_table() { + $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent', 'url', 'key', 'table', 'form_data', 'stage', 'bottleneck', 'prefix', 'current_row', 'dump_filename', 'last_table', 'gzip', 'primary_keys' ) ); + $filtered_post['primary_keys'] = stripslashes( $filtered_post['primary_keys'] ); + if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { + echo $this->invalid_content_verification_error . ' (#137)'; + exit; + } + + $this->form_data = $this->parse_migration_form_data( $_POST['form_data'] ); + $this->handle_table_backup(); + } + + function handle_table_backup() { + if ( isset( $this->form_data['gzip_file'] ) ) { + unset( $this->form_data['gzip_file'] ); + } + $this->maximum_chunk_size = $this->get_bottleneck(); + $sql_dump_file_name = $this->get_upload_info( 'path' ) . DS; + $sql_dump_file_name .= $this->format_dump_name( $_POST['dump_filename'] ); + $file_created = file_exists( $sql_dump_file_name ); + $this->fp = $this->open( $sql_dump_file_name ); + if ( $file_created == false ) { + $this->db_backup_header(); + } + $this->export_table( $_POST['table'] ); + $this->display_errors(); + $this->close( $this->fp ); + } + + function respond_to_process_pull_request() { + $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent', 'url', 'key', 'table', 'form_data', 'stage', 'bottleneck', 'prefix', 'current_row', 'dump_filename', 'pull_limit', 'last_table', 'gzip', 'primary_keys', 'path_current_site' ) ); + + // verification will fail unless we strip slashes on primary_keys and form_data + $filtered_post['primary_keys'] = stripslashes( $filtered_post['primary_keys'] ); + $filtered_post['form_data'] = stripslashes( $filtered_post['form_data'] ); + if( isset( $filtered_post['path_current_site'] ) ) { + $filtered_post['path_current_site'] = stripslashes( $filtered_post['path_current_site'] ); + } + + if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { + echo $this->invalid_content_verification_error . ' (#124)'; + exit; + } + + if ( $this->settings['allow_pull'] != true ) { + echo 'The connection succeeded but the remote site is configured to reject pull connections. You can change this in the "settings" tab on the remote site. (#132)'; + exit; + } + + $this->maximum_chunk_size = $_POST['pull_limit']; + $this->export_table( $_POST['table'] ); + $this->display_errors(); + exit; + } + // Occurs right before the first table is migrated / backed up during the migration process // Does a quick check to make sure the verification string is valid and also opens / creates files for writing to (if required) function ajax_initiate_migration() { @@ -1040,7 +875,7 @@ function ajax_initiate_migration() { else { // does one last check that our verification string is valid $data = array( - 'action' => 'wpmdb_respond_initiate_migration', + 'action' => 'wpmdb_remote_initiate_migration', 'intent' => $_POST['intent'], 'form_data' => $_POST['form_data'], ); @@ -1081,8 +916,8 @@ function ajax_initiate_migration() { exit; } - // End point for the above AJAX call, ensures that the verification string is valid before continuing with the migration - function ajax_respond_initiate_migration() { + // End point for the above remote_post call, ensures that the verification string is valid before continuing with the migration + function respond_to_remote_initiate_migration() { $return = array(); $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent', 'form_data' ) ); if ( $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { @@ -1161,9 +996,9 @@ function ajax_reset_api_key() { // AJAX endpoint for when the user pastes into the connection info box (or when they click "connect") // Responsible for contacting the remote website and retrieving info and testing the verification string - function ajax_prepare_remote_connection() { + function ajax_verify_connection_to_remote_site() { $data = array( - 'action' => 'wpmdb_establish_remote_connection', + 'action' => 'wpmdb_verify_connection_to_remote_site', 'intent' => $_POST['intent'] ); @@ -1182,7 +1017,7 @@ function ajax_prepare_remote_connection() { exit; } - $response = unserialize( $response ); + $response = unserialize( trim( $response ) ); if ( isset( $response['error'] ) && $response['error'] == 1 ) { $return = array( 'wpmdb_error' => 1, 'body' => $response['message'] ); @@ -1197,13 +1032,8 @@ function ajax_prepare_remote_connection() { exit; } - function format_table_sizes( $size ) { - $size *= 1024; - return size_format( $size ); - } - - // AJAX end point for the above AJAX call, returns table information, absolute file path, table prefix, etc - function ajax_establish_remote_connection() { + // End point for the above remote_post call, returns table information, absolute file path, table prefix, etc + function respond_to_verify_connection_to_remote_site() { global $wpdb; $return = array(); @@ -1223,7 +1053,6 @@ function ajax_establish_remote_connection() { exit; } - $plugin_info = get_plugin_data( $this->plugin_file_path, false, false ); $return['tables'] = $this->get_tables(); $return['prefixed_tables'] = $this->get_tables( 'prefix' ); $return['table_sizes'] = $this->get_table_sizes(); @@ -1234,19 +1063,23 @@ function ajax_establish_remote_connection() { $return['prefix'] = $wpdb->prefix; $return['bottleneck'] = $this->get_bottleneck(); $return['error'] = 0; - $return['plugin_version'] = $plugin_info['Version']; - $return['domain'] = ( defined( 'DOMAIN_CURRENT_SITE' ) ? DOMAIN_CURRENT_SITE : '' ); + $return['plugin_version'] = $this->get_installed_version(); + $return['domain'] = $this->get_domain_current_site(); + $return['path_current_site'] = $this->get_path_current_site(); $return['uploads_dir'] = $this->get_short_uploads_dir(); $return['gzip'] = ( $this->gzip() ? '1' : '0' ); + $return['post_types'] = $this->get_post_types(); + $return['write_permissions'] = ( is_writeable( $this->get_upload_info( 'path' ) ) ? '1' : '0' ); + $return['upload_dir_long'] = $this->get_upload_info( 'path' ); + $return = apply_filters( 'wpmdb_establish_remote_connection_data', $return ); echo serialize( $return ); exit; } - // Utility debugging function - function printer( $debug ) { - echo '
    ' . print_r( $debug, true ) . '
    '; + function format_table_sizes( $size ) { + $size *= 1024; + return size_format( $size ); } - // Generates our secret key function generate_key() { $keyset = 'abcdefghijklmnopqrstuvqxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/'; @@ -1268,7 +1101,36 @@ function get_tables( $scope = 'regular' ) { } $clean_tables[] = $table[0]; } - return $clean_tables; + return apply_filters( 'wpmdb_tables', $clean_tables, $scope ); + } + + function get_post_types() { + global $wpdb; + + if( is_multisite() ) { + $tables = $this->get_tables(); + $sql = "SELECT `post_type` FROM `{$wpdb->prefix}posts` "; + foreach( $tables as $table ) { + if( 0 == preg_match( '/' . $wpdb->prefix . '[0-9]+_posts/', $table ) ) continue; + $blog_id = str_replace( array( $wpdb->prefix, '_posts' ), array( '', '' ), $table ); + $sql .= "UNION SELECT `post_type` FROM `{$wpdb->prefix}" . $blog_id . "_posts` "; + } + $sql .= ";"; + $post_types = $wpdb->get_results( $sql, ARRAY_A ); + } + else { + $post_types = $wpdb->get_results( + "SELECT DISTINCT `post_type` + FROM `{$wpdb->prefix}posts` + WHERE 1;", ARRAY_A + ); + } + + $return = array( 'revision' ); + foreach( $post_types as $post_type ) { + $return[] = $post_type['post_type']; + } + return apply_filters( 'wpmdb_post_types', array_unique( $return ) ); } // Retrieves the specified profile, if -1, returns the default profile @@ -1310,11 +1172,7 @@ function get_table_sizes( $scope = 'regular' ) { $return[$result['table']] = $result['size']; } - return $return; - } - - function template( $template ) { - include $this->template_dir . $template . '.php'; + return apply_filters( 'wpmdb_table_sizes', $return, $scope ); } function get_post_max_size() { @@ -1341,8 +1199,8 @@ function get_bottleneck( $type = 'regular' ) { $suhosin_post_limit = false; if ( function_exists( 'ini_get' ) ) { - $suhosin_request_limit = ini_get( 'suhosin.request.max_value_length' ); - $suhosin_post_limit = ini_get( 'suhosin.post.max_value_length' ); + $suhosin_request_limit = $this->return_bytes( ini_get( 'suhosin.request.max_value_length' ) ); + $suhosin_post_limit = $this->return_bytes( ini_get( 'suhosin.post.max_value_length' ) ); } if ( $suhosin_request_limit && $suhosin_post_limit ) { @@ -1364,28 +1222,6 @@ function get_bottleneck( $type = 'regular' ) { return apply_filters( 'wpmdb_bottleneck', $calculated_bottleneck ); } - function ajax_process_pull_request() { - $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent', 'url', 'key', 'table', 'form_data', 'stage', 'bottleneck', 'prefix', 'current_row', 'dump_filename', 'pull_limit', 'last_table', 'gzip', 'primary_keys' ) ); - - // verification will fail unless we strip slashes on primary_keys - $filtered_post['primary_keys'] = stripslashes( $filtered_post['primary_keys'] ); - - if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { - echo $this->invalid_content_verification_error . ' (#124)'; - exit; - } - - if ( $this->settings['allow_pull'] != true ) { - echo 'The connection succeeded but the remote site is configured to reject pull connections. You can change this in the "settings" tab on the remote site. (#132)'; - exit; - } - - $this->maximum_chunk_size = $_POST['pull_limit']; - $this->backup_table( $_POST['table'] ); - $this->display_errors(); - exit; - } - function format_dump_name( $dump_name ) { $extension = '.sql'; $dump_name = sanitize_file_name( $dump_name ); @@ -1402,11 +1238,17 @@ function options_page() {

    Migrate DB Pro

    + + + + -
    +

    PHP Safe Mode Enabled — We do not officially support running this plugin in @@ -1425,7 +1267,7 @@ function options_page() { } ?> -

    \ No newline at end of file +
    diff --git a/wp-migrate-db-pro.php b/wp-migrate-db-pro.php old mode 100644 new mode 100755 From e4e4bf312029a5fecbe2a11c3dc183f7c9dc9529 Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Sun, 29 Dec 2013 14:31:51 -0600 Subject: [PATCH 07/52] finish removing "pro" suffix --- class/{wpmdbpro-addon.php => wpmdb-addon.php} | 8 ++-- class/{wpmdbpro-base.php => wpmdb-base.php} | 6 +-- class/{wpmdbpro.php => wpmdb.php} | 40 +++++++++---------- wp-migrate-db-pro.php => wp-migrate-db.php | 16 ++++---- 4 files changed, 35 insertions(+), 35 deletions(-) rename class/{wpmdbpro-addon.php => wpmdb-addon.php} (88%) rename class/{wpmdbpro-base.php => wpmdb-base.php} (98%) rename class/{wpmdbpro.php => wpmdb.php} (97%) rename wp-migrate-db-pro.php => wp-migrate-db.php (71%) diff --git a/class/wpmdbpro-addon.php b/class/wpmdb-addon.php similarity index 88% rename from class/wpmdbpro-addon.php rename to class/wpmdb-addon.php index 5a96a96..c414b60 100644 --- a/class/wpmdbpro-addon.php +++ b/class/wpmdb-addon.php @@ -1,5 +1,5 @@ get_installed_version( 'wp-migrate-db-pro/wp-migrate-db-pro.php' ); + $wpmdb_pro_version = $this->get_installed_version( 'wp-migrate-db/wp-migrate-db.php' ); $result = version_compare( $wpmdb_pro_version, $version_required, '>=' ); $this->version_required = $version_required; if( false == $result ) $this->hook_version_requirement_actions(); @@ -35,11 +35,11 @@ function version_requirement_warning() { ?>

    Update Requiredget_plugin_name(); $required = $this->version_required; $installed = $this->get_installed_version( $wpmdb_basename ); - $update = wp_nonce_url( network_admin_url( 'update.php?action=upgrade-plugin&plugin=wp-migrate-db-pro%2Fwp-migrate-db-pro.php' ), 'upgrade-plugin_' . $wpmdb_basename ); + $update = wp_nonce_url( network_admin_url( 'update.php?action=upgrade-plugin&plugin=wp-migrate-db%2Fwp-migrate-db.php' ), 'upgrade-plugin_' . $wpmdb_basename ); echo sprintf( 'The version of %s you have installed, requires version %s of WP Migrate DB. You currently have %s installed. Update Now', $addon_name, $required, $installed, $update ); ?>

    diff --git a/class/wpmdbpro-base.php b/class/wpmdb-base.php similarity index 98% rename from class/wpmdbpro-base.php rename to class/wpmdb-base.php index b9f27e9..36ad718 100755 --- a/class/wpmdbpro-base.php +++ b/class/wpmdb-base.php @@ -1,5 +1,5 @@ plugin_title = str_ireplace( array( 'db', 'wp' ), array( 'DB', 'WP' ), $this->plugin_title ); if ( is_multisite() ) { - $this->plugin_base = 'settings.php?page=wp-migrate-db-pro'; + $this->plugin_base = 'settings.php?page=wp-migrate-db'; } else { - $this->plugin_base = 'tools.php?page=wp-migrate-db-pro'; + $this->plugin_base = 'tools.php?page=wp-migrate-db'; } } diff --git a/class/wpmdbpro.php b/class/wpmdb.php similarity index 97% rename from class/wpmdbpro.php rename to class/wpmdb.php index bc64142..4740e38 100755 --- a/class/wpmdbpro.php +++ b/class/wpmdb.php @@ -1,5 +1,5 @@ plugin_base = 'settings.php?page=wp-migrate-db-pro'; + $this->plugin_base = 'settings.php?page=wp-migrate-db'; } else { add_action( 'admin_menu', array( $this, 'admin_menu' ) ); - $this->plugin_base = 'tools.php?page=wp-migrate-db-pro'; + $this->plugin_base = 'tools.php?page=wp-migrate-db'; } } @@ -202,7 +202,7 @@ function get_upload_info( $type = 'path' ) { $upload_dir_name = apply_filters( 'wpmdb_upload_dir_name', 'wp-migrate-db' ); if( ! file_exists( $upload_dir['basedir'] . DS . $upload_dir_name ) ) { - $url = wp_nonce_url( $this->plugin_base, 'wp-migrate-db-pro-nonce' ); + $url = wp_nonce_url( $this->plugin_base, 'wp-migrate-db-nonce' ); if( false === @mkdir( $upload_dir['basedir'] . DS . $upload_dir_name, 0755 ) ) { return $upload_info[$type]; @@ -251,7 +251,7 @@ function parse_migration_form_data( $data ) { } function plugin_action_links( $links ) { - $link = sprintf( '%s', network_admin_url( $this->plugin_base ), __( 'Settings', 'wp-migrate-db-pro' ) ); + $link = sprintf( '%s', network_admin_url( $this->plugin_base ), __( 'Settings', 'wp-migrate-db' ) ); array_unshift( $links, $link ); return $links; } @@ -1121,7 +1121,7 @@ function options_page() {
    -

    Migrate DB Pro

    +

    Migrate DB

    @@ -1354,7 +1354,7 @@ function export_table( $table ) { if ( $this->form_data['action'] == 'savefile' || $_POST['stage'] == 'backup' ) { $this->stow( "\n\n" ); $this->stow( "#\n" ); - $this->stow( "# " . sprintf( __( 'Delete any existing table %s', 'wp-migrate-db-pro' ), $this->backquote( $table ) ) . "\n" ); + $this->stow( "# " . sprintf( __( 'Delete any existing table %s', 'wp-migrate-db' ), $this->backquote( $table ) ) . "\n" ); $this->stow( "#\n" ); $this->stow( "\n" ); $this->stow( "DROP TABLE IF EXISTS " . $this->backquote( $table ) . ";\n" ); @@ -1368,7 +1368,7 @@ function export_table( $table ) { if ( $this->form_data['action'] == 'savefile' || $_POST['stage'] == 'backup' ) { $this->stow( "\n\n" ); $this->stow( "#\n" ); - $this->stow( "# " . sprintf( __( 'Table structure of table %s', 'wp-migrate-db-pro' ), $this->backquote( $table ) ) . "\n" ); + $this->stow( "# " . sprintf( __( 'Table structure of table %s', 'wp-migrate-db' ), $this->backquote( $table ) ) . "\n" ); $this->stow( "#\n" ); $this->stow( "\n" ); } @@ -1407,7 +1407,7 @@ function export_table( $table ) { if ( $this->form_data['action'] == 'savefile' || $_POST['stage'] == 'backup' ) { $this->stow( "\n\n" ); $this->stow( "#\n" ); - $this->stow( '# ' . sprintf( __( 'Data contents of table %s', 'wp-migrate-db-pro' ), $this->backquote( $table ) ) . "\n" ); + $this->stow( '# ' . sprintf( __( 'Data contents of table %s', 'wp-migrate-db' ), $this->backquote( $table ) ) . "\n" ); $this->stow( "#\n" ); } } @@ -1673,7 +1673,7 @@ function export_table( $table ) { if ( $this->form_data['action'] == 'savefile' || $_POST['stage'] == 'backup' ) { $this->stow( "\n" ); $this->stow( "#\n" ); - $this->stow( "# " . sprintf( __( 'End of data contents of table %s', 'wp-migrate-db-pro' ), $this->backquote( $table ) ) . "\n" ); + $this->stow( "# " . sprintf( __( 'End of data contents of table %s', 'wp-migrate-db' ), $this->backquote( $table ) ) . "\n" ); $this->stow( "# --------------------------------------------------------\n" ); $this->stow( "\n" ); @@ -1769,11 +1769,11 @@ function recursive_unserialize_replace( $data, $serialized = false, $parent_seri function db_backup_header() { $charset = ( defined( 'DB_CHARSET' ) ? DB_CHARSET : 'utf8' ); - $this->stow( "# " . __( 'WordPress MySQL database migration', 'wp-migrate-db-pro' ) . "\n", false ); + $this->stow( "# " . __( 'WordPress MySQL database migration', 'wp-migrate-db' ) . "\n", false ); $this->stow( "#\n", false ); - $this->stow( "# " . sprintf( __( 'Generated: %s', 'wp-migrate-db-pro' ), date( "l j. F Y H:i T" ) ) . "\n", false ); - $this->stow( "# " . sprintf( __( 'Hostname: %s', 'wp-migrate-db-pro' ), DB_HOST ) . "\n", false ); - $this->stow( "# " . sprintf( __( 'Database: %s', 'wp-migrate-db-pro' ), $this->backquote( DB_NAME ) ) . "\n", false ); + $this->stow( "# " . sprintf( __( 'Generated: %s', 'wp-migrate-db' ), date( "l j. F Y H:i T" ) ) . "\n", false ); + $this->stow( "# " . sprintf( __( 'Hostname: %s', 'wp-migrate-db' ), DB_HOST ) . "\n", false ); + $this->stow( "# " . sprintf( __( 'Database: %s', 'wp-migrate-db' ), $this->backquote( DB_NAME ) ) . "\n", false ); $this->stow( "# --------------------------------------------------------\n\n", false ); $this->stow( "/*!40101 SET NAMES $charset */;\n\n", false ); } @@ -1899,12 +1899,12 @@ function sql_addslashes( $a_string = '', $is_like = false ) { } function network_admin_menu() { - $hook_suffix = add_submenu_page( 'settings.php', 'Migrate DB Pro', 'Migrate DB Pro', 'manage_network_options', 'wp-migrate-db-pro', array( $this, 'options_page' ) ); + $hook_suffix = add_submenu_page( 'settings.php', 'Migrate DB', 'Migrate DB', 'manage_network_options', 'wp-migrate-db', array( $this, 'options_page' ) ); $this->after_admin_menu( $hook_suffix ); } function admin_menu() { - $hook_suffix = add_management_page( 'Migrate DB Pro', 'Migrate DB Pro', 'export', 'wp-migrate-db-pro', array( $this, 'options_page' ) ); + $hook_suffix = add_management_page( 'Migrate DB', 'Migrate DB', 'export', 'wp-migrate-db', array( $this, 'options_page' ) ); $this->after_admin_menu( $hook_suffix ); } @@ -1940,18 +1940,18 @@ function load_assets() { $plugins_url = trailingslashit( plugins_url() ) . trailingslashit( $this->plugin_slug ); $src = $plugins_url . 'asset/css/styles.css'; - wp_enqueue_style( 'wp-migrate-db-pro-styles', $src, array(), $this->get_installed_version() ); + wp_enqueue_style( 'wp-migrate-db-styles', $src, array(), $this->get_installed_version() ); $src = $plugins_url . 'asset/js/common.js'; - wp_enqueue_script( 'wp-migrate-db-pro-common', $src, NULL, $this->get_installed_version(), true ); + wp_enqueue_script( 'wp-migrate-db-common', $src, NULL, $this->get_installed_version(), true ); $src = $plugins_url . 'asset/js/hook.js'; - wp_enqueue_script( 'wp-migrate-db-pro-hook', $src, NULL, $this->get_installed_version(), true ); + wp_enqueue_script( 'wp-migrate-db-hook', $src, NULL, $this->get_installed_version(), true ); do_action( 'wpmdb_load_assets' ); $src = $plugins_url . 'asset/js/script.js'; - wp_enqueue_script( 'wp-migrate-db-pro-script', $src, array( 'jquery' ), $this->get_installed_version(), true ); + wp_enqueue_script( 'wp-migrate-db-script', $src, array( 'jquery' ), $this->get_installed_version(), true ); wp_enqueue_script('jquery'); wp_enqueue_script('jquery-ui-core'); diff --git a/wp-migrate-db-pro.php b/wp-migrate-db.php similarity index 71% rename from wp-migrate-db-pro.php rename to wp-migrate-db.php index 3abbc0d..fd438f1 100755 --- a/wp-migrate-db-pro.php +++ b/wp-migrate-db.php @@ -1,7 +1,7 @@ Date: Sun, 29 Dec 2013 14:54:23 -0600 Subject: [PATCH 08/52] rename & reorganize readme move license into separate file add a prettier donate link remove the changelog - pretty outdated --- LICENSE | 339 +++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 32 +++++ readme.txt | 94 --------------- 3 files changed, 371 insertions(+), 94 deletions(-) create mode 100644 LICENSE create mode 100755 README.md delete mode 100755 readme.txt diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d7f1051 --- /dev/null +++ b/LICENSE @@ -0,0 +1,339 @@ +GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {description} + Copyright (C) {year} {fullname} + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + {signature of Ty Coon}, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/README.md b/README.md new file mode 100755 index 0000000..839ce25 --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +#WP Migrate DB +Exports your database, does a find and replace on URLs and file paths, then allows you to save it to your computer. + +Donate [here](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5VPMGLLK94XJC) to support [bradt](https://github.com/bradt), the original author of [WP Migrate DB](https://github.com/bradt/wp-migrate-db). And check out [WP Migrate DB Pro](https://deliciousbrains.com/wp-migrate-db-pro/pricing/) for a variant of the plugin that has dedicated customer support. + +##Description +WP Migrate DB exports your database as a MySQL data dump (much like phpMyAdmin), does a find and replace on URLs and file paths, then allows you to save it to your computer. It is perfect for developers who develop locally and need to move their Wordpress site to a staging or production server. + +It even takes into account serialized data and updates the string length values. + +Example: s:5:"hello" becomes s:11:"hello world" + +##Installation +1. Use WordPress' built-in installer +2. Access the WP Migrate DB menu option under Tools + +##Help Videos + +###Feature Walkthrough +http://www.youtube.com/watch?v=SlfSuuePYaQ + +A brief walkthrough of the WP Migrate DB plugin showing all of the different options and explaining them. + +###Pulling Live Data Into Your Local Development Environment +http://www.youtube.com/watch?v=IFdHIpf6jjc + +This screencast demonstrates how you can pull data from a remote, live WordPress install and update the data in your local development environment. + +###Pushing Local Development Data to a Staging Environment +http://www.youtube.com/watch?v=FjTzNqAlQE0 + +This screencast demonstrates how you can push a local WordPress database you've been using for development to a staging environment. diff --git a/readme.txt b/readme.txt deleted file mode 100755 index 2fdf36e..0000000 --- a/readme.txt +++ /dev/null @@ -1,94 +0,0 @@ -=== WP Migrate DB === -Contributors: bradt -Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5VPMGLLK94XJC -Tags: database, migrate, backup, mysql -Requires at least: 2.0.3 -Tested up to: 3.5 -Stable tag: 0.4.3 -License: GPLv2 - -Exports your database, does a find and replace on URLs and file paths, then allows you to save it to your computer. - -== Description == - -WP Migrate DB exports your database as a MySQL data dump (much like phpMyAdmin), does a find and replace on URLs and file paths, then allows you to save it to your computer. It is perfect for developers who develop locally and need to move their Wordpress site to a staging or production server. - -It even takes into account serialized data and updates the string length values. - -Example: s:5:"hello" becomes s:11:"hello world" - -[**Contribute on Github**](https://github.com/bradt/wp-migrate-db) - -== Installation == - -1. Use WordPress' built-in installer -2. Access the WP Migrate DB menu option under Tools - -== Screenshots == - -1. Main screen -2. Saving the exported database - -== Changelog == - -= 0.4.3 - 2012-12-18 = -* Fixed deprecated error notices when debug mode is on -* Bug fix: [Exports views as tables](https://github.com/bradt/wp-migrate-db/issues/3) -* Compatibility tested with WordPress 3.5 - -= 0.4.2 - 2012-09-13 = -* Moved screenshots to /assets folder and updated them to support retina -* Added sidebar including author profile and survey to gauge interest for a pro version - -= 0.4.1 - 2012-08-15 = -* Removed WP App Store installer - not allowed in WP.org repo - -= 0.4 - 2012-08-07 = -* New: More than 4x faster than version 0.3 due to find & replace improvements -* New: Option to turn off replacing GUIDs -* New: Option to exclude spam comments and post revisions from the export -* New: Option to save file with gzip compression -* New: Added date and time to file names -* New: Display path to SQL file on the server -* New: WP App Store installer integration -* Bug fix: Notices and warnings displayed when WP_DEBUG is on - -= 0.3 - 2011-12-16 = -* Bug fix: [Null formatting error](http://plugins.trac.wordpress.org/ticket/1430) -* Bug fix: [Deprecated capability](http://plugins.trac.wordpress.org/ticket/1431) -* Bug fix: Serialized string lengths incorrect when string contains double quotes - -= 0.2.2 - 2011-09-23 = -* Bug fix: [Breaks Export](http://wordpress.org/support/topic/plugin-wp-migrate-db-breaks-export?replies=1) - -= 0.2.1 - 2009-12-13 = -* Moved to Wordpress.org hosting - -= 0.2 - 2009-04-03 = -* Moved menu link from "Settings" to "Tools" -* The random string of characters no longer appears in the filename on save. - -= 0.1 - 2009-03-20 = -* First release - -== Upgrade Notice == - -= 0.4 = -Runs export over 4x faster and adds some nice new features often requested. Upgrade recommended. - -= 0.2.2 = -This version fixes a bug that breaks the WordPress core export feature. It is highly recommended that everyone upgrade. - -== Help Videos == - -Feature Walkthrough -http://www.youtube.com/watch?v=SlfSuuePYaQ -A brief walkthrough of the WP Migrate DB plugin showing all of the different options and explaining them. - -Pulling Live Data Into Your Local Development Environment -http://www.youtube.com/watch?v=IFdHIpf6jjc -This screencast demonstrates how you can pull data from a remote, live WordPress install and update the data in your local development environment. - -Pushing Local Development Data to a Staging Environment -http://www.youtube.com/watch?v=FjTzNqAlQE0 -This screencast demonstrates how you can push a local WordPress database you've been using for development to a staging environment. From bd9eacff6d7a8863752c752bc3dc2f1f8b887e52 Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Sun, 29 Dec 2013 15:42:32 -0600 Subject: [PATCH 09/52] add a screenshot --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 839ce25..8281c43 100755 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ Exports your database, does a find and replace on URLs and file paths, then allo Donate [here](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5VPMGLLK94XJC) to support [bradt](https://github.com/bradt), the original author of [WP Migrate DB](https://github.com/bradt/wp-migrate-db). And check out [WP Migrate DB Pro](https://deliciousbrains.com/wp-migrate-db-pro/pricing/) for a variant of the plugin that has dedicated customer support. + + ##Description WP Migrate DB exports your database as a MySQL data dump (much like phpMyAdmin), does a find and replace on URLs and file paths, then allows you to save it to your computer. It is perfect for developers who develop locally and need to move their Wordpress site to a staging or production server. From cccea5fc86e7f407a0643a0e631a295ba789c5c7 Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Sun, 29 Dec 2013 18:39:20 -0600 Subject: [PATCH 10/52] update the readme & use github-updater for updates --- README.md | 30 ++++++++++++++++++++++++------ wp-migrate-db.php | 1 + 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 8281c43..dcbc0ec 100755 --- a/README.md +++ b/README.md @@ -1,20 +1,38 @@ #WP Migrate DB -Exports your database, does a find and replace on URLs and file paths, then allows you to save it to your computer. +WP Migrate DB eliminates the manual work of migrating a WP database. Copy your db from one WP install to another with a single-click in your dashboard. Especially handy for syncing a local development database with a live site. Donate [here](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5VPMGLLK94XJC) to support [bradt](https://github.com/bradt), the original author of [WP Migrate DB](https://github.com/bradt/wp-migrate-db). And check out [WP Migrate DB Pro](https://deliciousbrains.com/wp-migrate-db-pro/pricing/) for a variant of the plugin that has dedicated customer support. ##Description -WP Migrate DB exports your database as a MySQL data dump (much like phpMyAdmin), does a find and replace on URLs and file paths, then allows you to save it to your computer. It is perfect for developers who develop locally and need to move their Wordpress site to a staging or production server. +WP Migrate DB exports your database as a MySQL data dump (much like phpMyAdmin), does a find and replace on URLs and file paths, then allows you to save it to your computer, or send it directly to another WordPress instance. It is perfect for developers who develop locally and need to move their WordPress site to a staging or production server. -It even takes into account serialized data and updates the string length values. +###Pull: Quickly Replace a Local DB with a Remote DB +Let's say you're developing locally but need the latest data from the live database. With WP Migrate DB installed on both sites, you can quickly and easily pull the live database down and replace your local database with a few clicks. -Example: s:5:"hello" becomes s:11:"hello world" +###Push: Easily Replace a Remote DB with a Local DB +Let's say you have a new feature to add to a site that's been live for a while. You pull down a fresh copy of the live database and start hacking. When the feature is complete, you push your local database to the staging site with your changes so the client can review before making the feature live. How's that for a workflow? + +###Save Time with Automatic Find & Replace +When migrating a WordPress site, URLs in the content, widgets, menus, etc need to be updated to the new site's URL. Doing this manually is annoying, time consuming, and can be very frustrating when dealing with serialized data (like widgets). WP Migrate DB does all of this for you. + +###Convenient Database Export +In addition to pulling & pushing, in just a couple of clicks you can save an SQL file of your database to your computer. No need to drop into ssh or phpMyAdmin. + +###Select the Tables You Want to Migrate +WP Migrate DB gives you control over which database tables are migrated. Have a huge stats table you'd rather not migrate? Deselect it. Easy. + +###Stress Tested on Massive Databases +Have a huge database? No problem. We've tested migration of tables with over 100MB of data. + +###Intelligently Detects Environment Limitations +WP Migrate DB analyses both the remote and local environments to detect limitations and optimize performance. For example, we detect MySQL's `max_allowed_packet_size` setting and adjust how much SQL we execute at a time. Not only does this avoid failure, but allows us to increase performance. ##Installation -1. Use WordPress' built-in installer -2. Access the WP Migrate DB menu option under Tools +1. Install [github-updater](https://github.com/afragen/github-updater) by downloading the latest zip [here](https://github.com/afragen/github-updater/releases). We rely on this plugin for updating WP Migrate DB directly from this git repo. +2. Install WP Migrate DB by downloading the latest zip [here](https://github.com/slang800/wp-migrate-db/releases). Both github-updater and WP Migrate DB will now download their own updates automatically, so you will never need to go through that tedious zip downloading again. +3. Access the WP Migrate DB menu option under Tools ##Help Videos diff --git a/wp-migrate-db.php b/wp-migrate-db.php index fd438f1..50fbf9c 100755 --- a/wp-migrate-db.php +++ b/wp-migrate-db.php @@ -6,6 +6,7 @@ Author: Delicious Brains Version: 1.3 Author URI: http://deliciousbrains.com +GitHub Plugin URI: slang800/wp-migrate-db */ if ( version_compare( PHP_VERSION, '5.2', '<' ) ) { From f3c75c545237a7867960e0db0236dfd05e842cb6 Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Mon, 30 Dec 2013 15:10:17 -0600 Subject: [PATCH 11/52] explain the connection to WP Migrate DB Pro --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index dcbc0ec..1ffbbdd 100755 --- a/README.md +++ b/README.md @@ -50,3 +50,11 @@ This screencast demonstrates how you can pull data from a remote, live WordPress http://www.youtube.com/watch?v=FjTzNqAlQE0 This screencast demonstrates how you can push a local WordPress database you've been using for development to a staging environment. + +##Isn't this the same as WP Migrate DB Pro? +No, of course not, don't be silly. I took out the license verification code, a really shady looking PressTrends reporter, and tab for installing the Media Files addon before I published it. Release 1.3 was the same as [WP Migrate DB Pro](https://deliciousbrains.com/wp-migrate-db-pro), but I've made several improvements since then. + +Also, because this plugin is free I'm not _obligated_ to help you like [bradt](https://github.com/bradt) is if you purchased WP Migrate DB Pro. Any help that I give is just because I'm a nice person and I enjoy helping people. Also, I only offer support through the public [issues manager](https://github.com/slang800/wp-migrate-db/issues). If you're an agency and need support at the drop of a hat, buy the plugin from bradt. + +##Is this Illegal? +**No.** Just because this is based on the paid-for WP Migrate DB Pro, it doesn't mean I can't release it. WP Migrate DB Pro is released under GPLv2, a copyleft license that guarantees my freedom (and the freedom of all users) to copy, distribute, and/or modify this software. From bac872b5a641d515a884d1570f0581e4c03c7926 Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Mon, 30 Dec 2013 16:07:10 -0600 Subject: [PATCH 12/52] talk about WP Migrate DB Media Files --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1ffbbdd..6aa7eec 100755 --- a/README.md +++ b/README.md @@ -29,10 +29,14 @@ Have a huge database? No problem. We've tested migration of tables with over 100 ###Intelligently Detects Environment Limitations WP Migrate DB analyses both the remote and local environments to detect limitations and optimize performance. For example, we detect MySQL's `max_allowed_packet_size` setting and adjust how much SQL we execute at a time. Not only does this avoid failure, but allows us to increase performance. +###Sync Media Libraries Between Installations +Using the optional [WP Migrate DB Media Files](https://github.com/slang800/wp-migrate-db-media-files) addon, you can have media files synced between installs too. + ##Installation 1. Install [github-updater](https://github.com/afragen/github-updater) by downloading the latest zip [here](https://github.com/afragen/github-updater/releases). We rely on this plugin for updating WP Migrate DB directly from this git repo. 2. Install WP Migrate DB by downloading the latest zip [here](https://github.com/slang800/wp-migrate-db/releases). Both github-updater and WP Migrate DB will now download their own updates automatically, so you will never need to go through that tedious zip downloading again. -3. Access the WP Migrate DB menu option under Tools +3. Access the WP Migrate DB menu option under Tools. +4. Install the optional [WP Migrate DB Media Files](https://github.com/slang800/wp-migrate-db-media-files) addon. ##Help Videos @@ -52,7 +56,7 @@ http://www.youtube.com/watch?v=FjTzNqAlQE0 This screencast demonstrates how you can push a local WordPress database you've been using for development to a staging environment. ##Isn't this the same as WP Migrate DB Pro? -No, of course not, don't be silly. I took out the license verification code, a really shady looking PressTrends reporter, and tab for installing the Media Files addon before I published it. Release 1.3 was the same as [WP Migrate DB Pro](https://deliciousbrains.com/wp-migrate-db-pro), but I've made several improvements since then. +No, of course not, don't be silly. I took out the license verification code, a really shady looking PressTrends reporter, and the tab for installing the Media Files addon before I published 1.4. Release 1.3 was the same as [WP Migrate DB Pro](https://deliciousbrains.com/wp-migrate-db-pro), but I've made several improvements since then. Also, because this plugin is free I'm not _obligated_ to help you like [bradt](https://github.com/bradt) is if you purchased WP Migrate DB Pro. Any help that I give is just because I'm a nice person and I enjoy helping people. Also, I only offer support through the public [issues manager](https://github.com/slang800/wp-migrate-db/issues). If you're an agency and need support at the drop of a hat, buy the plugin from bradt. From 813467578f9261762df623cfb22c75552f8068b0 Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Mon, 30 Dec 2013 16:16:37 -0600 Subject: [PATCH 13/52] fix the markup for the readme screenshot --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6aa7eec..af144eb 100755 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ WP Migrate DB eliminates the manual work of migrating a WP database. Copy your d Donate [here](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5VPMGLLK94XJC) to support [bradt](https://github.com/bradt), the original author of [WP Migrate DB](https://github.com/bradt/wp-migrate-db). And check out [WP Migrate DB Pro](https://deliciousbrains.com/wp-migrate-db-pro/pricing/) for a variant of the plugin that has dedicated customer support. - +

    ##Description WP Migrate DB exports your database as a MySQL data dump (much like phpMyAdmin), does a find and replace on URLs and file paths, then allows you to save it to your computer, or send it directly to another WordPress instance. It is perfect for developers who develop locally and need to move their WordPress site to a staging or production server. From 82218d6d160590f21023d4345226be1e2e9a69ca Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Mon, 30 Dec 2013 16:32:08 -0600 Subject: [PATCH 14/52] update to 1.4 --- wp-migrate-db.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/wp-migrate-db.php b/wp-migrate-db.php index 50fbf9c..4c7399a 100755 --- a/wp-migrate-db.php +++ b/wp-migrate-db.php @@ -1,11 +1,10 @@ Date: Mon, 24 Mar 2014 22:59:49 -0500 Subject: [PATCH 15/52] added another video & reformatted a little --- template/help.php | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/template/help.php b/template/help.php index b538d7f..6ed4392 100755 --- a/template/help.php +++ b/template/help.php @@ -2,48 +2,41 @@ $videos = array( 'SlfSuuePYaQ' => array( 'title' => 'Feature Walkthrough', - 'desc' => 'A brief walkthrough of the WP Migrate DB plugin - showing all of the different options and explaining them.' + 'desc' => 'A brief walkthrough of the WP Migrate DB plugin showing all of the different options and explaining them.' ), 'IFdHIpf6jjc' => array( 'title' => 'Pulling Live Data Into Your Local Development Environment', - 'desc' => 'This screencast demonstrates how you can pull data from a remote, live - WordPress install and update the data in your local development - environment.' + 'desc' => 'This screencast demonstrates how you can pull data from a remote, live WordPress install and update the data in your local development environment.' ), 'FjTzNqAlQE0' => array( 'title' => 'Pushing Local Development Data to a Staging Environment', - 'desc' => 'This screencast demonstrates how you can push a local WordPress database - you\'ve been using for development to a staging environment.' + 'desc' => 'This screencast demonstrates how you can push a local WordPress database you\'ve been using for development to a staging environment.' + ), + '0aR8-jC2XXM' => array( + 'title' => 'Media Files Addon Demo', + 'desc' => 'A short demo of how the Media Files addon allows you to sync up your WordPress Media Libraries.' ) ); ?>
    -

    Email Support

    -

    Diagnostic Info & Error Log

    Clear Error Log
    -

    Videos

    - - - +

    @@ -102,9 +102,9 @@

    SSL Disabled — We couldn't connect over SSL but regular http (no SSL) appears to be working so we've switched to that. If you run a push or pull, your data will be transmitted unencrypted. Most people are fine with this, but just a heads up.

    - +
    - +
    @@ -124,7 +124,7 @@ We require write permissions to the standard WordPress uploads directory. Without this permission exports are unavailable. Please grant 755 permissions on the following directory: get_upload_info( 'path' ); ?>

    - +
    @@ -132,9 +132,9 @@
    Find
    Replace
    - +

    Doesn't look we have any replaces yet, add one?

    - +
    @@ -305,15 +305,15 @@ - +
    Advanced Options
    - +
    - +
    @@ -356,13 +356,13 @@
    - +
    - +

      - +
    -
    +
    - + From ca3433e36ae3351252265447641f14f79ea9dafc Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Sun, 30 Mar 2014 19:51:52 -0500 Subject: [PATCH 17/52] refactor to use get_wpmdb_basename function also fix some local variable names --- class/wpmdb-addon.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/class/wpmdb-addon.php b/class/wpmdb-addon.php index c414b60..8144d71 100644 --- a/class/wpmdb-addon.php +++ b/class/wpmdb-addon.php @@ -6,9 +6,14 @@ function __construct( $plugin_file_path ) { parent::__construct( $plugin_file_path ); } + function get_wpmdb_basename() { + global $wpmdb; + return plugin_basename( $wpmdb->get_plugin_file_path() ); + } + function meets_version_requirements( $version_required ) { - $wpmdb_pro_version = $this->get_installed_version( 'wp-migrate-db/wp-migrate-db.php' ); - $result = version_compare( $wpmdb_pro_version, $version_required, '>=' ); + $wpmdb_version = $this->get_installed_version( $this->get_wpmdb_basename() ); + $result = version_compare( $wpmdb_version, $version_required, '>=' ); $this->version_required = $version_required; if( false == $result ) $this->hook_version_requirement_actions(); return $result; @@ -35,11 +40,11 @@ function version_requirement_warning() { ?>

    Update Requiredget_wpmdb_basename(); $addon_name = $this->get_plugin_name(); $required = $this->version_required; $installed = $this->get_installed_version( $wpmdb_basename ); - $update = wp_nonce_url( network_admin_url( 'update.php?action=upgrade-plugin&plugin=wp-migrate-db%2Fwp-migrate-db.php' ), 'upgrade-plugin_' . $wpmdb_basename ); + $update = wp_nonce_url( network_admin_url( 'update.php?action=upgrade-plugin&plugin=' . urlencode( $wpmdb_basename ) ), 'upgrade-plugin_' . $wpmdb_basename ); echo sprintf( 'The version of %s you have installed, requires version %s of WP Migrate DB. You currently have %s installed. Update Now', $addon_name, $required, $installed, $update ); ?>

    From c6be94a7e92d183d9f273aea838837cc98d571c6 Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Sun, 30 Mar 2014 21:03:43 -0500 Subject: [PATCH 18/52] replace config.rb with a readme --- asset/README.md | 4 ++++ asset/config.rb | 25 ------------------------- 2 files changed, 4 insertions(+), 25 deletions(-) create mode 100644 asset/README.md delete mode 100644 asset/config.rb diff --git a/asset/README.md b/asset/README.md new file mode 100644 index 0000000..e81d6c6 --- /dev/null +++ b/asset/README.md @@ -0,0 +1,4 @@ +# How to Compile the SASS +`cd` into this directory, and run `sass --compass ./sass/styles.scss ./css/styles.css` + +This project might be converted to use roots later, so nobody needs to remember what commands to use. diff --git a/asset/config.rb b/asset/config.rb deleted file mode 100644 index b582f88..0000000 --- a/asset/config.rb +++ /dev/null @@ -1,25 +0,0 @@ -# Require any additional compass plugins here. - -# Set this to the root of your project when deployed: -http_path = "/" -css_dir = "css" -sass_dir = "sass" -images_dir = "img" -javascripts_dir = "js" - -# You can select your preferred output style here (can be overridden via the command line): -# output_style = :expanded or :nested or :compact or :compressed -output_style = :expanded - -# To enable relative paths to assets via compass helper functions. Uncomment: -# relative_assets = true - -# To disable debugging comments that display the original location of your selectors. Uncomment: -line_comments = false - - -# If you prefer the indented syntax, you might want to regenerate this -# project again passing --syntax sass, or you can uncomment this: -# preferred_syntax = :sass -# and then run: -# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass From 2cee33161821df2a5d3af57cf8056d58bcf90895 Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Sun, 30 Mar 2014 21:04:45 -0500 Subject: [PATCH 19/52] recompile css with updated scss & compass --- asset/css/styles.css | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/asset/css/styles.css b/asset/css/styles.css index b34bbd5..a4819dd 100755 --- a/asset/css/styles.css +++ b/asset/css/styles.css @@ -562,8 +562,10 @@ .wpmdb .help-tab .videos ul > li a:before { width: 64px; height: 64px; - -moz-border-radius: 64px; -webkit-border-radius: 64px; + -moz-border-radius: 64px; + -ms-border-radius: 64px; + -o-border-radius: 64px; border-radius: 64px; filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); opacity: 0.8; @@ -653,10 +655,11 @@ height: 10px; background-color: #8cc1e9; margin-bottom: 5px; + background-image: -webkit-gradient(linear, 50% 100%, 50% 0%, color-stop(0%, #72a7cf), color-stop(100%, #8cc1e9)); + background-image: -webkit-linear-gradient(bottom, #72a7cf, #8cc1e9); background-image: -moz-linear-gradient(bottom, #72a7cf, #8cc1e9); background-image: -o-linear-gradient(bottom, #72a7cf, #8cc1e9); - background-image: -webkit-linear-gradient(bottom, #72a7cf, #8cc1e9); - background-image: linear-gradient(to top, #72a7cf, #8cc1e9); } + background-image: linear-gradient(bottom, #72a7cf, #8cc1e9); } .progress-content .progress-title { font-size: 18px; font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", sans-serif; From 29c200b5543e7709908bb2a7715692debf93734a Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Sun, 30 Mar 2014 21:10:57 -0500 Subject: [PATCH 20/52] small css updates --- asset/css/styles.css | 12 +++++++++++- asset/sass/_mp6.scss | 8 ++++++-- asset/sass/styles.scss | 21 ++++++++++++++++----- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/asset/css/styles.css b/asset/css/styles.css index a4819dd..beb98c4 100755 --- a/asset/css/styles.css +++ b/asset/css/styles.css @@ -33,6 +33,8 @@ -webkit-box-sizing: border-box; box-sizing: border-box; margin: 10px 0; } + .wpmdb > div.updated.warning p { + font-size: 13px; } .wpmdb a { text-decoration: none; } .wpmdb li { @@ -422,6 +424,11 @@ display: inline-block; } .wpmdb p img.save-profile-ajax-spinner { margin-left: 10px; } + .wpmdb .backup-description { + left: 20px; + position: relative; } + .wpmdb .backup-option-disabled { + margin-bottom: 0px; } .wpmdb .import-button { display: none; } .wpmdb .settings-tab { @@ -936,7 +943,7 @@ body.mp6 .wpmdb .inline-message.error, body.mp6 .wpmdb .notification-message.err body.mp6 .wpmdb .inline-message.warning, body.mp6 .wpmdb .notification-message.warning-notice { background-color: #fff; border-left: 4px solid #ffba00; } -body.mp6 .wpmdb .inline-message.success, body.mp6 .wpmdb .notication-message.success-notice { +body.mp6 .wpmdb .inline-message.success, body.mp6 .wpmdb .notification-message.success-notice { border-left: 4px solid #7ad03a; } body.mp6 .wpmdb .ssl-notice { margin-bottom: 0; } @@ -950,6 +957,9 @@ body.mp6 .progress-content { font-family: 'Open Sans', sans-serif; font-weight: normal; font-size: 22px; } + body.mp6 .progress-content .dashicons-yes { + font-size: 42px; + line-height: 0.5em; } body.mp6 .progress-content .progress-bar { background-image: none; background-color: #0074a2; } diff --git a/asset/sass/_mp6.scss b/asset/sass/_mp6.scss index c87580e..183c19b 100755 --- a/asset/sass/_mp6.scss +++ b/asset/sass/_mp6.scss @@ -19,7 +19,6 @@ body.mp6 { } .wpmdb { - input[type=checkbox], input[type=radio]{ vertical-align: middle; @@ -286,7 +285,7 @@ body.mp6 { border-left: 4px solid #ffba00; } - .inline-message.success, .notication-message.success-notice { + .inline-message.success, .notification-message.success-notice { border-left: 4px solid #7ad03a; } @@ -311,6 +310,11 @@ body.mp6 { font-size: 22px; } + .dashicons-yes { + font-size: 42px; + line-height: 0.5em; + } + .progress-bar { background-image: none; background-color: #0074a2; diff --git a/asset/sass/styles.scss b/asset/sass/styles.scss index f8a7f8d..1231cdb 100755 --- a/asset/sass/styles.scss +++ b/asset/sass/styles.scss @@ -15,6 +15,10 @@ -webkit-box-sizing: border-box; box-sizing: border-box; margin: 10px 0; + + p { + font-size: 13px; + } } /* ============================================================================= @@ -651,6 +655,14 @@ margin-left: 10px; } + .backup-description { + left: 20px; + position: relative; + } + .backup-option-disabled { + margin-bottom: 0px; + } + /* Import DB */ .import-button { display: none; @@ -986,10 +998,10 @@ box-sizing: border-box; .progress-bar { - height: 10px; - background-color: #8cc1e9; - margin-bottom: 5px; - @include background-image(linear-gradient(bottom, #72a7cf, #8cc1e9)); + height: 10px; + background-color: #8cc1e9; + margin-bottom: 5px; + @include background-image(linear-gradient(bottom, #72a7cf, #8cc1e9)); } .progress-title { @@ -1150,7 +1162,6 @@ color: #666; border-color: #aaa; } - } @import "mp6"; From d3a6374a5a715087a325af55957156f79eec1a6e Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Sun, 30 Mar 2014 21:14:43 -0500 Subject: [PATCH 21/52] remaining updates from v1.3.2 of official --- asset/js/common.js | 5 +- asset/js/script.js | 291 +++++++++++++++++------- class/wpmdb-base.php | 95 ++++++-- class/wpmdb.php | 530 +++++++++++++++++++++++++++---------------- 4 files changed, 630 insertions(+), 291 deletions(-) diff --git a/asset/js/common.js b/asset/js/common.js index 7c4150c..6153aa8 100644 --- a/asset/js/common.js +++ b/asset/js/common.js @@ -3,6 +3,7 @@ var hooks = []; var call_stack = []; var non_fatal_errors = ''; var migration_error = false; +var connection_data; function wpmdb_call_next_hook() { if( ! call_stack.length ) { @@ -36,7 +37,3 @@ function wpmdb_parse_json( maybe_json ) { } return json_object; } - -(function($) { - // jQuery code here -})(jQuery); diff --git a/asset/js/script.js b/asset/js/script.js index 9a70d66..0642eb1 100755 --- a/asset/js/script.js +++ b/asset/js/script.js @@ -16,12 +16,12 @@ var migration_complete_events; var migration_completed = false; var currently_migrating = false; var dump_filename = ''; + var dump_url = ''; var migration_intent; var remote_site; var secret_key; var form_data; var stage; - var connection_data; var elapsed_interval; var completed_msg; var tables_to_migrate = ''; @@ -103,12 +103,15 @@ var migration_complete_events; function maybe_show_ssl_warning( url, key, remote_scheme ) { var scheme = url.substr(0, url.indexOf(':')); - if( remote_scheme != scheme ) { + if( remote_scheme != scheme && url.indexOf('https') != -1 ) { $('.ssl-notice').show(); show_ssl_notice = true; url = url.replace('https','http'); $('.pull-push-connection-info').val( url + "\n" + key ); + return; } + show_ssl_notice = false; + return; } function maybe_show_version_warning( plugin_version, url ) { @@ -155,9 +158,13 @@ var migration_complete_events; return profile_name = action + ' ' + preposition + ' ' + domain; } + function remove_protocol( url ) { + return url.replace(/^https?:/i, ""); + } + $(document).ready(function() { - if( navigator.appName.indexOf('Internet Explorer') != -1 ) { + if ( navigator.userAgent.indexOf('MSIE') > 0 || navigator.userAgent.indexOf('Trident') > 0 ) { $('.ie-warning').show(); } @@ -209,13 +216,15 @@ var migration_complete_events; var pull_select = $('#select-tables').clone(); var push_post_type_select = $('#select-post-types').clone(); var pull_post_type_select = $('#select-post-types').clone(); + var push_select_backup = $('#select-backup').clone(); + var pull_select_backup = $('#select-backup').clone(); $('.help-tab .video').each(function() { var $container = $(this), $viewer = $('.video-viewer'); $('a', this).click(function() { - $viewer.attr('src', 'http://www.youtube.com/embed/' + $container.data('video-id') + '?autoplay=1'); + $viewer.attr('src', '//www.youtube.com/embed/' + $container.data('video-id') + '?autoplay=1'); $viewer.show(); var offset = $viewer.offset(); $(window).scrollTop(offset.top - 50); @@ -230,6 +239,20 @@ var migration_complete_events; $('.keep-active-plugins').hide(); } + function disable_export_type_controls() { + $('.option-group').each(function(index){ + $('input', this).attr('disabled','disabled'); + $('label', this).css('cursor','default'); + }); + } + + function enable_export_type_controls() { + $('.option-group').each(function(index){ + $('input', this).removeAttr('disabled'); + $('label', this).css('cursor','pointer'); + }); + } + // automatically validate connnection info if we're loading a saved profile establish_remote_connection_from_saved_profile(); @@ -240,10 +263,13 @@ var migration_complete_events; return; } + last_replace_switch = action; + doing_ajax = true; + disable_export_type_controls(); $('.connection-status').html( 'Establishing connection to remote server, please wait' ); - $('.connection-status').removeClass( 'migration-error' ); + $('.connection-status').removeClass( 'notification-message error-notice migration-error' ); $('.connection-status').append( '' ); var intent = $('input[name=action]:checked').val(); @@ -261,17 +287,19 @@ var migration_complete_events; }, error: function(jqXHR, textStatus, errorThrown){ $('.connection-status').html( 'A problem occurred when attempting to connect to the local server, please check the details and try again. (#102)' ); - $('.connection-status').addClass( 'migration-error' ); + $('.connection-status').addClass( 'notification-message error-notice migration-error' ); $('.ajax-spinner').remove(); doing_ajax = false; + enable_export_type_controls(); }, success: function(data){ $('.ajax-spinner').remove(); doing_ajax = false; + enable_export_type_controls(); if( typeof data.wpmdb_error != 'undefined' && data.wpmdb_error == 1 ){ $('.connection-status').html( data.body ); - $('.connection-status').addClass( 'migration-error' ); + $('.connection-status').addClass( 'notification-message error-notice migration-error' ); if( data.body.indexOf( '401 Unauthorized' ) > -1 ) { $('.basic-access-auth-wrapper').show(); @@ -295,12 +323,17 @@ var migration_complete_events; move_connection_info_box(); var loaded_tables = ''; - if( wpmdb_default_profile == false && wpmdb_export_with_prefix == false ){ + if( wpmdb_default_profile == false && typeof wpmdb_loaded_tables != 'undefined' ){ loaded_tables = $.parseJSON( wpmdb_loaded_tables ); } var table_select = document.createElement('select'); - $(table_select).attr('multiple', 'multiple').attr('name','select_tables[]').attr('id','select-tables').attr('class','multiselect'); + $(table_select).attr({ + multiple: 'multiple', + name: 'select_tables[]', + id: 'select-tables', + class: 'multiselect' + }); $.each(connection_data.tables, function(index, value) { var selected = $.inArray( value, loaded_tables ); @@ -316,12 +349,17 @@ var migration_complete_events; pull_select = table_select; var loaded_post_prefixes = ''; - if( wpmdb_default_profile == false && wpmdb_migrate_all_post_types == false ){ - loaded_post_prefixes = $.parseJSON( wpmdb_loaded_post_types ); + if( wpmdb_default_profile == false && typeof wpmdb_loaded_post_types != 'undefined' ){ + loaded_post_prefixes = $.parseJSON( wpmdb_loaded_post_types ); } var post_type_select = document.createElement('select'); - $(post_type_select).attr('multiple', 'multiple').attr('name','select_post_types[]').attr('id','select-post-types').attr('class','multiselect'); + $(post_type_select).attr({ + multiple: 'multiple', + name: 'select_post_types[]', + id: 'select-post-types', + class: 'multiselect' + }); $.each(connection_data.post_types, function(index, value) { var selected = $.inArray( value, loaded_post_prefixes ); @@ -336,14 +374,46 @@ var migration_complete_events; pull_post_type_select = post_type_select; + var loaded_tables_backup = ''; + if( wpmdb_default_profile == false && typeof wpmdb_loaded_tables_backup != 'undefined' ){ + loaded_tables_backup = $.parseJSON( wpmdb_loaded_tables_backup ); + } + + var table_select_backup = document.createElement('select'); + $(table_select_backup).attr({ + multiple: 'multiple', + name: 'select_backup[]', + id: 'select-backup', + class: 'multiselect' + }); + + $.each(connection_data.tables, function(index, value) { + var selected = $.inArray( value, loaded_tables_backup ); + if( selected != -1 ){ + selected = ' selected="selected" '; + } + else{ + selected = ' '; + } + $(table_select_backup).append('' + value + ' (' + connection_data.table_sizes_hr[value] + ')'); + }); + + push_select_backup = table_select_backup; + if( $('#pull').is(':checked') ){ $('#select-tables').remove(); $('.select-tables-wrap').prepend(pull_select); $('#select-post-types').remove(); $('.select-post-types-wrap').prepend(pull_post_type_select); + $('#select-backup').remove(); + $('.backup-tables-wrap').prepend(pull_select_backup); $('.table-prefix').html(data.prefix); $('.uploads-dir').html(wpmdb_this_uploads_dir); } + else { + $('#select-backup').remove(); + $('.backup-tables-wrap').prepend(push_select_backup); + } $.wpmdb.do_action( 'verify_connection_to_remote_site', connection_data ); @@ -575,58 +645,76 @@ var migration_complete_events; $('#overlay').after($progress_content); - completed_msg = 'Exporting complete.'; + completed_msg = 'Exporting complete'; if( migration_intent == 'savefile' ){ static_migration_label = 'Exporting, please wait...'; } else{ static_migration_label = get_default_profile_name(remote_site, migration_intent, true) + ', please wait...'; - completed_msg = get_default_profile_name(remote_site, migration_intent, true) + ' complete.'; + completed_msg = get_default_profile_name(remote_site, migration_intent, true) + ' complete'; } $('.progress-title').html(static_migration_label); $('#overlay').show(); + backup_option = $('input[name=backup_option]:checked').val(); + table_option = $('input[name=table_migrate_option]:checked').val(); - if( table_intent == 'migrate_select' ){ // user has elected to migrate only certain tables - // grab tables as per what the user has selected from the multiselect box - temp_tables_to_migrate = $('#select-tables').val(); - tables_to_migrate = temp_tables_to_migrate; - // user is pushing or exporting - if( migration_intent == 'push' || migration_intent == 'savefile' ){ - // default value, assuming we're not backing up - table_rows = $.parseJSON(wpmdb_this_table_rows); - // backing up, during a push, need to only grab the common tables - if( stage == 'backup' ){ - tables_to_migrate = get_intersect(connection_data.tables,temp_tables_to_migrate); - table_rows = connection_data.table_rows; + if( stage == 'backup' ) { + if( table_option == 'migrate_only_with_prefix' && backup_option == 'backup_selected' ) { + backup_option = 'backup_only_with_prefix'; + } + if( migration_intent == 'push' ){ + table_rows = connection_data.table_rows; + if( backup_option == 'backup_only_with_prefix' ) { + tables_to_migrate = connection_data.prefixed_tables; + } + else if( backup_option == 'backup_selected' ) { + selected_tables = $('#select-tables').val(); + tables_to_migrate = get_intersect( selected_tables, connection_data.tables ); + } + else if( backup_option == 'backup_manual_select' ) { + tables_to_migrate = $('#select-backup').val(); } } else{ - table_rows = connection_data.table_rows; - if( stage == 'backup' ){ - tables_to_migrate = get_intersect(temp_tables_to_migrate,this_tables); - table_rows = $.parseJSON(wpmdb_this_table_rows); + table_rows = $.parseJSON(wpmdb_this_table_rows); + if( backup_option == 'backup_only_with_prefix' ) { + tables_to_migrate = $.parseJSON( wpmdb_this_prefixed_tables ); + } + else if( backup_option == 'backup_selected' ) { + selected_tables = $('#select-tables').val(); + local_tables = $.parseJSON( wpmdb_this_tables ); + tables_to_migrate = get_intersect( selected_tables, local_tables ); + } + else if( backup_option == 'backup_manual_select' ) { + tables_to_migrate = $('#select-backup').val(); } } } - else{ - if( migration_intent == 'push' || migration_intent == 'savefile' ){ - tables_to_migrate = this_prefixed_tables; - table_rows = $.parseJSON(wpmdb_this_table_rows); - if( stage == 'backup' ){ - tables_to_migrate = get_intersect(connection_data.prefixed_tables,this_prefixed_tables); + else { + if( table_intent == 'migrate_select' ){ // user has elected to migrate only certain tables + // grab tables as per what the user has selected from the multiselect box + tables_to_migrate = $('#select-tables').val(); + // user is pushing or exporting + if( migration_intent == 'push' || migration_intent == 'savefile' ){ + // default value, assuming we're not backing up + table_rows = $.parseJSON(wpmdb_this_table_rows); + } + else{ table_rows = connection_data.table_rows; } } else{ - tables_to_migrate = connection_data.prefixed_tables; - table_rows = connection_data.table_rows; - if( stage == 'backup' ){ - tables_to_migrate = get_intersect(connection_data.tables,this_prefixed_tables); + if( migration_intent == 'push' || migration_intent == 'savefile' ){ + tables_to_migrate = this_prefixed_tables; table_rows = $.parseJSON(wpmdb_this_table_rows); } + else{ + tables_to_migrate = connection_data.prefixed_tables; + table_rows = connection_data.table_rows; + } } } @@ -711,6 +799,12 @@ var migration_complete_events; $('.progress-title').html('Migration failed'); $('.progress-text').html( 'A problem occurred when attempting to connect to the local server, please check the details and try again. (#112)' ); $('.progress-text').addClass( 'migration-error' ); + console.log( jqXHR ); + console.log( textStatus ); + console.log( errorThrown ); + migration_error = true; + migration_complete_events(); + return; }, success: function(data){ if( typeof data.wpmdb_error != 'undefined' && data.wpmdb_error == 1 ){ @@ -721,7 +815,7 @@ var migration_complete_events; return; } - var dump_url = data.dump_url; + dump_url = data.dump_url; dump_filename = data.dump_filename; var i = 0; @@ -770,8 +864,9 @@ var migration_complete_events; } else { + hooks = $.wpmdb.apply_filters( 'wpmdb_before_migration_complete_hooks', hooks ); hooks.push( 'migration_complete' ); - hooks = $.wpmdb.apply_filters( 'wpmdb_migration_complete_hooks', hooks ); + hooks = $.wpmdb.apply_filters( 'wpmdb_after_migration_complete_hooks', hooks ); hooks.push( 'migration_complete_events' ); wpmdb_call_next_hook(); return; @@ -815,8 +910,9 @@ var migration_complete_events; request_data.prefix = connection_data.prefix; } - if( connection_data && connection_data.path_current_site ) { + if( connection_data && connection_data.path_current_site && connection_data.domain ) { request_data.path_current_site = connection_data.path_current_site; + request_data.domain_current_site = connection_data.domain; } $.ajax({ @@ -829,6 +925,7 @@ var migration_complete_events; error: function(jqXHR, textStatus, errorThrown){ $('.progress-title').html('Migration failed'); $('.progress-text').html( 'A problem occurred when processing the ' + tables_to_migrate[i] + ' table. (#113)' ); + $('.progress-text').append( '

    Status: ' + jqXHR.status + ' ' + jqXHR.statusText + '

    Response:
    ' + jqXHR.responseText ); $('.progress-text').addClass( 'migration-error' ); console.log( jqXHR ); console.log( textStatus ); @@ -840,9 +937,14 @@ var migration_complete_events; success: function(data){ data = $.trim( data ); row_information = wpmdb_parse_json( data ); - if( false == row_information ){ + if( false == row_information || null == row_information ){ $('.progress-title').html('Migration failed'); - $('.progress-text').html(data); + if( '' == data || null == data ) { + $('.progress-text').html( 'A problem occurred when processing the ' + tables_to_migrate[i] + ' table. We were expecting a response in JSON format but instead received an empty response.' ); + } + else { + $('.progress-text').html(data); + } $('.progress-text').addClass('migration-error'); migration_error = true; migration_complete_events(); @@ -885,24 +987,33 @@ var migration_complete_events; migration_complete_events = function() { if( false == migration_error ) { if( non_fatal_errors == '' ) { - $('.progress-text').html('Migration complete'); - $('.progress-title').html(completed_msg); + if( 'savefile' != migration_intent && true == $('#save_computer').is(':checked') ) { + $('.progress-text').css('visibility','hidden'); + } + $('.progress-title').html(completed_msg).append('
    '); } else { $('.progress-text').html(non_fatal_errors); $('.progress-text').addClass('migration-error'); $('.progress-title').html('Migration completed with some errors'); } + + $('.progress-bar-wrapper').hide(); } + // reset migration variables so consecutive migrations work correctly + hooks = []; + call_stack = []; + migration_error = false; + currently_migrating = false; migration_completed = true; + non_fatal_errors = ''; + $('.progress-label').remove(); $('.migration-progress-ajax-spinner').remove(); $('.close-progress-content').show(); $('#overlay').css('cursor','pointer'); clearInterval( elapsed_interval ); - currently_migrating = false; - non_fatal_errors = ''; } migration_complete = function() { @@ -940,8 +1051,8 @@ var migration_complete_events; url : remote_site, key : secret_key, form_data : form_data, - stage : stage, prefix : connection_data.prefix, + temp_prefix : connection_data.temp_prefix, tables : tables_to_migrate.join(','), }, error: function(jqXHR, textStatus, errorThrown){ @@ -1129,12 +1240,12 @@ var migration_complete_events; $('.different-plugin-version-notice').show(); $('.step-two').hide(); } + $('.directory-scope').html('local'); if( false == wpmdb_write_permission ) { $('#create-backup').prop('checked',false); $('#create-backup').attr('disabled','disabled'); $('#create-backup-label').addClass('disabled'); $('.backup-option-disabled').show(); - $('.directory-scope').html('local'); $('.upload-directory-location').html(wpmdb_this_upload_dir_long); } } @@ -1165,12 +1276,12 @@ var migration_complete_events; $('.different-plugin-version-notice').show(); $('.step-two').hide(); } + $('.directory-scope').html('remote'); if( '0' == connection_data.write_permissions ) { $('#create-backup').prop('checked',false); $('#create-backup').attr('disabled','disabled'); $('#create-backup-label').addClass('disabled'); $('.backup-option-disabled').show(); - $('.directory-scope').html('remote'); $('.upload-directory-location').html(connection_data.upload_dir_long); } } @@ -1209,6 +1320,8 @@ var migration_complete_events; $('.select-tables-wrap').prepend(push_select); $('#select-post-types').remove(); $('.select-post-types-wrap').prepend(push_post_type_select); + $('#select-backup').remove(); + $('.backup-tables-wrap').prepend(push_select_backup); last_replace_switch = 'push'; } else if( $('#pull').is(':checked') ){ @@ -1223,23 +1336,13 @@ var migration_complete_events; $('.select-tables-wrap').prepend(pull_select); $('#select-post-types').remove(); $('.select-post-types-wrap').prepend(pull_post_type_select); + $('#select-backup').remove(); + $('.backup-tables-wrap').prepend(pull_select_backup); last_replace_switch = 'pull'; } } - // keep a copy of select boxes when making changes - $('#select-tables').change(function(){ - if( $('#push').is(':checked') || $('#savefile').is(':checked') ){ - push_select = $('#select-tables').clone(); - push_post_type_select = $('#select-post-types').clone(); - } - else if( $('#pull').is(':checked') ){ - pull_select = $('#select-tables').clone(); - pull_post_type_select = $('#select-post-types').clone(); - } - }); - // hide second section if pull or push is selected with no connection established if( ( $('#pull').is(':checked') || $('#push').is(':checked') ) && ! connection_established ){ $('.step-two').hide(); @@ -1380,6 +1483,17 @@ var migration_complete_events; } }); + $('input[name=backup_option]').change(function(){ + $('.backup-tables-wrap').hide(); + if( $(this).val() == 'backup_manual_select' ) { + $('.backup-tables-wrap').show(); + } + }); + + if( $('#backup-manual-select').is(':checked') ) { + $('.backup-tables-wrap').show(); + } + // delete a profile from the migrate form area $('body').delegate('.delete-profile', 'click', function(){ var name = $(this).next().clone(); @@ -1577,7 +1691,7 @@ var migration_complete_events; if( error ){ $('.connection-status').html( error_message ); - $('.connection-status').addClass( 'migration-error' ); + $('.connection-status').addClass( 'notification-message error-notice migration-error' ); return; } @@ -1589,10 +1703,11 @@ var migration_complete_events; show_prefix_notice = false; doing_ajax = true; + disable_export_type_controls(); if( $('.basic-access-auth-wrapper').is(':visible') ) { connection_info[0] = connection_info[0].replace( /\/\/(.*)@/, '//' ); - connection_info[0] = connection_info[0].replace( '//', '//' + $.trim( $('.auth-username').val() ) + ':' + $.trim( $('.auth-password').val() ) + '@' ); + connection_info[0] = connection_info[0].replace( '//', '//' + encodeURIComponent( $.trim( $('.auth-username').val() ) ) + ':' + encodeURIComponent( $.trim( $('.auth-password').val() ) ) + '@' ); var new_connection_info_contents = connection_info[0] + "\n" + connection_info[1]; $('.pull-push-connection-info').val(new_connection_info_contents); $('.basic-access-auth-wrapper').hide(); @@ -1604,7 +1719,7 @@ var migration_complete_events; $('.connection-status').show(); $('.connection-status').html( 'Establishing connection to remote server, please wait' ); - $('.connection-status').removeClass( 'migration-error' ); + $('.connection-status').removeClass( 'notification-message error-notice migration-error' ); $('.connection-status').append( '' ); var intent = $('input[name=action]:checked').val(); @@ -1624,17 +1739,19 @@ var migration_complete_events; }, error: function(jqXHR, textStatus, errorThrown){ $('.connection-status').html( 'A problem occurred when attempting to connect to the local server, please check the details and try again. (#100)' ); - $('.connection-status').addClass( 'migration-error' ); + $('.connection-status').addClass( 'notification-message error-notice migration-error' ); $('.ajax-spinner').remove(); doing_ajax = false; + enable_export_type_controls(); }, success: function(data){ $('.ajax-spinner').remove(); doing_ajax = false; + enable_export_type_controls(); if( typeof data.wpmdb_error != 'undefined' && data.wpmdb_error == 1 ){ $('.connection-status').html( data.body ); - $('.connection-status').addClass( 'migration-error' ); + $('.connection-status').addClass( 'notification-message error-notice migration-error' ); if( data.body.indexOf( '401 Unauthorized' ) > -1 ) { $('.basic-access-auth-wrapper').show(); @@ -1652,25 +1769,41 @@ var migration_complete_events; $('.connection-status').hide(); $('.step-two').show(); - connection_established = true; - connection_data = data; - move_connection_info_box(); maybe_show_ssl_warning( connection_info[0], connection_info[1], data.scheme ); maybe_show_version_warning( data.plugin_version, connection_info[0] ); maybe_show_prefix_notice( data.prefix ); + connection_established = true; + connection_data = data; + move_connection_info_box(); + var table_select = document.createElement('select'); - $(table_select).attr('multiple', 'multiple').attr('name','select_tables[]').attr('id','select-tables').attr('class','multiselect'); + $(table_select).attr({ + multiple: 'multiple', + name: 'select_tables[]', + id: 'select-tables', + class: 'multiselect' + }); $.each(connection_data.tables, function(index, value) { $(table_select).append(''); }); pull_select = table_select; + push_select_backup = $(table_select).clone(); + $(push_select_backup).attr({ + name : 'select_backup[]', + id : 'select-backup' + }); var post_type_select = document.createElement('select'); - $(post_type_select).attr('multiple', 'multiple').attr('name','select_post_types[]').attr('id','select-post-types').attr('class','multiselect'); + $(post_type_select).attr({ + multiple : 'multiple', + name : 'select_post_types[]', + id : 'select-post-types', + class : 'multiselect' + }); $.each(connection_data.post_types, function(index, value) { $(post_type_select).append(''); @@ -1679,14 +1812,13 @@ var migration_complete_events; pull_post_type_select = post_type_select; if( $('#pull').is(':checked') ){ - $('#new-url').val( wpmdb_this_url ); + $('#new-url').val( remove_protocol( wpmdb_this_url ) ); $('#new-path').val( wpmdb_this_path ); if( wpmdb_is_multisite == true ) { $('#new-domain').val( wpmdb_this_domain ); } - $('#old-url').val( data.url ); + $('#old-url').val( remove_protocol( data.url ) ); $('#old-path').val( data.path ); - $('#old-domain').val( data.domain ); $('#select-tables').remove(); $('.select-tables-wrap').prepend(pull_select); $('#select-post-types').remove(); @@ -1695,9 +1827,10 @@ var migration_complete_events; $('.uploads-dir').html(wpmdb_this_uploads_dir); } else{ - $('#new-url').val( data.url ); + $('#select-backup').remove(); + $('.backup-tables-wrap').prepend(push_select_backup); + $('#new-url').val( remove_protocol( data.url ) ); $('#new-path').val( data.path ); - $('#new-domain').val( data.domain ); } $.wpmdb.do_action( 'verify_connection_to_remote_site', connection_data ); diff --git a/class/wpmdb-base.php b/class/wpmdb-base.php index 8a38e67..29811bf 100755 --- a/class/wpmdb-base.php +++ b/class/wpmdb-base.php @@ -13,11 +13,20 @@ class WPMDB_Base { protected $multipart_boundary = 'bWH4JVmYCnf6GfXacrcc'; protected $attempting_to_connect_to; protected $error; + protected $temp_prefix = '_mig_'; protected $invalid_content_verification_error = 'Invalid content verification signature, please verify the connection information on the remote site and try again.'; + protected $addons; function __construct( $plugin_file_path ) { $this->settings = get_option( 'wpmdb_settings' ); + $this->addons = array( + 'wp-migrate-db-media-files/wp-migrate-db-media-files.php' => array( + 'name' => 'Media Files', + 'required_version' => '1.0.1', + ) + ); + $this->transient_timeout = 60 * 60 * 12; $this->transient_retry_timeout = 60 * 60 * 2; @@ -35,6 +44,9 @@ function __construct( $plugin_file_path ) { else { $this->plugin_base = 'tools.php?page=wp-migrate-db'; } + + // allow devs to change the temporary prefix applied to the tables + $this->temp_prefix = apply_filters( 'wpmdb_temporary_prefix', $this->temp_prefix ); } function printer( $debug ) { @@ -101,7 +113,9 @@ function remote_post( $url, $data, $scope, $args = array(), $expecting_serial = ) ); $args['method'] = 'POST'; - $args['body'] = $this->array_to_multipart( $data ); + if( ! isset( $args['body'] ) ) { + $args['body'] = $this->array_to_multipart( $data ); + } $args['headers']['Content-Type'] = 'multipart/form-data; boundary=' . $this->multipart_boundary; $args['headers']['Referer'] = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ); @@ -115,13 +129,7 @@ function remote_post( $url, $data, $scope, $args = array(), $expecting_serial = if ( is_wp_error( $response ) ) { if( strpos( $url, 'https://' ) === 0 && $scope == 'ajax_verify_connection_to_remote_site' ) { - $url = substr_replace( $url, 'http', 0, 5 ); - if( $response = $this->remote_post( $url, $data, $scope, $args, $expecting_serial ) ) { - return $response; - } - else { - return false; - } + return $this->retry_remote_post( $url, $data, $scope, $args, $expecting_serial ); } else if( isset( $response->errors['http_request_failed'][0] ) && strstr( $response->errors['http_request_failed'][0], 'timed out' ) ) { $this->error = 'The connection to the remote server has timed out, no changes have been committed. (#134 - scope: ' . $scope . ')'; @@ -141,13 +149,7 @@ function remote_post( $url, $data, $scope, $args = array(), $expecting_serial = } elseif ( (int) $response['response']['code'] < 200 || (int) $response['response']['code'] > 399 ) { if( strpos( $url, 'https://' ) === 0 && $scope == 'ajax_verify_connection_to_remote_site' ) { - $url = substr_replace( $url, 'http', 0, 5 ); - if( $response = $this->remote_post( $url, $data, $scope, $args, $expecting_serial ) ) { - return $response; - } - else { - return false; - } + return $this->retry_remote_post( $url, $data, $scope, $args, $expecting_serial ); } else if( $response['response']['code'] == '401' ) { $this->error = 'The remote site is protected with Basic Authentication. Please enter the username and password above to continue. (401 Unauthorized)'; @@ -161,11 +163,17 @@ function remote_post( $url, $data, $scope, $args = array(), $expecting_serial = } } elseif ( $expecting_serial && is_serialized( $response['body'] ) == false ) { + if( strpos( $url, 'https://' ) === 0 && $scope == 'ajax_verify_connection_to_remote_site' ) { + return $this->retry_remote_post( $url, $data, $scope, $args, $expecting_serial ); + } $this->error = 'There was a problem with the AJAX request, we were expecting a serialized response, instead we received:
    ' . htmlentities( $response['body'] ); $this->log_error( $this->error, $response ); return false; } elseif ( $response['body'] === '0' ) { + if( strpos( $url, 'https://' ) === 0 && $scope == 'ajax_verify_connection_to_remote_site' ) { + return $this->retry_remote_post( $url, $data, $scope, $args, $expecting_serial ); + } $this->error = 'WP Migrate DB does not seem to be installed or active on the remote site. (#131 - scope: ' . $scope . ')'; $this->log_error( $this->error, $response ); return false; @@ -174,6 +182,14 @@ function remote_post( $url, $data, $scope, $args = array(), $expecting_serial = return $response['body']; } + function retry_remote_post( $url, $data, $scope, $args = array(), $expecting_serial = false ) { + $url = substr_replace( $url, 'http', 0, 5 ); + if( $response = $this->remote_post( $url, $data, $scope, $args, $expecting_serial ) ) { + return $response; + } + return false; + } + function array_to_multipart( $data ) { if ( !$data || !is_array( $data ) ) { return $data; @@ -205,6 +221,26 @@ function array_to_multipart( $data ) { return $result; } + function file_to_multipart( $file ) { + $result = ''; + + if( false == file_exists( $file ) ) return false; + + $filetype = wp_check_filetype( $file ); + $contents = file_get_contents( $file ); + + $result .= '--' . $this->multipart_boundary . "\r\n" . + sprintf( 'Content-Disposition: form-data; name="media[]"; filename="%s"', basename( $file ) ); + + $result .= sprintf( "\r\nContent-Type: %s", $filetype['type'] ); + + $result .= "\r\n\r\n" . $contents . "\r\n"; + + $result .= "--" . $this->multipart_boundary . "--\r\n"; + + return $result; + } + function log_error( $wpmdb_error, $additional_error_var = false ){ $error_header = "********************************************\n****** Log date: " . date( 'Y/m/d H:i:s' ) . " ******\n********************************************\n\n"; $error = $error_header . "WPMDB Error: " . $wpmdb_error . "\n\n"; @@ -278,4 +314,33 @@ function get_plugin_name( $plugin = false ) { return $plugins[$plugin_basename]['Name']; } + // Get only the table beginning with our DB prefix or temporary prefix, also skip views + function get_tables( $scope = 'regular' ) { + global $wpdb; + $prefix = ( $scope == 'temp' ? $this->temp_prefix : $wpdb->prefix ); + $tables = $wpdb->get_results( 'SHOW FULL TABLES', ARRAY_N ); + foreach ( $tables as $table ) { + if ( ( ( $scope == 'temp' || $scope == 'prefix' ) && 0 !== strpos( $table[0], $prefix ) ) || $table[1] == 'VIEW' ) { + continue; + } + $clean_tables[] = $table[0]; + } + return apply_filters( 'wpmdb_tables', $clean_tables, $scope ); + } + + function plugins_dir() { + $path = untrailingslashit( $this->plugin_dir_path ); + return substr( $path, 0, strrpos( $path, DS ) ) . DS; + } + + function is_addon_outdated( $addon_basename ) { + $installed_version = $this->get_installed_version( $addon_basename ); + $required_version = $this->addons[$addon_basename]['required_version']; + return version_compare( $installed_version, $required_version, '<' ); + } + + function get_plugin_file_path() { + return $this->plugin_file_path; + } + } diff --git a/class/wpmdb.php b/class/wpmdb.php index 03651f9..5ab5841 100755 --- a/class/wpmdb.php +++ b/class/wpmdb.php @@ -12,7 +12,6 @@ class WPMDB extends WPMDB_Base { protected $remote_key; protected $form_data; protected $max_insert_string_len; - protected $temp_prefix = '_mig_'; protected $row_tracker; protected $rows_per_segment = 100; protected $create_alter_table_query; @@ -117,6 +116,8 @@ function __construct( $plugin_file_path ) { 'keep_active_plugins', 'post_type_migrate_option', 'select_post_types', + 'backup_option', + 'select_backup', ); $this->default_profile = array( @@ -130,6 +131,16 @@ function __construct( $plugin_file_path ) { 'select_tables' => array(), 'post_type_migrate_option' => 'migrate_all_post_types', 'select_post_types' => array(), + 'backup_option' => 'backup_only_with_prefix' + ); + + $this->checkbox_options = array( + 'save_computer' => '0', + 'gzip_file' => '0', + 'replace_guids' => '0', + 'exclude_spam' => '0', + 'keep_active_plugins' => '0', + 'create_backup' => '0' ); if ( is_multisite() ) { @@ -144,9 +155,6 @@ function __construct( $plugin_file_path ) { // this is how many DB rows are processed at a time, allow devs to change this value $this->rows_per_segment = apply_filters( 'wpmdb_rows_per_segment', $this->rows_per_segment ); - // allow devs to change the temporary prefix applied to the tables - $this->temp_prefix = apply_filters( 'wpmdb_temporary_prefix', $this->temp_prefix ); - if ( is_multisite() ) { add_action( 'network_admin_menu', array( $this, 'network_admin_menu' ) ); $this->plugin_base = 'settings.php?page=wp-migrate-db'; @@ -157,6 +165,12 @@ function __construct( $plugin_file_path ) { } } + function check_again_clear_transients( $current_screen ) { + if( ! isset( $current_screen->id ) || strpos( $current_screen->id, 'update-core' ) === false || ! isset( $_GET['force-check'] ) ) return; + delete_site_transient( 'wpmdb_upgrade_data' ); + delete_site_transient( 'update_plugins' ); + } + function get_alter_table_name() { if ( ! is_null( $this->alter_table_name ) ) { return $this->alter_table_name; @@ -223,7 +237,8 @@ function get_upload_info( $type = 'path' ) { function ajax_update_max_request_size() { $this->settings['max_request'] = (int) $_POST['max_request_size'] * 1024; update_option( 'wpmdb_settings', $this->settings ); - exit; + $result = $this->end_ajax(); + return $result; } function is_json( $string, $strict = false ) { @@ -258,13 +273,17 @@ function plugin_action_links( $links ) { function ajax_clear_log() { delete_option( 'wpmdb_error_log' ); - exit; + $result = $this->end_ajax(); + return $result; } function ajax_get_log() { + ob_start(); $this->output_diagnostic_info(); $this->output_log_file(); - exit; + $return = ob_get_clean(); + $result = $this->end_ajax( $return ); + return $result; } function output_log_file() { @@ -368,15 +387,6 @@ function output_diagnostic_info() { } else { _e( 'Disabled', 'wp-app-store' ); } - echo "\r\n"; - - _e( 'set_time_limit()', 'wp-app-store' ); echo ': '; - if ( $this->set_time_limit_available() ) { - _e('Enabled', 'wp-app-store' ); - } else { - _e( 'Disabled', 'wp-app-store' ); - } - echo "\r\n"; echo "\r\n"; @@ -406,12 +416,13 @@ function remove_wp_plugin_dir( $name ) { function fire_migration_complete() { $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'url' ) ); if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { - echo $this->invalid_content_verification_error . ' (#138)'; - exit; + $result = $this->end_ajax( $this->invalid_content_verification_error . ' (#138)' ); + return $result; } do_action( 'wpmdb_migration_complete', 'pull', $_POST['url'] ); - exit; + $result = $this->end_ajax(); + return $result; } function get_alter_queries() { @@ -430,8 +441,9 @@ function get_alter_queries() { // After table migration, delete old tables and rename new tables removing the temporarily prefix function ajax_finalize_migration() { global $wpdb; + $return = ''; if ( $_POST['intent'] == 'pull' ) { - $this->finalize_migration(); + $return = $this->finalize_migration(); } else { do_action( 'wpmdb_migration_complete', 'push', $_POST['url'] ); @@ -441,24 +453,29 @@ function ajax_finalize_migration() { $data['prefix'] = $wpdb->prefix; $data['type'] = 'push'; $data['location'] = home_url(); + $data['temp_prefix'] = $this->temp_prefix; $data['sig'] = $this->create_signature( $data, $data['key'] ); $ajax_url = trailingslashit( $_POST['url'] ) . 'wp-admin/admin-ajax.php'; $response = $this->remote_post( $ajax_url, $data, __FUNCTION__ ); + ob_start(); echo $response; $this->display_errors(); + $return = ob_get_clean(); } - exit; + $result = $this->end_ajax( $return ); + return $result; } function respond_to_remote_finalize_migration() { - $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent', 'url', 'key', 'form_data', 'stage', 'prefix', 'type', 'location', 'tables' ) ); + $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent', 'url', 'key', 'form_data', 'prefix', 'type', 'location', 'tables', 'temp_prefix' ) ); if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { - echo $this->invalid_content_verification_error . ' (#123)'; - exit; - } - $this->finalize_migration(); - exit; + $result = $this->end_ajax( $this->invalid_content_verification_error . ' (#123)' ); + return $result; } + $return = $this->finalize_migration(); + $result = $this->end_ajax( $return ); + return $result; + } function finalize_migration() { global $wpdb; @@ -466,7 +483,8 @@ function finalize_migration() { $tables = explode( ',', $_POST['tables'] ); $temp_tables = array(); foreach( $tables as $table ) { - $temp_tables[] = $this->temp_prefix . $table; + $temp_prefix = stripslashes( $_POST['temp_prefix'] ); + $temp_tables[] = $temp_prefix . $table; } $sql = "SET FOREIGN_KEY_CHECKS=0;\n"; @@ -481,9 +499,9 @@ function finalize_migration() { $preserved_options = apply_filters( 'wpmdb_preserved_options', $preserved_options ); foreach ( $temp_tables as $table ) { - $sql .= 'DROP TABLE IF EXISTS ' . $this->backquote( substr( $table, strlen( $this->temp_prefix ) ) ) . ';'; + $sql .= 'DROP TABLE IF EXISTS ' . $this->backquote( substr( $table, strlen( $temp_prefix ) ) ) . ';'; $sql .= "\n"; - $sql .= 'RENAME TABLE ' . $this->backquote( $table ) . ' TO ' . $this->backquote( substr( $table, strlen( $this->temp_prefix ) ) ) . ';'; + $sql .= 'RENAME TABLE ' . $this->backquote( $table ) . ' TO ' . $this->backquote( substr( $table, strlen( $temp_prefix ) ) ) . ';'; $sql .= "\n"; } @@ -498,7 +516,11 @@ function finalize_migration() { $sql .= $this->get_alter_queries(); $sql .= "DROP TABLE IF EXISTS " . $this->backquote( $alter_table_name ) . ";\n"; - $this->process_chunk( $sql ); + $process_chunk_result = $this->process_chunk( $sql ); + if( true !== $process_chunk_result ) { + $result = $this->end_ajax( $process_chunk_result ); + return $result; + } $type = ( isset( $_POST['type'] ) ? 'push' : 'pull' ); $location = ( isset( $_POST['location'] ) ? $_POST['location'] : $_POST['url'] ); @@ -510,8 +532,14 @@ function finalize_migration() { $data['sig'] = $this->create_signature( $data, $_POST['key'] ); $ajax_url = trailingslashit( $_POST['url'] ) . 'wp-admin/admin-ajax.php'; $response = $this->remote_post( $ajax_url, $data, __FUNCTION__ ); + ob_start(); echo $response; $this->display_errors(); + $maybe_errors = trim( ob_get_clean() ); + if( false === empty( $maybe_errors ) ) { + $result = $this->end_ajax( $maybe_errors ); + return $result; + } } // flush rewrite rules to prevent 404s and other oddities @@ -531,13 +559,13 @@ function ajax_process_chunk() { $tmp_file_path = wp_tempnam( $tmp_file_name ); if ( !isset( $_FILES['chunk']['tmp_name'] ) || !move_uploaded_file( $_FILES['chunk']['tmp_name'], $tmp_file_path ) ) { - echo 'Could not upload the SQL to the server. (#135)'; - exit; + $result = $this->end_ajax( 'Could not upload the SQL to the server. (#135)' ); + return $result; } if ( false === ( $chunk = file_get_contents( $tmp_file_path ) ) ) { - echo 'Could not read the SQL we\'ve uploaded to the server. (#136)'; - exit; + $result = $this->end_ajax( 'Could not read the SQL we\'ve uploaded to the server. (#136)' ); + return $result; } @unlink( $tmp_file_path ); @@ -545,21 +573,22 @@ function ajax_process_chunk() { $filtered_post['chunk'] = $chunk; if ( !$this->verify_signature( $filtered_post, $this->settings['key'] ) ) { - echo $this->invalid_content_verification_error . ' (#130)'; - exit; + $result = $this->end_ajax( $this->invalid_content_verification_error . ' (#130)' ); + return $result; } if ( $this->settings['allow_push'] != true ) { - echo 'The connection succeeded but the remote site is configured to reject push connections. You can change this in the "settings" tab on the remote site. (#133)'; - exit; + $result = $this->end_ajax( 'The connection succeeded but the remote site is configured to reject push connections. You can change this in the "settings" tab on the remote site. (#133)' ); + return $result; } if( $gzip ) { $filtered_post['chunk'] = gzuncompress( $filtered_post['chunk'] ); } - $this->process_chunk( $filtered_post['chunk'] ); - exit; + $process_chunk_result = $this->process_chunk( $filtered_post['chunk'] ); + $result = $this->end_ajax( $process_chunk_result ); + return $result; } function process_chunk( $chunk ) { @@ -568,7 +597,9 @@ function process_chunk( $chunk ) { $this->set_time_limit(); $queries = array_filter( explode( ";\n", $chunk ) ); + array_unshift( $queries, "SET sql_mode='NO_AUTO_VALUE_ON_ZERO';" ); + ob_start(); $wpdb->show_errors(); if( empty( $wpdb->charset ) ) { $charset = ( defined( 'DB_CHARSET' ) ? DB_CHARSET : 'utf8' ); @@ -577,9 +608,12 @@ function process_chunk( $chunk ) { } foreach( $queries as $query ) { if( false === $wpdb->query( $query ) ) { - exit; + $return = ob_get_clean(); + $result = $this->end_ajax( $return ); + return $result; } } + return true; } function ajax_migrate_table() { @@ -587,6 +621,7 @@ function ajax_migrate_table() { $this->form_data = $this->parse_migration_form_data( $_POST['form_data'] ); + $result = ''; // checks if we're performing a backup, if so, continue with the backup and exit immediately after if ( $_POST['stage'] == 'backup' && $_POST['intent'] != 'savefile' ) { // if performing a push we need to backup the REMOTE machine's DB @@ -598,13 +633,16 @@ function ajax_migrate_table() { $data['primary_keys'] = stripslashes( $data['primary_keys'] ); $data['sig'] = $this->create_signature( $data, $data['key'] ); $response = $this->remote_post( $ajax_url, $data, __FUNCTION__ ); + ob_start(); $this->display_errors(); - echo $response; + $return = ob_get_clean(); + $return .= $response; } else { - $this->handle_table_backup(); - } - exit; + $return = $this->handle_table_backup(); + } + $result = $this->end_ajax( $return ); + return $result; } // Pull and push need to be handled differently for obvious reasons, trigger different code depending on the migration intent (push or pull) @@ -623,11 +661,18 @@ function ajax_migrate_table() { if ( $_POST['intent'] == 'savefile' ) { $this->fp = $this->open( $sql_dump_file_name ); } - $this->export_table( $_POST['table'] ); - $this->display_errors(); + $result = $this->export_table( $_POST['table'] ); if ( $_POST['intent'] == 'savefile' ) { $this->close( $this->fp ); } + ob_start(); + $this->display_errors(); + $maybe_errors = trim( ob_get_clean() ); + if( false === empty( $maybe_errors ) ) { + $result = $this->end_ajax( $maybe_errors ); + return $result; + } + return $result; } else { $data = $_POST; @@ -635,6 +680,7 @@ function ajax_migrate_table() { $data['pull_limit'] = $this->get_sensible_pull_limit(); if( is_multisite() ) { $data['path_current_site'] = $this->get_path_current_site(); + $data['domain_current_site'] = $this->get_domain_current_site(); } $data['prefix'] = $wpdb->prefix; if ( isset( $data['sig'] ) ) { @@ -645,11 +691,17 @@ function ajax_migrate_table() { $data['sig'] = $this->create_signature( $data, $data['key'] ); $response = $this->remote_post( $ajax_url, $data, __FUNCTION__ ); + ob_start(); $this->display_errors(); + $maybe_errors = trim( ob_get_clean() ); + if( false === empty( $maybe_errors ) ) { + $result = $this->end_ajax( $maybe_errors ); + return $result; + } if( strpos( $response, ';' ) === false ) { - echo $response; - exit; + $result = $this->end_ajax( $response ); + return $result; } // returned data is just a big string like this query;query;query;33 @@ -659,29 +711,34 @@ function ajax_migrate_table() { $chunk = substr( $response, 0, strrpos( $response, ";\n" ) + 1 ); if ( ! empty( $chunk ) ) { - $this->process_chunk( $chunk ); + $process_chunk_result = $this->process_chunk( $chunk ); + if( true !== $process_chunk_result ) { + $result = $this->end_ajax( $process_chunk_result ); + return $result; + } } - echo json_encode( + $result = $this->end_ajax( json_encode( array( 'current_row' => $row_information[0], 'primary_keys' => $row_information[1] ) - ); + ) ); } - exit; + return $result; } function respond_to_backup_remote_table() { - $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent', 'url', 'key', 'table', 'form_data', 'stage', 'bottleneck', 'prefix', 'current_row', 'dump_filename', 'last_table', 'gzip', 'primary_keys' ) ); + $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent', 'url', 'key', 'table', 'form_data', 'stage', 'bottleneck', 'prefix', 'current_row', 'dump_filename', 'last_table', 'gzip', 'primary_keys', 'path_current_site', 'domain_current_site' ) ); $filtered_post['primary_keys'] = stripslashes( $filtered_post['primary_keys'] ); if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { - echo $this->invalid_content_verification_error . ' (#137)'; - exit; + $result = $this->end_ajax( $this->invalid_content_verification_error . ' (#137)' ); + return $result; } $this->form_data = $this->parse_migration_form_data( $_POST['form_data'] ); - $this->handle_table_backup(); + $result = $this->handle_table_backup(); + return $result; } function handle_table_backup() { @@ -696,13 +753,23 @@ function handle_table_backup() { if ( $file_created == false ) { $this->db_backup_header(); } - $this->export_table( $_POST['table'] ); + $result = $this->export_table( $_POST['table'] ); + if( isset( $this->fp ) ) { + $this->close( $this->fp ); + } + ob_start(); $this->display_errors(); - $this->close( $this->fp ); + $maybe_errors = trim( ob_get_clean() ); + if( false === empty( $maybe_errors ) ) { + $result = $this->end_ajax( $maybe_errors ); + return $result; + } + + return $result; } function respond_to_process_pull_request() { - $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent', 'url', 'key', 'table', 'form_data', 'stage', 'bottleneck', 'prefix', 'current_row', 'dump_filename', 'pull_limit', 'last_table', 'gzip', 'primary_keys', 'path_current_site' ) ); + $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent', 'url', 'key', 'table', 'form_data', 'stage', 'bottleneck', 'prefix', 'current_row', 'dump_filename', 'pull_limit', 'last_table', 'gzip', 'primary_keys', 'path_current_site', 'domain_current_site' ) ); // verification will fail unless we strip slashes on primary_keys and form_data $filtered_post['primary_keys'] = stripslashes( $filtered_post['primary_keys'] ); @@ -712,19 +779,22 @@ function respond_to_process_pull_request() { } if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { - echo $this->invalid_content_verification_error . ' (#124)'; - exit; + $result = $this->end_ajax( $this->invalid_content_verification_error . ' (#124)' ); + return $result; } if ( $this->settings['allow_pull'] != true ) { - echo 'The connection succeeded but the remote site is configured to reject pull connections. You can change this in the "settings" tab on the remote site. (#132)'; - exit; + $result = $this->end_ajax( 'The connection succeeded but the remote site is configured to reject pull connections. You can change this in the "settings" tab on the remote site. (#132)' ); + return $result; } $this->maximum_chunk_size = $_POST['pull_limit']; $this->export_table( $_POST['table'] ); + ob_start(); $this->display_errors(); - exit; + $return = ob_get_clean(); + $result = $this->end_ajax( $return ); + return $result; } // Occurs right before the first table is migrated / backed up during the migration process @@ -745,7 +815,11 @@ function ajax_initiate_migration() { $create_alter_table_query = $this->get_create_alter_table_query(); // sets up our table to store 'ALTER' queries - $this->process_chunk( $create_alter_table_query ); + $process_chunk_result = $this->process_chunk( $create_alter_table_query ); + if( true !== $process_chunk_result ) { + $result = $this->end_ajax( $process_chunk_result ); + return $result; + } if ( $this->gzip() && isset( $this->form_data['gzip_file'] ) ) { $return['dump_filename'] .= '.gz'; @@ -771,18 +845,20 @@ function ajax_initiate_migration() { if ( false === $response ) { $return = array( 'wpmdb_error' => 1, 'body' => $this->error ); - } - else{ - $return = array( - 'body' => stripslashes( $response ), - ); - $return = json_decode( $response, ARRAY_A ); + $result = $this->end_ajax( json_encode( $return ) ); + return $result; } + $return = json_decode( stripslashes( $response ), ARRAY_A ); + if( $_POST['intent'] == 'pull' ) { // sets up our table to store 'ALTER' queries $create_alter_table_query = $this->get_create_alter_table_query(); - $this->process_chunk( $create_alter_table_query ); + $process_chunk_result = $this->process_chunk( $create_alter_table_query ); + if( true !== $process_chunk_result ) { + $result = $this->end_ajax( $process_chunk_result ); + return $result; + } } if( ! empty( $this->form_data['create_backup'] ) && $_POST['intent'] == 'pull' ) { @@ -793,12 +869,11 @@ function ajax_initiate_migration() { } - $return['dump_filename'] = ( empty( $return['dump_filename'] ) ? '' : $return['dump_filename'] ); - $return['dump_url'] = ( empty( $return['dump_url'] ) ? '' : $return['dump_url'] ); + $return['dump_filename'] = ( empty( $return['dump_filename'] ) ) ? '' : $return['dump_filename']; + $return['dump_url'] = ( empty( $return['dump_url'] ) ) ? '' : $return['dump_url']; - echo json_encode( $return ); - - exit; + $result = $this->end_ajax( json_encode( $return ) ); + return $result; } // End point for the above remote_post call, ensures that the verification string is valid before continuing with the migration @@ -826,19 +901,23 @@ function respond_to_remote_initiate_migration() { $return['dump_url'] = $this->get_sql_dump_info( 'backup', 'url' ); } - echo json_encode( $return ); - if( $_POST['intent'] == 'push' ) { // sets up our table to store 'ALTER' queries $create_alter_table_query = $this->get_create_alter_table_query(); - $this->process_chunk( $create_alter_table_query ); + $process_chunk_result = $this->process_chunk( $create_alter_table_query ); + if( true !== $process_chunk_result ) { + $result = $this->end_ajax( $process_chunk_result ); + return $result; + } } - exit; + $result = $this->end_ajax( json_encode( $return ) ); + return $result; } function ajax_save_profile() { $profile = $this->parse_migration_form_data( $_POST['profile'] ); + $profile = wp_parse_args( $profile, $this->checkbox_options ); if ( isset( $profile['save_migration_profile_option'] ) && $profile['save_migration_profile_option'] == 'new' ) { $profile['name'] = $profile['create_new_profile']; $this->settings['profiles'][] = $profile; @@ -850,33 +929,36 @@ function ajax_save_profile() { $this->settings['profiles'][$key]['name'] = $name; } update_option( 'wpmdb_settings', $this->settings ); - echo count( $this->settings['profiles'] ) - 1; - exit; + $result = $this->end_ajax( count( $this->settings['profiles'] ) - 1 ); + return $result; } function ajax_save_setting() { $this->settings[$_POST['setting']] = ( $_POST['checked'] == 'false' ? false : true ); update_option( 'wpmdb_settings', $this->settings ); - exit; + $result = $this->end_ajax(); + return $result; } function ajax_delete_migration_profile() { $key = $_POST['profile_id']; + $return = ''; if ( isset( $this->settings['profiles'][$key] ) ) { unset( $this->settings['profiles'][$key] ); update_option( 'wpmdb_settings', $this->settings ); } else { - echo '-1'; + $return = '-1'; } - exit; + $result = $this->end_ajax( $return ); + return $result; } function ajax_reset_api_key() { $this->settings['key'] = $this->generate_key(); update_option( 'wpmdb_settings', $this->settings ); - printf( "%s\n%s", site_url( '', 'https' ), $this->settings['key'] ); - exit; + $result = $this->end_ajax( sprintf( "%s\n%s", site_url( '', 'https' ), $this->settings['key'] ) ); + return $result; } // AJAX endpoint for when the user pastes into the connection info box (or when they click "connect") @@ -898,23 +980,23 @@ function ajax_verify_connection_to_remote_site() { if ( false === $response ) { $return = array( 'wpmdb_error' => 1, 'body' => $this->error ); - echo json_encode( $return ); - exit; + $result = $this->end_ajax( json_encode( $return ) ); + return $result; } $response = unserialize( trim( $response ) ); if ( isset( $response['error'] ) && $response['error'] == 1 ) { $return = array( 'wpmdb_error' => 1, 'body' => $response['message'] ); - echo json_encode( $return ); - exit; + $result = $this->end_ajax( json_encode( $return ) ); + return $result; } $response['scheme'] = $url_bits['scheme']; $return = json_encode( $response ); - echo $return; - exit; + $result = $this->end_ajax( $return ); + return $result; } // End point for the above remote_post call, returns table information, absolute file path, table prefix, etc @@ -927,15 +1009,15 @@ function respond_to_verify_connection_to_remote_site() { if ( !$this->verify_signature( $filtered_post, $this->settings['key'] ) ) { $return['error'] = 1; $return['message'] = $this->invalid_content_verification_error . ' (#120) Try again?'; - echo serialize( $return ); - exit; + $result = $this->end_ajax( serialize( $return ) ); + return $result; } if ( !isset( $this->settings['allow_' . $_POST['intent']] ) || $this->settings['allow_' . $_POST['intent']] != true ) { $return['error'] = 1; $return['message'] = 'The connection succeeded but the remote site is configured to reject ' . $_POST['intent'] . ' connections. You can change this in the "settings" tab on the remote site. (#122) Try again?'; - echo serialize( $return ); - exit; + $result = $this->end_ajax( serialize( $return ) ); + return $result; } $return['tables'] = $this->get_tables(); @@ -956,9 +1038,10 @@ function respond_to_verify_connection_to_remote_site() { $return['post_types'] = $this->get_post_types(); $return['write_permissions'] = ( is_writeable( $this->get_upload_info( 'path' ) ) ? '1' : '0' ); $return['upload_dir_long'] = $this->get_upload_info( 'path' ); + $return['temp_prefix'] = $this->temp_prefix; $return = apply_filters( 'wpmdb_establish_remote_connection_data', $return ); - echo serialize( $return ); - exit; + $result = $this->end_ajax( serialize( $return ) ); + return $result; } function format_table_sizes( $size ) { @@ -975,20 +1058,6 @@ function generate_key() { return $key; } - // Get only the table beginning with our DB prefix or temporary prefix, also skip views - function get_tables( $scope = 'regular' ) { - global $wpdb; - $prefix = ( $scope == 'temp' ? $this->temp_prefix : $wpdb->prefix ); - $tables = $wpdb->get_results( 'SHOW FULL TABLES', ARRAY_N ); - foreach ( $tables as $table ) { - if ( ( ( $scope == 'temp' || $scope == 'prefix' ) && 0 !== strpos( $table[0], $prefix ) ) || $table[1] == 'VIEW' ) { - continue; - } - $clean_tables[] = $table[0]; - } - return apply_filters( 'wpmdb_tables', $clean_tables, $scope ); - } - function get_post_types() { global $wpdb; @@ -1128,10 +1197,23 @@ function options_page() { addons as $addon_basename => $addon ) { + if( false == $this->is_addon_outdated( $addon_basename ) || false == is_plugin_active( $addon_basename ) ) continue; + $update_url = wp_nonce_url( network_admin_url( 'update.php?action=upgrade-plugin&plugin=' . urlencode( $addon_basename ) ), 'upgrade-plugin_' . $addon_basename ); + ?> +
    +

    + Update Required — + Update Now', $addon['name'], $this->get_installed_version( $addon_basename ), $update_url ); ?> +

    +
    +

    @@ -1396,7 +1478,11 @@ function export_table( $table ) { $alter_table_name = $this->get_alter_table_name(); $insert = sprintf( "INSERT INTO %s ( `query` ) VALUES ( '%s' );\n", $this->backquote( $alter_table_name ), esc_sql( $alter_table_query ) ); if ( $this->form_data['action'] == 'savefile' || $_POST['stage'] == 'backup' ) { - $this->process_chunk( $insert ); + $process_chunk_result = $this->process_chunk( $insert ); + if( true !== $process_chunk_result ) { + $result = $this->end_ajax( $process_chunk_result ); + return $result; + } } else { $this->stow( $insert ); @@ -1463,10 +1549,12 @@ function export_table( $table ) { } } + $first_select = true; if( ! empty( $_POST['primary_keys'] ) ) { $_POST['primary_keys'] = trim( $_POST['primary_keys'] ); if( ! empty( $_POST['primary_keys'] ) && is_serialized( $_POST['primary_keys'] ) ) { $this->primary_keys = unserialize( stripslashes( $_POST['primary_keys'] ) ); + $first_select = false; } } @@ -1475,53 +1563,46 @@ function export_table( $table ) { $insert_buffer = $insert_query_template = "INSERT INTO " . $this->backquote( $table_name ) . " ( " . $fields . ") VALUES\n"; do { - $join = ''; + $join = array(); $where = 'WHERE 1=1'; $order_by = ''; // We need ORDER BY here because with LIMIT, sometimes it will return // the same results from the previous query and we'll have duplicate insert statements if ( isset( $this->form_data['exclude_spam'] ) ) { - if ( $wpdb->comments == $table || preg_match( '/' . $wpdb->prefix . '[0-9]+_comments/', $table ) ) { + if ( $this->table_is( 'comments', $table ) ) { $where .= ' AND comment_approved != "spam"'; } - elseif ( $wpdb->commentmeta == $table || preg_match( '/' . $wpdb->prefix . '[0-9]+_commentmeta/', $table ) ) { - $comment_table = $wpdb->comments; - $commentmeta_table = $wpdb->commentmeta; - $blog_id = str_replace( array( $wpdb->prefix, '_commentmeta' ) , array( '', '' ), $table ); - if( is_multisite() && ! empty( $blog_id ) ) { - $comment_table = $wpdb->prefix . $blog_id . '_comments'; - $commentmeta_table = $wpdb->prefix . $blog_id . '_commentmeta'; - } - $join .= sprintf( 'INNER JOIN %1$s - ON %1$s.comment_ID = %2$s.comment_id AND %1$s.comment_approved != \'spam\'', - $this->backquote( $comment_table ), $this->backquote( $commentmeta_table ) ); + elseif ( $this->table_is( 'commentmeta', $table ) ) { + extract( $this->get_ms_compat_table_names( array( 'commentmeta', 'comments' ), $table ) ); + $join[] = sprintf( 'INNER JOIN %1$s ON %1$s.comment_ID = %2$s.comment_id', $this->backquote( $comments_table ), $this->backquote( $commentmeta_table ) ); + $where .= sprintf( ' AND %1$s.comment_approved != \'spam\'', $this->backquote( $comments_table ) ); } } if ( isset( $this->form_data['post_type_migrate_option'] ) && $this->form_data['post_type_migrate_option'] == 'migrate_select_post_types' && ! empty( $this->form_data['select_post_types'] ) ) { - $post_types = array(); - foreach( $this->form_data['select_post_types'] as $post_type ) { - $post_types[] = '\'' . $post_type . '\''; + $post_types = '\'' . implode( '\', \'', $this->form_data['select_post_types'] ) . '\''; + if( $this->table_is( 'posts', $table ) ) { + $where .= ' AND `post_type` IN ( ' . $post_types . ' )'; } - if( $wpdb->posts == $table || preg_match( '/' . $wpdb->prefix . '[0-9]+_posts/', $table ) ) { - $where .= ' AND `post_type` IN ( '; - $where .= implode( ', ', $post_types ) . ' )'; + elseif( $this->table_is( 'postmeta', $table ) ) { + extract( $this->get_ms_compat_table_names( array( 'postmeta', 'posts' ), $table ) ); + $join[] = sprintf( 'INNER JOIN %1$s ON %1$s.ID = %2$s.post_id', $this->backquote( $posts_table ), $this->backquote( $postmeta_table ) ); + $where .= sprintf( ' AND %1$s.post_type IN ( ' . $post_types . ' )', $this->backquote( $posts_table ) ); } - elseif( $wpdb->postmeta == $table || preg_match( '/' . $wpdb->prefix . '[0-9]+_postmeta/', $table ) ) { - $post_table = $wpdb->posts; - $postmeta_table = $wpdb->postmeta; - $blog_id = str_replace( array( $wpdb->prefix, '_postmeta' ) , array( '', '' ), $table ); - if( is_multisite() && ! empty( $blog_id ) ) { - $post_table = $wpdb->prefix . $blog_id . '_posts'; - $postmeta_table = $wpdb->prefix . $blog_id . '_postmeta'; - } - $join .= sprintf( 'INNER JOIN %1$s - ON %1$s.ID = %2$s.post_id AND %1$s.post_type IN ( ' . implode( ', ', $post_types ) . ' )' , - $this->backquote( $post_table ), $this->backquote( $postmeta_table ) ); + elseif ( $this->table_is( 'comments', $table ) ) { + extract( $this->get_ms_compat_table_names( array( 'comments', 'posts' ), $table ) ); + $join[] = sprintf( 'INNER JOIN %1$s ON %1$s.ID = %2$s.comment_post_ID', $this->backquote( $posts_table ), $this->backquote( $comments_table ) ); + $where .= sprintf( ' AND %1$s.post_type IN ( ' . $post_types . ' )', $this->backquote( $posts_table ) ); + } + elseif( $this->table_is( 'commentmeta', $table ) ) { + extract( $this->get_ms_compat_table_names( array( 'commentmeta', 'posts', 'comments' ), $table ) ); + $join[] = sprintf( 'INNER JOIN %1$s ON %1$s.comment_ID = %2$s.comment_id', $this->backquote( $comments_table ), $this->backquote( $commentmeta_table ) ); + $join[] = sprintf( 'INNER JOIN %2$s ON %2$s.ID = %1$s.comment_post_ID', $this->backquote( $comments_table ), $this->backquote( $posts_table ) ); + $where .= sprintf( ' AND %1$s.post_type IN ( ' . $post_types . ' )', $this->backquote( $posts_table ) ); } } - if ( true === apply_filters( 'wpmdb_exclude_transients', true ) && ( $wpdb->options == $table || ( isset( $wpdb->sitemeta ) && $wpdb->sitemeta == $table ) || preg_match( '/' . $wpdb->prefix . '[0-9]+_options/', $table ) ) ) { + if ( true === apply_filters( 'wpmdb_exclude_transients', true ) && ( $this->table_is( 'options', $table ) || ( isset( $wpdb->sitemeta ) && $wpdb->sitemeta == $table ) ) ) { $col_name = 'option_name'; if( isset( $wpdb->sitemeta ) && $wpdb->sitemeta == $table ) { @@ -1538,31 +1619,42 @@ function export_table( $table ) { $primary_keys_keys = array_map( array( $this, 'backquote' ), $primary_keys_keys ); $order_by = 'ORDER BY ' . implode( ',', $primary_keys_keys ); - $where .= ' AND '; - - $temp_primary_keys = $this->primary_keys; - - $primary_key_count = count( $temp_primary_keys ); - for( $j = 0; $j < $primary_key_count; $j++ ) { - $where .= ( $j == 0 ? '( ' : ' OR ( ' ); - $i = 0; - foreach( $temp_primary_keys as $primary_key => $value ) { - $where .= ( $i == 0 ? '' : ' AND ' ); - $operator = ( count( $temp_primary_keys ) - 1 == $i ? '>' : '=' ); - $operator = ( $value == 0 && $operator == '>' ) ? '>=' : $operator; - $where .= sprintf( '%s %s %s', $this->backquote( $primary_key ), $operator, $value ); - ++$i; + $limit = "LIMIT $row_inc"; + if( false == $first_select ) { + $where .= ' AND '; + + $temp_primary_keys = $this->primary_keys; + $primary_key_count = count( $temp_primary_keys ); + + // build a list of clauses, iteratively reducing the number of fields compared in the compound key + // e.g. (a = 1 AND b = 2 AND c > 3) OR (a = 1 AND b > 2) OR (a > 1) + $clauses = array(); + for( $j = 0; $j < $primary_key_count; $j++ ) { + // build a subclause for each field in the compound index + $subclauses = array(); + $i = 0; + foreach( $temp_primary_keys as $primary_key => $value ) { + // only the last field in the key should be different in this subclause + $operator = ( count( $temp_primary_keys ) - 1 == $i ? '>' : '=' ); + $subclauses[] = sprintf( '%s %s %s', $this->backquote( $primary_key ), $operator, $wpdb->prepare( '%s', $value ) ); + ++$i; + } + + // remove last field from array to reduce fields in next clause + array_pop( $temp_primary_keys ); + + // join subclauses into a single clause + // NB: AND needs to be wrapped in () as it has higher precedence than OR + $clauses[] = '( ' . implode( ' AND ', $subclauses ) . ' )'; } - $tmp = $temp_primary_keys; - $keys = array_keys( $tmp ); - $end = end( $keys ); - unset( $temp_primary_keys[$end] ); - $where .= ' )'; + // join clauses into a single clause + // NB: OR needs to be wrapped in () as it has lower precedence than AND + $where .= '( ' . implode( ' OR ', $clauses ) . ' )'; } - - $limit = "LIMIT $row_inc"; + $first_select = false; } + $join = implode( ' ', array_unique( $join ) ); $join = apply_filters( 'wpmdb_rows_join', $join, $table ); $where = apply_filters( 'wpmdb_rows_where', $where, $table ); $order_by = apply_filters( 'wpmdb_rows_order_by', $order_by, $table ); @@ -1603,7 +1695,23 @@ function export_table( $table ) { } } - if ( 'guid' != $key || ( isset( $this->form_data['replace_guids'] ) && ( $wpdb->posts == $table || preg_match( '/' . $wpdb->prefix . '[0-9]+_posts/', $table ) ) ) ) { + if( is_multisite() && 'domain' == $key && $_POST['stage'] != 'backup' && ( $wpdb->site == $table || $wpdb->blogs == $table ) ) { + if( ! empty( $_POST['domain_current_site'] ) ) { + $main_domain_replace = $_POST['domain_current_site']; + } + else { + $url = parse_url( $this->form_data['replace_new'][1] ); + $main_domain_replace = $url['host']; + } + + $main_domain_find = sprintf( "/%s/", $this->get_domain_current_site() ); + $domain_replaces[$main_domain_find] = $main_domain_replace; + $domain_replaces = apply_filters( 'wpmdb_domain_replaces', $domain_replaces ); + + $value = preg_replace( array_keys( $domain_replaces ), array_values( $domain_replaces ), $value ); + } + + if ( 'guid' != $key || ( isset( $this->form_data['replace_guids'] ) && $this->table_is( 'posts', $table ) ) ) { if ( $_POST['stage'] != 'backup' ) { $value = $this->recursive_unserialize_replace( $value ); } @@ -1634,7 +1742,7 @@ function export_table( $table ) { $this->stow( $insert_buffer ); $insert_buffer = $insert_query_template; $query_size = 0; - $this->transfer_chunk(); + return $this->transfer_chunk(); } if ( ( $query_size + strlen( $insert_line ) ) > $this->max_insert_string_len && $insert_buffer != $insert_query_template ) { @@ -1690,10 +1798,28 @@ function export_table( $table ) { } $this->row_tracker = -1; - $this->transfer_chunk(); + return $this->transfer_chunk(); } // end backup_table() + function table_is( $desired_table, $given_table ) { + global $wpdb; + return ( $wpdb->{$desired_table} == $given_table || preg_match( '/' . $wpdb->prefix . '[0-9]+_' . $desired_table . '/', $given_table ) ); + } + + function get_ms_compat_table_names( $tables, $queried_table ) { + global $wpdb; + $blog_id = str_replace( array( $wpdb->prefix, '_' . $tables[0] ) , array( '', '' ), $queried_table ); + $ms_compat_table_names = array(); + foreach( $tables as $table ) { + $ms_compat_table_names[$table . '_table'] = $wpdb->{$table}; + if( is_multisite() && ! empty( $blog_id ) ) { + $ms_compat_table_names[$table . '_table'] = sprintf( '%s%s_%s', $wpdb->prefix, $blog_id, $table ); + } + } + return $ms_compat_table_names; + } + /** * Take a serialized array and unserialize it replacing elements as needed and * unserialising any subordinate arrays and performing the replace on those too. @@ -1776,6 +1902,7 @@ function db_backup_header() { $this->stow( "# " . sprintf( __( 'Database: %s', 'wp-migrate-db' ), $this->backquote( DB_NAME ) ) . "\n", false ); $this->stow( "# --------------------------------------------------------\n\n", false ); $this->stow( "/*!40101 SET NAMES $charset */;\n\n", false ); + $this->stow( "SET sql_mode='NO_AUTO_VALUE_ON_ZERO';\n\n", false ); } function gzip() { @@ -1794,6 +1921,7 @@ function open( $filename = '', $mode = 'a' ) { function close( $fp ) { if ( $this->gzip() && isset( $this->form_data['gzip_file'] ) ) gzclose( $fp ); else fclose( $fp ); + unset( $this->fp ); } function stow( $query_line, $replace = true ) { @@ -1821,18 +1949,18 @@ function stow( $query_line, $replace = true ) { function transfer_chunk() { if( $_POST['intent'] == 'savefile' || $_POST['stage'] == 'backup' ) { $this->close( $this->fp ); - echo json_encode( + $result = $this->end_ajax( json_encode( array( 'current_row' => $this->row_tracker, 'primary_keys' => serialize( $this->primary_keys ) ) - ); - exit; + ) ); + return $result; } if ( $_POST['intent'] == 'pull' ) { - echo $this->row_tracker . ',' . serialize( $this->primary_keys ); - exit; + $result = $this->end_ajax( $this->row_tracker . ',' . serialize( $this->primary_keys ) ); + return $result; } $chunk_gzipped = '0'; @@ -1852,20 +1980,22 @@ function transfer_chunk() { $ajax_url = trailingslashit( $this->remote_url ) . 'wp-admin/admin-ajax.php'; $response = $this->remote_post( $ajax_url, $data, __FUNCTION__ ); + ob_start(); $this->display_errors(); - $response = trim( $response ); + $response = ob_get_clean(); + $response .= trim( $response ); if( ! empty( $response ) ) { - echo $response; - exit; + $result = $this->end_ajax( $response ); + return $result; } - echo json_encode( + $result = $this->end_ajax( json_encode( array( 'current_row' => $this->row_tracker, 'primary_keys' => serialize( $this->primary_keys ) ) - ); - exit; + ) ); + return $result; } /** @@ -1939,19 +2069,21 @@ function load_assets() { $plugins_url = trailingslashit( plugins_url() ) . trailingslashit( $this->plugin_slug ); + $version = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? time() : $this->get_installed_version(); + $src = $plugins_url . 'asset/css/styles.css'; - wp_enqueue_style( 'wp-migrate-db-styles', $src, array(), $this->get_installed_version() ); + wp_enqueue_style( 'wp-migrate-db-styles', $src, array(), $version ); $src = $plugins_url . 'asset/js/common.js'; - wp_enqueue_script( 'wp-migrate-db-common', $src, NULL, $this->get_installed_version(), true ); + wp_enqueue_script( 'wp-migrate-db-common', $src, NULL, $version, true ); $src = $plugins_url . 'asset/js/hook.js'; - wp_enqueue_script( 'wp-migrate-db-hook', $src, NULL, $this->get_installed_version(), true ); + wp_enqueue_script( 'wp-migrate-db-hook', $src, NULL, $version, true ); do_action( 'wpmdb_load_assets' ); $src = $plugins_url . 'asset/js/script.js'; - wp_enqueue_script( 'wp-migrate-db-script', $src, array( 'jquery' ), $this->get_installed_version(), true ); + wp_enqueue_script( 'wp-migrate-db-script', $src, array( 'jquery' ), $version, true ); wp_enqueue_script('jquery'); wp_enqueue_script('jquery-ui-core'); @@ -2008,9 +2140,6 @@ function admin_head_connection_info() { var wpmdb_max_request = 'settings['max_request'] ?>'; var wpmdb_bottleneck = 'get_bottleneck( 'max' ); ?>'; var wpmdb_this_uploads_dir = 'get_short_uploads_dir() ); ?>'; - settings['profiles'][$_GET['wpmdb-profile']]['select_tables'] ) ) : ?> - var wpmdb_loaded_tables = 'settings['profiles'][$_GET['wpmdb-profile']]['select_tables'] ); ?>'; - var wpmdb_write_permission = get_upload_info( 'path' ) ) ? 'true' : 'false' ); ?>; @@ -2036,7 +2165,7 @@ function maybe_update_profile( $profile, $profile_id ) { function get_path_from_url( $url ) { $parts = parse_url( $url ); - return trailingslashit( $parts['path'] ); + return ( ! empty( $parts['path'] ) ) ? trailingslashit( $parts['path'] ) : '/'; } function get_path_current_site() { @@ -2064,11 +2193,26 @@ function return_bytes($val) { $val *= 1024; case 'k': $val *= 1024; + break; default : $val = false; + break; } return $val; } + function end_ajax( $return = false ) { + if( defined( 'DOING_WPMDB_TESTS' ) ) { + return ( false === $return ) ? NULL : $return; + } + + echo ( false === $return ) ? '' : $return; + exit; + } + + function maybe_checked( $option ) { + echo ( isset( $option ) && $option == '1' ) ? ' checked="checked"' : ''; + } + } From 5ab3ab9713fd30a5ead58224712a3ced909f5c48 Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Sun, 30 Mar 2014 22:05:08 -0500 Subject: [PATCH 22/52] add another video to the readme --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index af144eb..741e05a 100755 --- a/README.md +++ b/README.md @@ -55,6 +55,11 @@ http://www.youtube.com/watch?v=FjTzNqAlQE0 This screencast demonstrates how you can push a local WordPress database you've been using for development to a staging environment. +###Media Files Addon Demo +http://www.youtube.com/watch?v=0aR8-jC2XXM + +A short demo of how the [Media Files addon](https://github.com/slang800/wp-migrate-db-media-files) allows you to sync up your WordPress Media Libraries. + ##Isn't this the same as WP Migrate DB Pro? No, of course not, don't be silly. I took out the license verification code, a really shady looking PressTrends reporter, and the tab for installing the Media Files addon before I published 1.4. Release 1.3 was the same as [WP Migrate DB Pro](https://deliciousbrains.com/wp-migrate-db-pro), but I've made several improvements since then. From 6099b11465d9c38f3bd341797551df2194f250cb Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Sun, 30 Mar 2014 22:06:28 -0500 Subject: [PATCH 23/52] remove email help section, replace with GH issues --- template/help.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/template/help.php b/template/help.php index 6ed4392..a98523e 100755 --- a/template/help.php +++ b/template/help.php @@ -21,8 +21,8 @@

    -

    Email Support

    -
    +

    Support

    +

    Please report bugs or ask questions in the GitHub Issue Tracker.

    Diagnostic Info & Error Log

    @@ -44,5 +44,4 @@
    - -
    +
    From 3ce6ee4cfe47a1f39deb0deee8f950e43587ba7c Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Mon, 16 Jun 2014 19:53:21 -0400 Subject: [PATCH 24/52] rename wp-migrate-db to wp-sync-db add in a short explanation as to why it's renamed rewrite a bunch of the readme --- README.md | 80 ++-- asset/css/styles.css | 422 ++++++++++----------- asset/js/common.js | 6 +- asset/js/hook.js | 30 +- asset/js/script.js | 126 +++--- asset/sass/_mp6.scss | 4 +- asset/sass/styles.scss | 4 +- class/{wpmdb-addon.php => wpsdb-addon.php} | 26 +- class/{wpmdb-base.php => wpsdb-base.php} | 24 +- class/{wpmdb.php => wpsdb.php} | 236 ++++++------ template/help.php | 2 +- template/migrate.php | 20 +- template/profile.php | 6 +- wp-migrate-db.php => wp-sync-db.php | 20 +- 14 files changed, 506 insertions(+), 500 deletions(-) rename class/{wpmdb-addon.php => wpsdb-addon.php} (67%) rename class/{wpmdb-base.php => wpsdb-base.php} (94%) rename class/{wpmdb.php => wpsdb.php} (90%) rename wp-migrate-db.php => wp-sync-db.php (57%) diff --git a/README.md b/README.md index 741e05a..7a4b7c8 100755 --- a/README.md +++ b/README.md @@ -1,69 +1,75 @@ -#WP Migrate DB -WP Migrate DB eliminates the manual work of migrating a WP database. Copy your db from one WP install to another with a single-click in your dashboard. Especially handy for syncing a local development database with a live site. - -Donate [here](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5VPMGLLK94XJC) to support [bradt](https://github.com/bradt), the original author of [WP Migrate DB](https://github.com/bradt/wp-migrate-db). And check out [WP Migrate DB Pro](https://deliciousbrains.com/wp-migrate-db-pro/pricing/) for a variant of the plugin that has dedicated customer support. +# WP Sync DB +WP Sync DB eliminates the manual work of migrating a WP database. Copy your db from one WP install to another with a single-click in your dashboard. Especially handy for syncing a local development database with a live site.

    -##Description -WP Migrate DB exports your database as a MySQL data dump (much like phpMyAdmin), does a find and replace on URLs and file paths, then allows you to save it to your computer, or send it directly to another WordPress instance. It is perfect for developers who develop locally and need to move their WordPress site to a staging or production server. +## Description +WP Sync DB exports your database as a MySQL data dump (much like phpMyAdmin), does a find and replace on URLs and file paths, then allows you to save it to your computer, or send it directly to another WordPress instance. It is perfect for developers who develop locally and need to move their WordPress site to a staging or production server. + +### Selective Sync +WP Sync DB lets you choose which DB tables are migrated. Have a huge analytics table you'd rather not send? Simply deselect it and it won't be synced. + +### Bi-directional Sync -###Pull: Quickly Replace a Local DB with a Remote DB -Let's say you're developing locally but need the latest data from the live database. With WP Migrate DB installed on both sites, you can quickly and easily pull the live database down and replace your local database with a few clicks. +#### Pull: Replace a Local DB with a Remote DB +If you have a test site setup locally but you need the latest data from the production server, just install WP Sync DB on both sites and you can pull the live database down, replacing your local database in just a few clicks. -###Push: Easily Replace a Remote DB with a Local DB -Let's say you have a new feature to add to a site that's been live for a while. You pull down a fresh copy of the live database and start hacking. When the feature is complete, you push your local database to the staging site with your changes so the client can review before making the feature live. How's that for a workflow? +#### Push: Replace a Remote DB with a Local DB +If you're developing a new feature for a site that's already live, you likely need to tweak your settings locally before deploying. Once you've perfected your configuration on your development machine, it's easy to send the settings to your production server. Just push to the server, replacing your remote database with your local one. -###Save Time with Automatic Find & Replace -When migrating a WordPress site, URLs in the content, widgets, menus, etc need to be updated to the new site's URL. Doing this manually is annoying, time consuming, and can be very frustrating when dealing with serialized data (like widgets). WP Migrate DB does all of this for you. +### Database Export & Backup +Not only can WP Sync DB pull and push your DB: it can export your DB to an SQL file that you can save and backup wherever you want. No need to ssh into your machine or open up phpMyAdmin. -###Convenient Database Export -In addition to pulling & pushing, in just a couple of clicks you can save an SQL file of your database to your computer. No need to drop into ssh or phpMyAdmin. +### Encrypted Transfers +All data is sent over SSL to prevent your database from being read during the transfer. WP Sync DB also uses HMAC encryption to sign and verify every request. This ensures that all requests are coming from an authorized server and haven't been tampered with en route. -###Select the Tables You Want to Migrate -WP Migrate DB gives you control over which database tables are migrated. Have a huge stats table you'd rather not migrate? Deselect it. Easy. +### Automatic Find & Replace +When migrating a WordPress site, URLs in the content, widgets, menus, etc need to be updated to the new site's URL. Doing this manually is annoying, time consuming, and very error-prone. WP Sync DB does all of this for you. -###Stress Tested on Massive Databases -Have a huge database? No problem. We've tested migration of tables with over 100MB of data. +### Stress Tested on Massive Sites +Huge database? No prob. WP Sync DB has been tested with tables several GBs in size. -###Intelligently Detects Environment Limitations -WP Migrate DB analyses both the remote and local environments to detect limitations and optimize performance. For example, we detect MySQL's `max_allowed_packet_size` setting and adjust how much SQL we execute at a time. Not only does this avoid failure, but allows us to increase performance. +### Detect Limitations Automatically +WP Sync DB checks both the remote and local servers to determine limitations and optimize for performance. For example, we detect the MySQL `max_allowed_packet_size` and adjust how much SQL we execute at a time. -###Sync Media Libraries Between Installations -Using the optional [WP Migrate DB Media Files](https://github.com/slang800/wp-migrate-db-media-files) addon, you can have media files synced between installs too. +### Sync Media Libraries Between Installations +Using the optional [WP Sync DB Media Files](https://github.com/slang800/wp-migrate-db-media-files) addon, you can have media files synced between installs too. -##Installation -1. Install [github-updater](https://github.com/afragen/github-updater) by downloading the latest zip [here](https://github.com/afragen/github-updater/releases). We rely on this plugin for updating WP Migrate DB directly from this git repo. -2. Install WP Migrate DB by downloading the latest zip [here](https://github.com/slang800/wp-migrate-db/releases). Both github-updater and WP Migrate DB will now download their own updates automatically, so you will never need to go through that tedious zip downloading again. -3. Access the WP Migrate DB menu option under Tools. -4. Install the optional [WP Migrate DB Media Files](https://github.com/slang800/wp-migrate-db-media-files) addon. +## Installation +1. Install [github-updater](https://github.com/afragen/github-updater) by downloading the latest zip [here](https://github.com/afragen/github-updater/releases). We rely on this plugin for updating WP Sync DB directly from this git repo. +2. Install WP Sync DB by downloading the latest zip [here](https://github.com/slang800/wp-sync-db/releases). Both github-updater and WP Sync DB will now download their own updates automatically, so you will never need to go through that tedious zip downloading again. +3. Access the WP Sync DB menu option under Tools. +4. Install the optional [WP Sync DB Media Files](https://github.com/slang800/wp-migrate-db-media-files) addon. -##Help Videos +## Help Videos -###Feature Walkthrough +### Feature Walkthrough http://www.youtube.com/watch?v=SlfSuuePYaQ -A brief walkthrough of the WP Migrate DB plugin showing all of the different options and explaining them. +A brief walkthrough of the WP Sync DB plugin showing all of the different options and explaining them. -###Pulling Live Data Into Your Local Development Environment +### Pulling Live Data Into Your Local Development Environment http://www.youtube.com/watch?v=IFdHIpf6jjc This screencast demonstrates how you can pull data from a remote, live WordPress install and update the data in your local development environment. -###Pushing Local Development Data to a Staging Environment +### Pushing Local Development Data to a Staging Environment http://www.youtube.com/watch?v=FjTzNqAlQE0 This screencast demonstrates how you can push a local WordPress database you've been using for development to a staging environment. -###Media Files Addon Demo +### Media Files Addon Demo http://www.youtube.com/watch?v=0aR8-jC2XXM A short demo of how the [Media Files addon](https://github.com/slang800/wp-migrate-db-media-files) allows you to sync up your WordPress Media Libraries. -##Isn't this the same as WP Migrate DB Pro? -No, of course not, don't be silly. I took out the license verification code, a really shady looking PressTrends reporter, and the tab for installing the Media Files addon before I published 1.4. Release 1.3 was the same as [WP Migrate DB Pro](https://deliciousbrains.com/wp-migrate-db-pro), but I've made several improvements since then. +## Similar Tools + - [Interconnect IT's Search & Replace](https://github.com/interconnectit/Search-Replace-DB) -Also, because this plugin is free I'm not _obligated_ to help you like [bradt](https://github.com/bradt) is if you purchased WP Migrate DB Pro. Any help that I give is just because I'm a nice person and I enjoy helping people. Also, I only offer support through the public [issues manager](https://github.com/slang800/wp-migrate-db/issues). If you're an agency and need support at the drop of a hat, buy the plugin from bradt. +## Isn't this the same as WP Migrate DB Pro? +No, of course not, don't be silly. I took out the license verification code, a really shady looking PressTrends reporter, and the tab for installing the Media Files addon before I published 1.4. Release 1.3 was the same as [WP Migrate DB Pro](https://deliciousbrains.com/wp-migrate-db-pro), but I've made several improvements since then. -##Is this Illegal? +## Is this Illegal? **No.** Just because this is based on the paid-for WP Migrate DB Pro, it doesn't mean I can't release it. WP Migrate DB Pro is released under GPLv2, a copyleft license that guarantees my freedom (and the freedom of all users) to copy, distribute, and/or modify this software. + +I _was_ forced to rename it from "WP Migrate DB" to "WP Sync DB" after Delicious Brains decided to trademark the name "WP Migrate DB", [filed a DMCA takedown](http://wptavern.com/dmca-takedown-notice-issued-against-fork-of-wp-migrate-db-pro) against the repo, and threatened to take me to court. But they should be OK with it now. diff --git a/asset/css/styles.css b/asset/css/styles.css index beb98c4..fa96c64 100755 --- a/asset/css/styles.css +++ b/asset/css/styles.css @@ -1,10 +1,10 @@ -#wpmdb-main { +#wpsdb-main { width: 742px; } #overlay { background-color: rgba(255, 255, 255, 0.9); } -.wpmdb { +.wpsdb { /* ============================================================================= Common & Global ========================================================================== */ @@ -27,100 +27,100 @@ /* ============================================================================= Help Tab ========================================================================== */ } - .wpmdb > div.updated.warning { + .wpsdb > div.updated.warning { max-width: 742px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; margin: 10px 0; } - .wpmdb > div.updated.warning p { + .wpsdb > div.updated.warning p { font-size: 13px; } - .wpmdb a { + .wpsdb a { text-decoration: none; } - .wpmdb li { + .wpsdb li { margin-bottom: 5px; position: relative; } - .wpmdb ul { + .wpsdb ul { margin: 0; } - .wpmdb input[type=checkbox], - .wpmdb input[type=radio] { + .wpsdb input[type=checkbox], + .wpsdb input[type=radio] { margin-right: 5px; vertical-align: baseline; margin-top: 0; } - .wpmdb input[type=text], - .wpmdb input[type=password] { + .wpsdb input[type=text], + .wpsdb input[type=password] { padding: 5px; } - .wpmdb label.disabled { + .wpsdb label.disabled { color: #888; cursor: default; } - .wpmdb .option-section { + .wpsdb .option-section { border-bottom: 1px solid #ccc; padding-bottom: 20px; margin-bottom: 20px; } - .wpmdb .option-section h3 { + .wpsdb .option-section h3 { font-size: 18px; font-weight: normal; } - .wpmdb p.migrate-db { + .wpsdb p.migrate-db { overflow: hidden; } - .wpmdb p.migrate-db input { + .wpsdb p.migrate-db input { float: left; } - .wpmdb p.migrate-db img { + .wpsdb p.migrate-db img { float: left; margin: 3px 0 0 5px; } - .wpmdb p.migrate-db .save-settings-button { + .wpsdb p.migrate-db .save-settings-button { margin-left: 10px; display: none; } - .wpmdb .indent-wrap { + .wpsdb .indent-wrap { margin-left: 24px; } - .wpmdb .expandable-content { + .wpsdb .expandable-content { display: none; margin-top: 10px; } - .wpmdb .expandable-content li:last-child { + .wpsdb .expandable-content li:last-child { margin-bottom: 0px; } - .wpmdb .header-wrapper { + .wpsdb .header-wrapper { margin-bottom: 10px; } - .wpmdb .header-expand-collapse { + .wpsdb .header-expand-collapse { cursor: pointer; display: inline-block; } - .wpmdb .option-description { + .wpsdb .option-description { font-size: 12px; color: #999; margin-left: 8px; font-weight: normal; } - .wpmdb .option-group li:last-child { + .wpsdb .option-group li:last-child { margin-bottom: 0; } - .wpmdb .connection-status { + .wpsdb .connection-status { display: none; overflow: auto; } - .wpmdb .connection-status.error { + .wpsdb .connection-status.error { color: #9D1818; } - .wpmdb .ajax-spinner { + .wpsdb .ajax-spinner { left: 6px; position: relative; top: 3px; } - .wpmdb div.message { + .wpsdb div.message { margin: 15px 0 0; } - .wpmdb .return-to-profile-selection { + .wpsdb .return-to-profile-selection { margin-bottom: 15px; display: inline-block; } - .wpmdb .return-to-profile-selection.bottom { + .wpsdb .return-to-profile-selection.bottom { margin-top: 10px; } - .wpmdb h2.nav-tab-wrapper { + .wpsdb h2.nav-tab-wrapper { margin-top: 10px; margin-bottom: 20px; padding-left: 5px; } - .wpmdb h2.nav-tab-wrapper a { + .wpsdb h2.nav-tab-wrapper a { margin-right: 4px; } - .wpmdb h2.nav-tab-wrapper a.nav-tab-active { + .wpsdb h2.nav-tab-wrapper a.nav-tab-active { color: #464646; cursor: default; } - .wpmdb label { + .wpsdb label { display: inline-block; clear: both; } - .wpmdb .migration-profile-options li { + .wpsdb .migration-profile-options li { position: relative; width: 520px; } - .wpmdb .migration-profile-options li a { + .wpsdb .migration-profile-options li a { padding: 5px 10px; width: 500px; border: 1px solid #ddd; @@ -128,9 +128,9 @@ display: block; font-size: 14px; color: #333; } - .wpmdb .migration-profile-options li a:hover { + .wpsdb .migration-profile-options li a:hover { border-color: #bbb; } - .wpmdb .main-list-delete-profile-link { + .wpsdb .main-list-delete-profile-link { color: #999999; font-family: "Times New Roman", serif; font-size: 26px; @@ -139,40 +139,40 @@ right: 7px; top: 6px; cursor: pointer; } - .wpmdb .main-list-delete-profile-link:hover { + .wpsdb .main-list-delete-profile-link:hover { color: #444; } - .wpmdb .option-group li { + .wpsdb .option-group li { margin-bottom: 5px; } - .wpmdb .option-group > li { + .wpsdb .option-group > li { margin-bottom: 8px; } - .wpmdb .option-group li > label { + .wpsdb .option-group li > label { font-size: 14px; font-weight: bold; } - .wpmdb .option-group ul { + .wpsdb .option-group ul { display: none; margin: 10px 0px 10px 25px; } - .wpmdb .option-group ul label { + .wpsdb .option-group ul label { font-size: 12px; font-weight: normal; } - .wpmdb .import-file label { + .wpsdb .import-file label { margin-right: 1em; } - .wpmdb .import-file .note { + .wpsdb .import-file .note { display: block; color: #999; font-style: italic; } - .wpmdb .option-heading, .wpmdb .checkbox-label { + .wpsdb .option-heading, .wpsdb .checkbox-label { font-size: 14px; font-weight: bold; } - .wpmdb .checkbox-label input[type=checkbox] { + .wpsdb .checkbox-label input[type=checkbox] { margin-right: 7px; position: relative; top: -1px; } - .wpmdb .expand-collapse-arrow { + .wpsdb .expand-collapse-arrow { margin-right: 9px; } - .wpmdb .migrate-connection-info { + .wpsdb .migrate-connection-info { min-width: 675px; margin: 0; } - .wpmdb .migrate-tab .pull-push-connection-info { + .wpsdb .migrate-tab .pull-push-connection-info { width: 418px; height: 65px; color: #333; @@ -180,48 +180,48 @@ font-size: 15px; line-height: 21px; padding: 10px; } - .wpmdb .basic-access-auth-wrapper { + .wpsdb .basic-access-auth-wrapper { display: none; margin-bottom: 5px; } - .wpmdb .auth-username, .wpmdb .auth-password { + .wpsdb .auth-username, .wpsdb .auth-password { width: 206px; margin-top: 3px; } - .wpmdb .auth-password { + .wpsdb .auth-password { width: 207px; } - .wpmdb .connection-info-wrapper { + .wpsdb .connection-info-wrapper { display: none; width: 670px; } - .wpmdb .connect-button { + .wpsdb .connect-button { margin-top: 2px; } - .wpmdb .temp-disabled { + .wpsdb .temp-disabled { background-color: #EEEEEE; color: #888888; font-family: Consolas, Monaco, monospace; text-shadow: 0 1px 0 #FFFFFF; } - .wpmdb .push-list ul { + .wpsdb .push-list ul { margin-bottom: 0px; } - .wpmdb .find-heading, .wpmdb .replace-heading { + .wpsdb .find-heading, .wpsdb .replace-heading { float: left; } - .wpmdb .find-heading { + .wpsdb .find-heading { width: 400px; } - .wpmdb .replace-fields { + .wpsdb .replace-fields { border-collapse: collapse; border-spacing: 0px; } - .wpmdb .replace-fields input { + .wpsdb .replace-fields input { width: 295px; } - .wpmdb .replace-fields tr td { + .wpsdb .replace-fields tr td { padding-bottom: 7px; } - .wpmdb .replace-fields tr:last-child td { + .wpsdb .replace-fields tr:last-child td { padding-bottom: 0px; } - .wpmdb .arrow-col { + .wpsdb .arrow-col { width: 93px; text-align: center; vertical-align: middle; } - .wpmdb .right-arrow { + .wpsdb .right-arrow { font-size: 36px; color: #aaa; font-family: arial, sans-serif; } - .wpmdb .replace-right-col span { + .wpsdb .replace-right-col span { border-radius: 50%; border: 1px solid #ccc; background-color: #eee; @@ -231,11 +231,11 @@ position: relative; top: 4px; cursor: pointer; } - .wpmdb .replace-right-col span:hover { + .wpsdb .replace-right-col span:hover { border-color: #aaa; } - .wpmdb .replace-remove-row { + .wpsdb .replace-remove-row { margin: 0px 2px; } - .wpmdb .replace-remove-row:after { + .wpsdb .replace-remove-row:after { content: ''; background-color: #aaa; display: block; @@ -244,7 +244,7 @@ position: absolute; top: 7px; width: 6px; } - .wpmdb .replace-add-row:after { + .wpsdb .replace-add-row:after { content: ''; background-color: #aaa; display: block; @@ -253,7 +253,7 @@ position: absolute; top: 7px; width: 6px; } - .wpmdb .replace-add-row:before { + .wpsdb .replace-add-row:before { content: ''; background-color: #aaa; display: block; @@ -262,39 +262,39 @@ position: absolute; top: 5px; width: 2px; } - .wpmdb .original-repeatable-field { + .wpsdb .original-repeatable-field { display: none; } - .wpmdb .no-replaces-message { + .wpsdb .no-replaces-message { display: none; margin-bottom: 0px; } - .wpmdb .tables-header { + .wpsdb .tables-header { display: inline-block; } - .wpmdb .expand-collapse-arrow { + .wpsdb .expand-collapse-arrow { display: inline-block; position: relative; top: -2px; font-size: 11px; } - .wpmdb .collapsed { + .wpsdb .collapsed { -moz-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); -webkit-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); -o-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); -ms-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); } - .wpmdb .select-deselect-divider { + .wpsdb .select-deselect-divider { margin: 0 6px; } - .wpmdb .select-wrap { + .wpsdb .select-wrap { display: none; margin-top: 12px; } - .wpmdb .multiselect { + .wpsdb .multiselect { min-width: 420px; min-height: 180px; margin-bottom: 10px; } - .wpmdb .table-migrate-options li label { + .wpsdb .table-migrate-options li label { font-size: 12px; font-weight: normal; } - .wpmdb .table-migrate-options li { + .wpsdb .table-migrate-options li { margin-bottom: 5px; } - .wpmdb .general-helper { + .wpsdb .general-helper { border-radius: 50%; border: 1px solid #ccc; background-color: #eee; @@ -306,9 +306,9 @@ margin-top: -4px; cursor: pointer; margin-left: 2px; } - .wpmdb .general-helper:hover { + .wpsdb .general-helper:hover { border-color: #aaa; } - .wpmdb .general-helper:after { + .wpsdb .general-helper:after { content: "?"; color: #999999; font-size: 10px; @@ -316,7 +316,7 @@ left: 4px; position: absolute; top: -1px; } - .wpmdb .helper-message { + .wpsdb .helper-message { padding: 10px; border: 1px solid #ccc; border-radius: 3px; @@ -326,17 +326,17 @@ z-index: 100; display: none; box-shadow: 0px 0px 5px #ccc; } - .wpmdb .inline-message { + .wpsdb .inline-message { padding: 10px; border-radius: 3px; margin-top: 5px; } - .wpmdb .inline-message.error { + .wpsdb .inline-message.error { border: 1px solid #CC0000; background-color: #FFEBE8; } - .wpmdb .inline-message.warning { + .wpsdb .inline-message.warning { background-color: #FFFFE0; border: 1px solid #E6DB55; } - .wpmdb .helper-message:after { + .wpsdb .helper-message:after { content: ''; border-bottom: 7px solid transparent; border-right: 7px solid #fff; @@ -347,7 +347,7 @@ position: absolute; top: 11px; width: 0; } - .wpmdb .helper-message:before { + .wpsdb .helper-message:before { content: ''; border-bottom: 7px solid transparent; border-right: 7px solid #aaa; @@ -358,42 +358,42 @@ position: absolute; top: 11px; width: 0; } - .wpmdb .label-disabled { + .wpsdb .label-disabled { color: #888; } - .wpmdb .prefix-notice, .wpmdb .ssl-notice, .wpmdb .different-plugin-version-notice, .wpmdb .directory-permission-notice { + .wpsdb .prefix-notice, .wpsdb .ssl-notice, .wpsdb .different-plugin-version-notice, .wpsdb .directory-permission-notice { background-color: #FFFFE0; border: 1px solid #E6DB55; padding: 15px; border-radius: 3px; margin-bottom: 15px; display: none; } - .wpmdb .prefix-notice p, .wpmdb .ssl-notice p, .wpmdb .different-plugin-version-notice p, .wpmdb .directory-permission-notice p { + .wpsdb .prefix-notice p, .wpsdb .ssl-notice p, .wpsdb .different-plugin-version-notice p, .wpsdb .directory-permission-notice p { margin-top: 0px; } - .wpmdb .prefix-notice p:last-child, .wpmdb .ssl-notice p:last-child, .wpmdb .different-plugin-version-notice p:last-child, .wpmdb .directory-permission-notice p:last-child { + .wpsdb .prefix-notice p:last-child, .wpsdb .ssl-notice p:last-child, .wpsdb .different-plugin-version-notice p:last-child, .wpsdb .directory-permission-notice p:last-child { margin: 0px; } - .wpmdb .different-plugin-version-notice, .wpmdb .directory-permission-notice { + .wpsdb .different-plugin-version-notice, .wpsdb .directory-permission-notice { background-color: #FFEBE8; border-color: #CC0000; } - .wpmdb .different-plugin-version-notice a, .wpmdb .directory-permission-notice a { + .wpsdb .different-plugin-version-notice a, .wpsdb .directory-permission-notice a { color: #CC0000; text-decoration: underline; } - .wpmdb .ssl-notice { + .wpsdb .ssl-notice { margin-bottom: 0; margin-top: 15px; } - .wpmdb .save-migration-profile-wrap li label { + .wpsdb .save-migration-profile-wrap li label { font-size: 12px; font-weight: normal; } - .wpmdb .save-migration-profile-wrap li { + .wpsdb .save-migration-profile-wrap li { margin-bottom: 5px; padding-left: 25px; } - .wpmdb .save-migration-profile-wrap .indent-wrap { + .wpsdb .save-migration-profile-wrap .indent-wrap { margin-left: 0px; } - .wpmdb .create-new-label { + .wpsdb .create-new-label { margin-right: 8px; } - .wpmdb .create-new-profile { + .wpsdb .create-new-profile { position: absolute; top: -5px; } - .wpmdb .delete-profile { + .wpsdb .delete-profile { background-color: #eee; border: 1px solid #ccc; border-radius: 50% 50% 50% 50%; @@ -409,63 +409,63 @@ background-position: 50% 50%; background-size: 6px 6px; background-repeat: no-repeat; } - .wpmdb .delete-profile:after { + .wpsdb .delete-profile:after { content: "\00d7"; left: 2px; position: absolute; top: -3px; color: #aaa; font-size: 12px; } - .wpmdb .delete-profile:hover { + .wpsdb .delete-profile:hover { border-color: #aaa; } - .wpmdb .migrate-db .ajax-success-msg { + .wpsdb .migrate-db .ajax-success-msg { font-weight: bold; margin: 3px 0 0 9px; display: inline-block; } - .wpmdb p img.save-profile-ajax-spinner { + .wpsdb p img.save-profile-ajax-spinner { margin-left: 10px; } - .wpmdb .backup-description { + .wpsdb .backup-description { left: 20px; position: relative; } - .wpmdb .backup-option-disabled { + .wpsdb .backup-option-disabled { margin-bottom: 0px; } - .wpmdb .import-button { + .wpsdb .import-button { display: none; } - .wpmdb .settings-tab { + .wpsdb .settings-tab { display: none; } - .wpmdb .settings-tab .slider { + .wpsdb .settings-tab .slider { max-width: 416px; } - .wpmdb .settings-tab .slider-label { + .wpsdb .settings-tab .slider-label { display: block; margin-bottom: 10px; float: left; width: 50%; } - .wpmdb .settings-tab .slider-label-wrapper { + .wpsdb .settings-tab .slider-label-wrapper { max-width: 416px; width: 100%; position: relative; } - .wpmdb .settings-tab .amount { + .wpsdb .settings-tab .amount { width: 50%; text-align: right; display: block; text-align: right; float: left; } - .wpmdb .settings-tab .slider-spinner { + .wpsdb .settings-tab .slider-spinner { position: absolute; right: -35px; bottom: -13px; } - .wpmdb .settings-tab .slider-success-msg { + .wpsdb .settings-tab .slider-success-msg { display: none; right: -53px; bottom: -13px; position: absolute; font-weight: bold; } - .wpmdb .settings-tab .ui-slider { + .wpsdb .settings-tab .ui-slider { border: 1px solid #dfdfdf; height: 10px; border-radius: 2px; position: relative; } - .wpmdb .settings-tab .ui-slider-handle { + .wpsdb .settings-tab .ui-slider-handle { width: 7px; height: 20px; background-color: #aaa; @@ -473,42 +473,42 @@ position: absolute; top: -5px; outline: none; } - .wpmdb .settings-tab .ui-slider-handle:active { + .wpsdb .settings-tab .ui-slider-handle:active { background-color: #999; } - .wpmdb .settings-tab .ui-slider-range { + .wpsdb .settings-tab .ui-slider-range { background-color: #eee; height: 100%; } - .wpmdb .settings-tab .option-section li label { + .wpsdb .settings-tab .option-section li label { font-size: 12px; font-weight: normal; position: relative; } - .wpmdb .settings-tab .option-section li { + .wpsdb .settings-tab .option-section li { margin-bottom: 5px; } - .wpmdb .settings-tab .option-section li:last-child { + .wpsdb .settings-tab .option-section li:last-child { margin-bottom: 0px; } - .wpmdb .settings-tab .option-section .ajax-spinner { + .wpsdb .settings-tab .option-section .ajax-spinner { right: -23px; left: inherit; top: 0px; position: absolute; } - .wpmdb .settings-tab .option-section .ajax-success-msg { + .wpsdb .settings-tab .option-section .ajax-success-msg { right: -42px; left: inherit; top: 0px; position: absolute; font-weight: bold; } - .wpmdb .settings-tab .option-section .verify-ssl .ajax-spinner { + .wpsdb .settings-tab .option-section .verify-ssl .ajax-spinner { right: -45px; } - .wpmdb .settings-tab .option-section .verify-ssl .ajax-success-msg { + .wpsdb .settings-tab .option-section .verify-ssl .ajax-success-msg { right: -65px; } - .wpmdb .allow-remote-reqeusts { + .wpsdb .allow-remote-reqeusts { font-size: 14px; font-weight: bold; } - .wpmdb .connection-info-label { + .wpsdb .connection-info-label { margin-top: 15px; margin-bottom: 5px; display: block; } - .wpmdb .connection-info { + .wpsdb .connection-info { clear: both; font-size: 15px; line-height: 21px; @@ -519,37 +519,37 @@ display: block; margin-bottom: 7px; width: 418px; } - .wpmdb .reset-button-wrap { + .wpsdb .reset-button-wrap { width: 418px; } - .wpmdb .reset-api-key { + .wpsdb .reset-api-key { float: left; } - .wpmdb .reset-api-key-ajax-spinner { + .wpsdb .reset-api-key-ajax-spinner { float: left; margin: 4px 7px; } - .wpmdb .help-tab { + .wpsdb .help-tab { display: none; } - .wpmdb .help-tab h3 { + .wpsdb .help-tab h3 { font-size: 18px; font-weight: normal; } - .wpmdb .help-tab .support { + .wpsdb .help-tab .support { border-bottom: 1px solid #ccc; margin-bottom: 25px; padding-bottom: 18px; } - .wpmdb .help-tab .support p { + .wpsdb .help-tab .support p { width: 640px; } - .wpmdb .help-tab .support .email a { + .wpsdb .help-tab .support .email a { font-size: 12px; } - .wpmdb .help-tab .support .ajax-spinner { + .wpsdb .help-tab .support .ajax-spinner { top: 2px; } - .wpmdb .help-tab .video-viewer { + .wpsdb .help-tab .video-viewer { margin-bottom: 30px; } - .wpmdb .help-tab .videos { + .wpsdb .help-tab .videos { width: 640px; } - .wpmdb .help-tab .videos ul > li { + .wpsdb .help-tab .videos ul > li { margin-bottom: 30px; overflow: hidden; position: relative; } - .wpmdb .help-tab .videos ul > li a { + .wpsdb .help-tab .videos ul > li a { overflow: hidden; display: block; width: 320px; @@ -558,7 +558,7 @@ margin-right: 15px; position: relative; z-index: 1; } - .wpmdb .help-tab .videos ul > li a:before, .wpmdb .help-tab .videos ul > li a:after { + .wpsdb .help-tab .videos ul > li a:before, .wpsdb .help-tab .videos ul > li a:after { position: absolute; content: " "; margin: auto; @@ -566,7 +566,7 @@ right: 0; top: 0; bottom: 0; } - .wpmdb .help-tab .videos ul > li a:before { + .wpsdb .help-tab .videos ul > li a:before { width: 64px; height: 64px; -webkit-border-radius: 64px; @@ -579,7 +579,7 @@ border: 1px solid #ddd; background-color: #fff; z-index: 2; } - .wpmdb .help-tab .videos ul > li a:after { + .wpsdb .help-tab .videos ul > li a:after { filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); opacity: 0.8; border: 21.33333px solid transparent; @@ -592,29 +592,29 @@ width: 0px; height: 0px; z-index: 3; } - .wpmdb .help-tab .videos .video:last-child { + .wpsdb .help-tab .videos .video:last-child { margin-bottom: 0px; } - .wpmdb .help-tab .videos img { + .wpsdb .help-tab .videos img { width: 320px; height: 240px; position: relative; top: 50%; margin-top: -120px; } - .wpmdb .help-tab .debug { + .wpsdb .help-tab .debug { width: 640px; border-bottom: 1px solid #CCCCCC; margin-bottom: 25px; padding-bottom: 28px; } - .wpmdb .help-tab .debug textarea { + .wpsdb .help-tab .debug textarea { width: 100%; min-height: 200px; font-family: Consolas, Monaco, monospace; margin-bottom: 5px; } - .wpmdb .help-tab h4 { + .wpsdb .help-tab h4 { margin: 0 0 0.2em 0; } - .wpmdb .help-tab p { + .wpsdb .help-tab p { margin: 0 0 0.5em 0; } - .wpmdb .help-tab iframe { + .wpsdb .help-tab iframe { display: none; } /* Progress Information */ @@ -792,61 +792,61 @@ body.mp6 input[type=checkbox]:disabled { opacity: 1; border-color: #ccc; } -body.mp6 #wpmdb-main { +body.mp6 #wpsdb-main { margin-top: 15px; font-size: 14px; } body.mp6 p { font-size: 14px; } body.mp6 .wrap h2 { float: left; } -body.mp6 .wpmdb input[type=checkbox], -body.mp6 .wpmdb input[type=radio] { +body.mp6 .wpsdb input[type=checkbox], +body.mp6 .wpsdb input[type=radio] { vertical-align: middle; margin-top: -4px; } -body.mp6 .wpmdb input[type=text], -body.mp6 .wpmdb input[type=password] { +body.mp6 .wpsdb input[type=text], +body.mp6 .wpsdb input[type=password] { padding: 3px 5px; } -body.mp6 .wpmdb input.code { +body.mp6 .wpsdb input.code { padding-top: 6px; } -body.mp6 .wpmdb label { +body.mp6 .wpsdb label { font-size: 14px; } -body.mp6 .wpmdb h2.nav-tab-wrapper { +body.mp6 .wpsdb h2.nav-tab-wrapper { float: none; margin-bottom: 0; width: 722px; } -body.mp6 .wpmdb .help-tab h3 { +body.mp6 .wpsdb .help-tab h3 { margin-top: 0; } -body.mp6 .wpmdb .temp-disabled { +body.mp6 .wpsdb .temp-disabled { background-color: #f9f9f9; } -body.mp6 .wpmdb .migration-profile-options li a { +body.mp6 .wpsdb .migration-profile-options li a { border-color: #ccc; color: #555; background-color: #e4e4e4; } -body.mp6 .wpmdb .migration-profile-options li a:hover { +body.mp6 .wpsdb .migration-profile-options li a:hover { background-color: #fff; color: #464646; } -body.mp6 .wpmdb .settings-tab .slider-label span { +body.mp6 .wpsdb .settings-tab .slider-label span { vertical-align: middle; } -body.mp6 .wpmdb .settings-tab .slider-label-wrapper { +body.mp6 .wpsdb .settings-tab .slider-label-wrapper { font-size: 14px; } -body.mp6 .wpmdb .settings-tab .ui-slider { +body.mp6 .wpsdb .settings-tab .ui-slider { border-color: #ccc; background-color: #fff; } -body.mp6 .wpmdb .settings-tab .ui-slider-range { +body.mp6 .wpsdb .settings-tab .ui-slider-range { background-color: #d8fcd1; } -body.mp6 .wpmdb .settings-tab .option-section li label { +body.mp6 .wpsdb .settings-tab .option-section li label { font-size: 14px; } -body.mp6 .wpmdb .connection-info, -body.mp6 .wpmdb .migrate-tab .pull-push-connection-info { +body.mp6 .wpsdb .connection-info, +body.mp6 .wpsdb .migrate-tab .pull-push-connection-info { font-weight: bold; font-size: 14px; } -body.mp6 .wpmdb .general-helper { +body.mp6 .wpsdb .general-helper { border: 0; width: auto; height: auto; top: auto; margin: 0; } -body.mp6 .wpmdb .general-helper:after { +body.mp6 .wpsdb .general-helper:after { content: "\f223"; display: inline-block; -webkit-font-smoothing: antialiased; @@ -855,47 +855,47 @@ body.mp6 .wpmdb .general-helper:after { top: auto; left: auto; position: relative; } -body.mp6 .wpmdb .helper-message { +body.mp6 .wpsdb .helper-message { font-size: 14px; line-height: 1.4em; } -body.mp6 .wpmdb .right-arrow { +body.mp6 .wpsdb .right-arrow { display: none; } -body.mp6 .wpmdb .arrow-col { +body.mp6 .wpsdb .arrow-col { width: 75px; } -body.mp6 .wpmdb .arrow-col:after { +body.mp6 .wpsdb .arrow-col:after { content: "\f344"; display: inline-block; -webkit-font-smoothing: antialiased; font: normal 22px/1 'dashicons'; vertical-align: top; color: #999; } -body.mp6 .wpmdb .find-heading { +body.mp6 .wpsdb .find-heading { width: 388px; } -body.mp6 .wpmdb .replace-fields input { +body.mp6 .wpsdb .replace-fields input { width: 304px; } -body.mp6 .wpmdb .replace-right-col span { +body.mp6 .wpsdb .replace-right-col span { border-color: #999; } - body.mp6 .wpmdb .replace-right-col span:hover { + body.mp6 .wpsdb .replace-right-col span:hover { border-color: #666; } -body.mp6 .wpmdb .replace-remove-row:after, body.mp6 .wpmdb .replace-remove-row:before, body.mp6 .wpmdb .replace-add-row:after, body.mp6 .wpmdb .replace-add-row:before { +body.mp6 .wpsdb .replace-remove-row:after, body.mp6 .wpsdb .replace-remove-row:before, body.mp6 .wpsdb .replace-add-row:after, body.mp6 .wpsdb .replace-add-row:before { background-color: #999; } -body.mp6 .wpmdb .replace-remove-row:hover:after, body.mp6 .wpmdb .replace-remove-row:hover:before, body.mp6 .wpmdb .replace-add-row:hover:after, body.mp6 .wpmdb .replace-add-row:hover:before { +body.mp6 .wpsdb .replace-remove-row:hover:after, body.mp6 .wpsdb .replace-remove-row:hover:before, body.mp6 .wpsdb .replace-add-row:hover:after, body.mp6 .wpsdb .replace-add-row:hover:before { background-color: #666; } -body.mp6 .wpmdb .option-group.migrate-selection > li > label { +body.mp6 .wpsdb .option-group.migrate-selection > li > label { font-size: 16px; } -body.mp6 .wpmdb .saved-migration-profile-label { +body.mp6 .wpsdb .saved-migration-profile-label { font-size: 16px; } -body.mp6 .wpmdb .option-heading, body.mp6 .wpmdb .checkbox-label { +body.mp6 .wpsdb .option-heading, body.mp6 .wpsdb .checkbox-label { font-size: 16px; } -body.mp6 .wpmdb .checkbox-label input[type=checkbox] { +body.mp6 .wpsdb .checkbox-label input[type=checkbox] { top: auto; } -body.mp6 .wpmdb .return-to-profile-selection { +body.mp6 .wpsdb .return-to-profile-selection { font-size: 14px; } -body.mp6 .wpmdb .option-description { +body.mp6 .wpsdb .option-description { font-size: 13px; } -body.mp6 .wpmdb .save-migration-profile-wrap li { +body.mp6 .wpsdb .save-migration-profile-wrap li { position: relative; } -body.mp6 .wpmdb .delete-profile { +body.mp6 .wpsdb .delete-profile { border: 0; border-radius: 0; height: auto; @@ -903,51 +903,51 @@ body.mp6 .wpmdb .delete-profile { left: 0; top: 50%; margin-left: 0; } - body.mp6 .wpmdb .delete-profile:after { + body.mp6 .wpsdb .delete-profile:after { content: "\f153"; display: inline-block; -webkit-font-smoothing: antialiased; font: normal 18px/1 'dashicons'; vertical-align: middle; color: #999; } - body.mp6 .wpmdb .delete-profile:hover:after { + body.mp6 .wpsdb .delete-profile:hover:after { color: #666; } -body.mp6 .wpmdb .help-tab .support p, body.mp6 .wpmdb .help-tab .support .email a { +body.mp6 .wpsdb .help-tab .support p, body.mp6 .wpsdb .help-tab .support .email a { font-size: 14px; } -body.mp6 .wpmdb .help-tab .videos h4, body.mp6 .wpmdb .help-tab .videos p { +body.mp6 .wpsdb .help-tab .videos h4, body.mp6 .wpsdb .help-tab .videos p { font-size: 14px; } -body.mp6 .wpmdb .inline-message, body.mp6 .wpmdb .notification-message { +body.mp6 .wpsdb .inline-message, body.mp6 .wpsdb .notification-message { border-radius: 0; border: 0; box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1); padding: 10px 14px; font-size: 13px; } -body.mp6 .wpmdb .notification-message { +body.mp6 .wpsdb .notification-message { margin-bottom: 20px; background-color: #fff; } - body.mp6 .wpmdb .notification-message p { + body.mp6 .wpsdb .notification-message p { font-size: 13px; margin-top: 0; } - body.mp6 .wpmdb .notification-message p:last-child { + body.mp6 .wpsdb .notification-message p:last-child { margin: 0; } - body.mp6 .wpmdb .notification-message h4 { + body.mp6 .wpsdb .notification-message h4 { margin-top: 0; } - body.mp6 .wpmdb .notification-message a { + body.mp6 .wpsdb .notification-message a { color: #0074a2; text-decoration: none; } - body.mp6 .wpmdb .notification-message a:hover { + body.mp6 .wpsdb .notification-message a:hover { color: #2ea2cc; } -body.mp6 .wpmdb .inline-message.error, body.mp6 .wpmdb .notification-message.error-notice { +body.mp6 .wpsdb .inline-message.error, body.mp6 .wpsdb .notification-message.error-notice { border-left: 4px solid #dd3d36; background-color: #fff; } -body.mp6 .wpmdb .inline-message.warning, body.mp6 .wpmdb .notification-message.warning-notice { +body.mp6 .wpsdb .inline-message.warning, body.mp6 .wpsdb .notification-message.warning-notice { background-color: #fff; border-left: 4px solid #ffba00; } -body.mp6 .wpmdb .inline-message.success, body.mp6 .wpmdb .notification-message.success-notice { +body.mp6 .wpsdb .inline-message.success, body.mp6 .wpsdb .notification-message.success-notice { border-left: 4px solid #7ad03a; } -body.mp6 .wpmdb .ssl-notice { +body.mp6 .wpsdb .ssl-notice { margin-bottom: 0; } -body.mp6 .wpmdb .different-plugin-version-notice, body.mp6 .wpmdb .directory-permission-notice { +body.mp6 .wpsdb .different-plugin-version-notice, body.mp6 .wpsdb .directory-permission-notice { margin-bottom: 10px; } body.mp6 .progress-content { font-size: 14px; diff --git a/asset/js/common.js b/asset/js/common.js index 6153aa8..0a5889b 100644 --- a/asset/js/common.js +++ b/asset/js/common.js @@ -5,7 +5,7 @@ var non_fatal_errors = ''; var migration_error = false; var connection_data; -function wpmdb_call_next_hook() { +function wpsdb_call_next_hook() { if( ! call_stack.length ) { call_stack = hooks; } @@ -15,7 +15,7 @@ function wpmdb_call_next_hook() { window[func](); // Uses the string from the array to call the function of the same name } -function wpmdb_add_commas( number_string ) { +function wpsdb_add_commas( number_string ) { number_string += ''; x = number_string.split('.'); x1 = x[0]; @@ -27,7 +27,7 @@ function wpmdb_add_commas( number_string ) { return x1 + x2; } -function wpmdb_parse_json( maybe_json ) { +function wpsdb_parse_json( maybe_json ) { try { var json_object = jQuery.parseJSON( maybe_json ); } diff --git a/asset/js/hook.js b/asset/js/hook.js index 9966430..e1a4ea2 100644 --- a/asset/js/hook.js +++ b/asset/js/hook.js @@ -1,42 +1,42 @@ (function($) { - $.wpmdb = { + $.wpsdb = { /** * Implement a WordPress-link Hook System for Javascript * TODO: Change 'tag' to 'args', allow number (priority), string (tag), object (priority+tag) */ hooks: { action: {}, filter: {} }, add_action: function( action, callable, tag ) { - jQuery.wpmdb.add_hook( 'action', action, callable, tag ); + jQuery.wpsdb.add_hook( 'action', action, callable, tag ); }, add_filter: function( action, callable, tag ) { - jQuery.wpmdb.add_hook( 'filter', action, callable, tag ); + jQuery.wpsdb.add_hook( 'filter', action, callable, tag ); }, do_action: function( action, args ) { - jQuery.wpmdb.do_hook( 'action', action, null, args ); + jQuery.wpsdb.do_hook( 'action', action, null, args ); }, apply_filters: function( action, value, args ) { - return jQuery.wpmdb.do_hook( 'filter', action, value, args ); + return jQuery.wpsdb.do_hook( 'filter', action, value, args ); }, remove_action: function( action, tag ) { - jQuery.wpmdb.remove_hook( 'action', action, tag ); + jQuery.wpsdb.remove_hook( 'action', action, tag ); }, remove_filter: function( action, tag ) { - jQuery.wpmdb.remove_hook( 'filter', action, tag ); + jQuery.wpsdb.remove_hook( 'filter', action, tag ); }, add_hook: function( hook_type, action, callable, tag ) { - if ( undefined == jQuery.wpmdb.hooks[hook_type][action] ) { - jQuery.wpmdb.hooks[hook_type][action] = []; + if ( undefined == jQuery.wpsdb.hooks[hook_type][action] ) { + jQuery.wpsdb.hooks[hook_type][action] = []; } - var hooks = jQuery.wpmdb.hooks[hook_type][action]; + var hooks = jQuery.wpsdb.hooks[hook_type][action]; if ( undefined == tag ) { tag = action + '_' + hooks.length; } - jQuery.wpmdb.hooks[hook_type][action].push( { tag:tag, callable:callable } ); + jQuery.wpsdb.hooks[hook_type][action].push( { tag:tag, callable:callable } ); }, do_hook: function( hook_type, action, value, args ) { - if ( undefined != jQuery.wpmdb.hooks[hook_type][action] ) { - var hooks = jQuery.wpmdb.hooks[hook_type][action]; + if ( undefined != jQuery.wpsdb.hooks[hook_type][action] ) { + var hooks = jQuery.wpsdb.hooks[hook_type][action]; for( var i=0; i=0; i--) { if (undefined==tag||tag==hooks[i].tag) hooks.splice(i,1); diff --git a/asset/js/script.js b/asset/js/script.js index 0642eb1..4721e1e 100755 --- a/asset/js/script.js +++ b/asset/js/script.js @@ -115,7 +115,7 @@ var migration_complete_events; } function maybe_show_version_warning( plugin_version, url ) { - if( typeof plugin_version != 'undefined' && plugin_version != wpmdb_plugin_version ) { + if( typeof plugin_version != 'undefined' && plugin_version != wpsdb_plugin_version ) { $('.different-plugin-version-notice').show(); $('.remote-version').html( plugin_version ); $('.remote-location').html( url ); @@ -125,7 +125,7 @@ var migration_complete_events; } function maybe_show_prefix_notice( prefix ) { - if( prefix != wpmdb_this_prefix ) { + if( prefix != wpsdb_this_prefix ) { $('.remote-prefix').html( prefix ); show_prefix_notice = true; if( $('#pull').is(':checked') ){ @@ -170,12 +170,12 @@ var migration_complete_events; $('.slider').slider({ range: 'min', - value: wpmdb_max_request / 1024, + value: wpsdb_max_request / 1024, min: 512, - max: wpmdb_bottleneck / 1024, + max: wpsdb_bottleneck / 1024, step: 512, slide: function( event, ui ) { - $('.amount').html( wpmdb_add_commas( ui.value ) + ' kB' ); + $('.amount').html( wpsdb_add_commas( ui.value ) + ' kB' ); }, change: function( event, ui ) { $('.amount').after( '' ); @@ -186,7 +186,7 @@ var migration_complete_events; dataType: 'json', cache: false, data: { - action : 'wpmdb_update_max_request_size', + action : 'wpsdb_update_max_request_size', max_request_size : parseInt( ui.value ), }, error: function(jqXHR, textStatus, errorThrown){ @@ -205,13 +205,13 @@ var migration_complete_events; }); } }); - $('.amount').html( wpmdb_add_commas( $('.slider').slider('value') ) + ' kB' ); + $('.amount').html( wpsdb_add_commas( $('.slider').slider('value') ) + ' kB' ); var progress_content_original = $('.progress-content').clone(); $('.progress-content').remove(); - var this_tables = $.parseJSON(wpmdb_this_tables); - var this_prefixed_tables = $.parseJSON(wpmdb_this_prefixed_tables); + var this_tables = $.parseJSON(wpsdb_this_tables); + var this_prefixed_tables = $.parseJSON(wpsdb_this_prefixed_tables); var push_select = $('#select-tables').clone(); var pull_select = $('#select-tables').clone(); var push_post_type_select = $('#select-post-types').clone(); @@ -259,7 +259,7 @@ var migration_complete_events; function establish_remote_connection_from_saved_profile(){ var action = $('input[name=action]:checked').val(); var connection_info = $.trim( $('.pull-push-connection-info').val() ).split("\n"); - if( typeof wpmdb_default_profile == 'undefined' || wpmdb_default_profile == true || action == 'savefile' || doing_ajax ){ + if( typeof wpsdb_default_profile == 'undefined' || wpsdb_default_profile == true || action == 'savefile' || doing_ajax ){ return; } @@ -280,7 +280,7 @@ var migration_complete_events; dataType: 'json', cache: false, data: { - action: 'wpmdb_verify_connection_to_remote_site', + action: 'wpsdb_verify_connection_to_remote_site', url: connection_info[0], key: connection_info[1], intent: intent, @@ -297,7 +297,7 @@ var migration_complete_events; doing_ajax = false; enable_export_type_controls(); - if( typeof data.wpmdb_error != 'undefined' && data.wpmdb_error == 1 ){ + if( typeof data.wpsdb_error != 'undefined' && data.wpsdb_error == 1 ){ $('.connection-status').html( data.body ); $('.connection-status').addClass( 'notification-message error-notice migration-error' ); @@ -323,8 +323,8 @@ var migration_complete_events; move_connection_info_box(); var loaded_tables = ''; - if( wpmdb_default_profile == false && typeof wpmdb_loaded_tables != 'undefined' ){ - loaded_tables = $.parseJSON( wpmdb_loaded_tables ); + if( wpsdb_default_profile == false && typeof wpsdb_loaded_tables != 'undefined' ){ + loaded_tables = $.parseJSON( wpsdb_loaded_tables ); } var table_select = document.createElement('select'); @@ -349,8 +349,8 @@ var migration_complete_events; pull_select = table_select; var loaded_post_prefixes = ''; - if( wpmdb_default_profile == false && typeof wpmdb_loaded_post_types != 'undefined' ){ - loaded_post_prefixes = $.parseJSON( wpmdb_loaded_post_types ); + if( wpsdb_default_profile == false && typeof wpsdb_loaded_post_types != 'undefined' ){ + loaded_post_prefixes = $.parseJSON( wpsdb_loaded_post_types ); } var post_type_select = document.createElement('select'); @@ -363,7 +363,7 @@ var migration_complete_events; $.each(connection_data.post_types, function(index, value) { var selected = $.inArray( value, loaded_post_prefixes ); - if( selected != -1 || ( wpmdb_convert_exclude_revisions == true && value != 'revision' ) ){ + if( selected != -1 || ( wpsdb_convert_exclude_revisions == true && value != 'revision' ) ){ selected = ' selected="selected" '; } else{ @@ -375,8 +375,8 @@ var migration_complete_events; pull_post_type_select = post_type_select; var loaded_tables_backup = ''; - if( wpmdb_default_profile == false && typeof wpmdb_loaded_tables_backup != 'undefined' ){ - loaded_tables_backup = $.parseJSON( wpmdb_loaded_tables_backup ); + if( wpsdb_default_profile == false && typeof wpsdb_loaded_tables_backup != 'undefined' ){ + loaded_tables_backup = $.parseJSON( wpsdb_loaded_tables_backup ); } var table_select_backup = document.createElement('select'); @@ -408,14 +408,14 @@ var migration_complete_events; $('#select-backup').remove(); $('.backup-tables-wrap').prepend(pull_select_backup); $('.table-prefix').html(data.prefix); - $('.uploads-dir').html(wpmdb_this_uploads_dir); + $('.uploads-dir').html(wpsdb_this_uploads_dir); } else { $('#select-backup').remove(); $('.backup-tables-wrap').prepend(push_select_backup); } - $.wpmdb.do_action( 'verify_connection_to_remote_site', connection_data ); + $.wpsdb.do_action( 'verify_connection_to_remote_site', connection_data ); } @@ -438,7 +438,7 @@ var migration_complete_events; dataType: 'text', cache: false, data: { - action : 'wpmdb_clear_log', + action : 'wpsdb_clear_log', }, error: function(jqXHR, textStatus, errorThrown){ alert('An error occurred when trying to clear the debug log. Please contact support. (#132)'); @@ -456,7 +456,7 @@ var migration_complete_events; dataType: 'text', cache: false, data: { - action : 'wpmdb_get_log', + action : 'wpsdb_get_log', }, error: function(jqXHR, textStatus, errorThrown){ alert('An error occurred when trying to update the debug log. Please contact support. (#133)'); @@ -587,7 +587,7 @@ var migration_complete_events; dataType: 'text', cache: false, data: { - action: 'wpmdb_save_profile', + action: 'wpsdb_save_profile', profile: profile, }, error: function(jqXHR, textStatus, errorThrown){ @@ -679,13 +679,13 @@ var migration_complete_events; } } else{ - table_rows = $.parseJSON(wpmdb_this_table_rows); + table_rows = $.parseJSON(wpsdb_this_table_rows); if( backup_option == 'backup_only_with_prefix' ) { - tables_to_migrate = $.parseJSON( wpmdb_this_prefixed_tables ); + tables_to_migrate = $.parseJSON( wpsdb_this_prefixed_tables ); } else if( backup_option == 'backup_selected' ) { selected_tables = $('#select-tables').val(); - local_tables = $.parseJSON( wpmdb_this_tables ); + local_tables = $.parseJSON( wpsdb_this_tables ); tables_to_migrate = get_intersect( selected_tables, local_tables ); } else if( backup_option == 'backup_manual_select' ) { @@ -700,7 +700,7 @@ var migration_complete_events; // user is pushing or exporting if( migration_intent == 'push' || migration_intent == 'savefile' ){ // default value, assuming we're not backing up - table_rows = $.parseJSON(wpmdb_this_table_rows); + table_rows = $.parseJSON(wpsdb_this_table_rows); } else{ table_rows = connection_data.table_rows; @@ -709,7 +709,7 @@ var migration_complete_events; else{ if( migration_intent == 'push' || migration_intent == 'savefile' ){ tables_to_migrate = this_prefixed_tables; - table_rows = $.parseJSON(wpmdb_this_table_rows); + table_rows = $.parseJSON(wpsdb_this_table_rows); } else{ tables_to_migrate = connection_data.prefixed_tables; @@ -788,7 +788,7 @@ var migration_complete_events; dataType: 'json', cache: false, data: { - action : 'wpmdb_initiate_migration', + action : 'wpsdb_initiate_migration', intent : migration_intent, url : remote_site, key : secret_key, @@ -807,7 +807,7 @@ var migration_complete_events; return; }, success: function(data){ - if( typeof data.wpmdb_error != 'undefined' && data.wpmdb_error == 1 ){ + if( typeof data.wpsdb_error != 'undefined' && data.wpsdb_error == 1 ){ migration_complete_events(); $('.progress-title').html('Migration failed'); $('.progress-text').addClass( 'migration-error' ); @@ -838,7 +838,7 @@ var migration_complete_events; if( table_intent == 'migrate_select' ){ tables_to_migrate = $('#select-tables').val(); if( migration_intent == 'push' || migration_intent == 'savefile' ){ - table_rows = $.parseJSON(wpmdb_this_table_rows); + table_rows = $.parseJSON(wpsdb_this_table_rows); } else{ table_rows = connection_data.table_rows; @@ -847,7 +847,7 @@ var migration_complete_events; else{ if( migration_intent == 'push' || migration_intent == 'savefile' ){ tables_to_migrate = this_prefixed_tables; - table_rows = $.parseJSON(wpmdb_this_table_rows); + table_rows = $.parseJSON(wpsdb_this_table_rows); } else{ tables_to_migrate = connection_data.prefixed_tables; @@ -864,11 +864,11 @@ var migration_complete_events; } else { - hooks = $.wpmdb.apply_filters( 'wpmdb_before_migration_complete_hooks', hooks ); + hooks = $.wpsdb.apply_filters( 'wpsdb_before_migration_complete_hooks', hooks ); hooks.push( 'migration_complete' ); - hooks = $.wpmdb.apply_filters( 'wpmdb_after_migration_complete_hooks', hooks ); + hooks = $.wpsdb.apply_filters( 'wpsdb_after_migration_complete_hooks', hooks ); hooks.push( 'migration_complete_events' ); - wpmdb_call_next_hook(); + wpsdb_call_next_hook(); return; } } @@ -891,7 +891,7 @@ var migration_complete_events; } var request_data = { - action : 'wpmdb_migrate_table', + action : 'wpsdb_migrate_table', intent : migration_intent, url : remote_site, key : secret_key, @@ -936,7 +936,7 @@ var migration_complete_events; }, success: function(data){ data = $.trim( data ); - row_information = wpmdb_parse_json( data ); + row_information = wpsdb_parse_json( data ); if( false == row_information || null == row_information ){ $('.progress-title').html('Migration failed'); if( '' == data || null == data ) { @@ -1021,7 +1021,7 @@ var migration_complete_events; currently_migrating = false; var migrate_complete_text = 'Migration complete'; if( $('#save_computer').is(':checked') ){ - var url = wpmdb_this_download_url + encodeURIComponent( dump_filename ); + var url = wpsdb_this_download_url + encodeURIComponent( dump_filename ); if( $('#gzip_file').is(':checked') ){ url += '&gzip=1'; } @@ -1046,7 +1046,7 @@ var migration_complete_events; dataType: 'text', cache: false, data: { - action : 'wpmdb_finalize_migration', + action : 'wpsdb_finalize_migration', intent : migration_intent, url : remote_site, key : secret_key, @@ -1073,7 +1073,7 @@ var migration_complete_events; migration_complete_events(); return; } - wpmdb_call_next_hook(); + wpsdb_call_next_hook(); } }); } @@ -1138,7 +1138,7 @@ var migration_complete_events; dataType: 'text', cache: false, data: { - action: 'wpmdb_save_profile', + action: 'wpsdb_save_profile', profile: profile, }, error: function(jqXHR, textStatus, errorThrown){ @@ -1225,7 +1225,7 @@ var migration_complete_events; $('.connection-status').hide(); $('.step-two').show(); $('.table-prefix').html(connection_data.prefix); - $('.uploads-dir').html(wpmdb_this_uploads_dir); + $('.uploads-dir').html(wpsdb_this_uploads_dir); if( profile_name_edited == false ){ var profile_name = get_domain_name( connection_info[0] ); $('.create-new-profile').val(profile_name); @@ -1241,12 +1241,12 @@ var migration_complete_events; $('.step-two').hide(); } $('.directory-scope').html('local'); - if( false == wpmdb_write_permission ) { + if( false == wpsdb_write_permission ) { $('#create-backup').prop('checked',false); $('#create-backup').attr('disabled','disabled'); $('#create-backup-label').addClass('disabled'); $('.backup-option-disabled').show(); - $('.upload-directory-location').html(wpmdb_this_upload_dir_long); + $('.upload-directory-location').html(wpsdb_this_upload_dir_long); } } else{ @@ -1260,7 +1260,7 @@ var migration_complete_events; if( connection_established ){ $('.connection-status').hide(); $('.step-two').show(); - $('.table-prefix').html(wpmdb_this_prefix); + $('.table-prefix').html(wpsdb_this_prefix); $('.uploads-dir').html(connection_data.uploads_dir); if( profile_name_edited == false ){ var profile_name = get_domain_name( connection_info[0] ); @@ -1293,18 +1293,18 @@ var migration_complete_events; else if( $('#savefile').is(':checked') ){ $('.connection-status').hide(); $('.step-two').show(); - $('.table-prefix').html(wpmdb_this_prefix); + $('.table-prefix').html(wpsdb_this_prefix); if( profile_name_edited == false ){ $('.create-new-profile').val(''); } $('.backup-options').hide(); $('.keep-active-plugins').hide(); - if( false == wpmdb_write_permission ) { + if( false == wpsdb_write_permission ) { $('.directory-permission-notice').show(); $('.step-two').hide(); } } - $.wpmdb.do_action( 'move_connection_info_box' ); + $.wpsdb.do_action( 'move_connection_info_box' ); } function change_replace_values(){ @@ -1452,7 +1452,7 @@ var migration_complete_events; dataType: 'text', cache: false, data: { - action: 'wpmdb_reset_api_key', + action: 'wpsdb_reset_api_key', }, error: function(jqXHR, textStatus, errorThrown){ alert('An error occurred when trying to generate the API key. Please see the Help tab for details on how to request support. (#105)'); @@ -1468,7 +1468,7 @@ var migration_complete_events; }); - var this_connection_info = $.parseJSON( wpmdb_connection_info ); + var this_connection_info = $.parseJSON( wpsdb_connection_info ); // show / hide table select box when specific settings change $('input.multiselect-toggle').change(function(){ @@ -1513,7 +1513,7 @@ var migration_complete_events; dataType: 'text', cache: false, data: { - action : 'wpmdb_delete_migration_profile', + action : 'wpsdb_delete_migration_profile', profile_id : $(this).attr('data-profile-id') }, error: function(jqXHR, textStatus, errorThrown){ @@ -1545,7 +1545,7 @@ var migration_complete_events; dataType: 'text', cache: false, data: { - action : 'wpmdb_delete_migration_profile', + action : 'wpsdb_delete_migration_profile', profile_id : $(this).attr('data-profile-id') }, error: function(jqXHR, textStatus, errorThrown){ @@ -1589,7 +1589,7 @@ var migration_complete_events; dataType: 'text', cache: false, data: { - action : 'wpmdb_save_setting', + action : 'wpsdb_save_setting', checked : checked, setting : setting }, @@ -1695,7 +1695,7 @@ var migration_complete_events; return; } - if( wpmdb_openssl_available == false ) { + if( wpsdb_openssl_available == false ) { connection_info[0] = connection_info[0].replace('https://','http://'); var new_connection_info_contents = connection_info[0] + "\n" + connection_info[1]; $('.pull-push-connection-info').val(new_connection_info_contents); @@ -1732,7 +1732,7 @@ var migration_complete_events; dataType: 'json', cache: false, data: { - action: 'wpmdb_verify_connection_to_remote_site', + action: 'wpsdb_verify_connection_to_remote_site', url: connection_info[0], key: connection_info[1], intent: intent, @@ -1749,7 +1749,7 @@ var migration_complete_events; doing_ajax = false; enable_export_type_controls(); - if( typeof data.wpmdb_error != 'undefined' && data.wpmdb_error == 1 ){ + if( typeof data.wpsdb_error != 'undefined' && data.wpsdb_error == 1 ){ $('.connection-status').html( data.body ); $('.connection-status').addClass( 'notification-message error-notice migration-error' ); @@ -1812,10 +1812,10 @@ var migration_complete_events; pull_post_type_select = post_type_select; if( $('#pull').is(':checked') ){ - $('#new-url').val( remove_protocol( wpmdb_this_url ) ); - $('#new-path').val( wpmdb_this_path ); - if( wpmdb_is_multisite == true ) { - $('#new-domain').val( wpmdb_this_domain ); + $('#new-url').val( remove_protocol( wpsdb_this_url ) ); + $('#new-path').val( wpsdb_this_path ); + if( wpsdb_is_multisite == true ) { + $('#new-domain').val( wpsdb_this_domain ); } $('#old-url').val( remove_protocol( data.url ) ); $('#old-path').val( data.path ); @@ -1824,7 +1824,7 @@ var migration_complete_events; $('#select-post-types').remove(); $('.select-post-types-wrap').prepend(pull_post_type_select); $('.table-prefix').html(data.prefix); - $('.uploads-dir').html(wpmdb_this_uploads_dir); + $('.uploads-dir').html(wpsdb_this_uploads_dir); } else{ $('#select-backup').remove(); @@ -1833,7 +1833,7 @@ var migration_complete_events; $('#new-path').val( data.path ); } - $.wpmdb.do_action( 'verify_connection_to_remote_site', connection_data ); + $.wpsdb.do_action( 'verify_connection_to_remote_site', connection_data ); } }); diff --git a/asset/sass/_mp6.scss b/asset/sass/_mp6.scss index 183c19b..73407c0 100755 --- a/asset/sass/_mp6.scss +++ b/asset/sass/_mp6.scss @@ -5,7 +5,7 @@ body.mp6 { border-color: #ccc; } - #wpmdb-main { + #wpsdb-main { margin-top: 15px; font-size: 14px; } @@ -18,7 +18,7 @@ body.mp6 { float: left; } - .wpmdb { + .wpsdb { input[type=checkbox], input[type=radio]{ vertical-align: middle; diff --git a/asset/sass/styles.scss b/asset/sass/styles.scss index 1231cdb..678b4dc 100755 --- a/asset/sass/styles.scss +++ b/asset/sass/styles.scss @@ -1,6 +1,6 @@ @import "compass"; -#wpmdb-main { +#wpsdb-main { width: 742px; } @@ -8,7 +8,7 @@ background-color: rgba(255,255,255,0.9); } -.wpmdb{ +.wpsdb{ > div.updated.warning { max-width: 742px; -moz-box-sizing: border-box; diff --git a/class/wpmdb-addon.php b/class/wpsdb-addon.php similarity index 67% rename from class/wpmdb-addon.php rename to class/wpsdb-addon.php index 8144d71..c4eb9bf 100644 --- a/class/wpmdb-addon.php +++ b/class/wpsdb-addon.php @@ -1,36 +1,36 @@ get_plugin_file_path() ); + function get_wpsdb_basename() { + global $wpsdb; + return plugin_basename( $wpsdb->get_plugin_file_path() ); } function meets_version_requirements( $version_required ) { - $wpmdb_version = $this->get_installed_version( $this->get_wpmdb_basename() ); - $result = version_compare( $wpmdb_version, $version_required, '>=' ); + $wpsdb_version = $this->get_installed_version( $this->get_wpsdb_basename() ); + $result = version_compare( $wpsdb_version, $version_required, '>=' ); $this->version_required = $version_required; if( false == $result ) $this->hook_version_requirement_actions(); return $result; } function hook_version_requirement_actions() { - add_action( 'wpmdb_notices', array( $this, 'version_requirement_actions' ) ); + add_action( 'wpsdb_notices', array( $this, 'version_requirement_actions' ) ); } function version_requirement_actions() { - $addon_requirement_check = get_option( 'wpmdb_addon_requirement_check', array() ); + $addon_requirement_check = get_option( 'wpsdb_addon_requirement_check', array() ); // we only want to delete the transients once, here we keep track of which versions we've checked if( ! isset( $addon_requirement_check[$this->plugin_slug] ) || $addon_requirement_check[$this->plugin_slug] != $this->get_installed_version() ) { - delete_site_transient( 'wpmdb_upgrade_data' ); + delete_site_transient( 'wpsdb_upgrade_data' ); delete_site_transient( 'update_plugins' ); $addon_requirement_check[$this->plugin_slug] = $this->get_installed_version(); - update_option( 'wpmdb_addon_requirement_check', $addon_requirement_check ); + update_option( 'wpsdb_addon_requirement_check', $addon_requirement_check ); } $this->version_requirement_warning(); } @@ -40,11 +40,11 @@ function version_requirement_warning() { ?>

    Update Requiredget_wpmdb_basename(); + $wpsdb_basename = $this->get_wpsdb_basename(); $addon_name = $this->get_plugin_name(); $required = $this->version_required; - $installed = $this->get_installed_version( $wpmdb_basename ); - $update = wp_nonce_url( network_admin_url( 'update.php?action=upgrade-plugin&plugin=' . urlencode( $wpmdb_basename ) ), 'upgrade-plugin_' . $wpmdb_basename ); + $installed = $this->get_installed_version( $wpsdb_basename ); + $update = wp_nonce_url( network_admin_url( 'update.php?action=upgrade-plugin&plugin=' . urlencode( $wpsdb_basename ) ), 'upgrade-plugin_' . $wpsdb_basename ); echo sprintf( 'The version of %s you have installed, requires version %s of WP Migrate DB. You currently have %s installed. Update Now', $addon_name, $required, $installed, $update ); ?>

    diff --git a/class/wpmdb-base.php b/class/wpsdb-base.php similarity index 94% rename from class/wpmdb-base.php rename to class/wpsdb-base.php index 29811bf..ea781dd 100755 --- a/class/wpmdb-base.php +++ b/class/wpsdb-base.php @@ -1,5 +1,5 @@ settings = get_option( 'wpmdb_settings' ); + $this->settings = get_option( 'wpsdb_settings' ); $this->addons = array( - 'wp-migrate-db-media-files/wp-migrate-db-media-files.php' => array( + 'wp-sync-db-media-files/wp-sync-db-media-files.php' => array( 'name' => 'Media Files', 'required_version' => '1.0.1', ) @@ -39,14 +39,14 @@ function __construct( $plugin_file_path ) { $this->plugin_title = str_ireplace( array( 'db', 'wp' ), array( 'DB', 'WP' ), $this->plugin_title ); if ( is_multisite() ) { - $this->plugin_base = 'settings.php?page=wp-migrate-db'; + $this->plugin_base = 'settings.php?page=wp-sync-db'; } else { - $this->plugin_base = 'tools.php?page=wp-migrate-db'; + $this->plugin_base = 'tools.php?page=wp-sync-db'; } // allow devs to change the temporary prefix applied to the tables - $this->temp_prefix = apply_filters( 'wpmdb_temporary_prefix', $this->temp_prefix ); + $this->temp_prefix = apply_filters( 'wpsdb_temporary_prefix', $this->temp_prefix ); } function printer( $debug ) { @@ -104,7 +104,7 @@ function remote_post( $url, $data, $scope, $args = array(), $expecting_serial = $sslverify = ( $this->settings['verify_ssl'] == 1 ? true : false ); - $default_remote_post_timeout = apply_filters( 'wpmdb_default_remote_post_timeout', 60 * 20 ); + $default_remote_post_timeout = apply_filters( 'wpsdb_default_remote_post_timeout', 60 * 20 ); $args = wp_parse_args( $args, array( 'timeout' => $default_remote_post_timeout, @@ -241,23 +241,23 @@ function file_to_multipart( $file ) { return $result; } - function log_error( $wpmdb_error, $additional_error_var = false ){ + function log_error( $wpsdb_error, $additional_error_var = false ){ $error_header = "********************************************\n****** Log date: " . date( 'Y/m/d H:i:s' ) . " ******\n********************************************\n\n"; - $error = $error_header . "WPMDB Error: " . $wpmdb_error . "\n\n"; + $error = $error_header . "WPSDB Error: " . $wpsdb_error . "\n\n"; if( ! empty( $this->attempting_to_connect_to ) ) { $error .= "Attempted to connect to: " . $this->attempting_to_connect_to . "\n\n"; } if( $additional_error_var !== false ){ $error .= print_r( $additional_error_var, true ) . "\n\n"; } - $log = get_option( 'wpmdb_error_log' ); + $log = get_option( 'wpsdb_error_log' ); if( $log ) { $log = $log . $error; } else { $log = $error; } - update_option( 'wpmdb_error_log', $log ); + update_option( 'wpsdb_error_log', $log ); } function display_errors() { @@ -325,7 +325,7 @@ function get_tables( $scope = 'regular' ) { } $clean_tables[] = $table[0]; } - return apply_filters( 'wpmdb_tables', $clean_tables, $scope ); + return apply_filters( 'wpsdb_tables', $clean_tables, $scope ); } function plugins_dir() { diff --git a/class/wpmdb.php b/class/wpsdb.php similarity index 90% rename from class/wpmdb.php rename to class/wpsdb.php index 5ab5841..da08fed 100755 --- a/class/wpmdb.php +++ b/class/wpsdb.php @@ -1,5 +1,5 @@ settings['max_request'] ) ) { $this->settings['max_request'] = min( 1024 * 1024, $this->get_bottleneck( 'max' ) ); - update_option( 'wpmdb_settings', $this->settings ); + update_option( 'wpsdb_settings', $this->settings ); } // if no settings exist then this is a fresh install, set up some default settings if ( empty( $this->settings ) ) { $this->settings = $default_settings; - update_option( 'wpmdb_settings', $this->settings ); + update_option( 'wpsdb_settings', $this->settings ); } // When we add a new setting, an existing customer's db won't have this // new setting, so we need to add it. Otherwise, they'll see @@ -56,7 +56,7 @@ function __construct( $plugin_file_path ) { } if ( $update_settings ) { - update_option( 'wpmdb_settings', $this->settings ); + update_option( 'wpsdb_settings', $this->settings ); } } @@ -64,27 +64,27 @@ function __construct( $plugin_file_path ) { add_filter( 'network_admin_plugin_action_links_' . $this->plugin_basename, array( $this, 'plugin_action_links' ) ); // internal AJAX handlers - add_action( 'wp_ajax_wpmdb_verify_connection_to_remote_site', array( $this, 'ajax_verify_connection_to_remote_site' ) ); - add_action( 'wp_ajax_wpmdb_reset_api_key', array( $this, 'ajax_reset_api_key' ) ); - add_action( 'wp_ajax_wpmdb_delete_migration_profile', array( $this, 'ajax_delete_migration_profile' ) ); - add_action( 'wp_ajax_wpmdb_save_setting', array( $this, 'ajax_save_setting' ) ); - add_action( 'wp_ajax_wpmdb_save_profile', array( $this, 'ajax_save_profile' ) ); - add_action( 'wp_ajax_wpmdb_initiate_migration', array( $this, 'ajax_initiate_migration' ) ); - add_action( 'wp_ajax_wpmdb_migrate_table', array( $this, 'ajax_migrate_table' ) ); - add_action( 'wp_ajax_wpmdb_finalize_migration', array( $this, 'ajax_finalize_migration' ) ); - add_action( 'wp_ajax_wpmdb_clear_log', array( $this, 'ajax_clear_log' ) ); - add_action( 'wp_ajax_wpmdb_get_log', array( $this, 'ajax_get_log' ) ); - add_action( 'wp_ajax_wpmdb_fire_migration_complete', array( $this, 'fire_migration_complete' ) ); - add_action( 'wp_ajax_wpmdb_update_max_request_size', array( $this, 'ajax_update_max_request_size' ) ); + add_action( 'wp_ajax_wpsdb_verify_connection_to_remote_site', array( $this, 'ajax_verify_connection_to_remote_site' ) ); + add_action( 'wp_ajax_wpsdb_reset_api_key', array( $this, 'ajax_reset_api_key' ) ); + add_action( 'wp_ajax_wpsdb_delete_migration_profile', array( $this, 'ajax_delete_migration_profile' ) ); + add_action( 'wp_ajax_wpsdb_save_setting', array( $this, 'ajax_save_setting' ) ); + add_action( 'wp_ajax_wpsdb_save_profile', array( $this, 'ajax_save_profile' ) ); + add_action( 'wp_ajax_wpsdb_initiate_migration', array( $this, 'ajax_initiate_migration' ) ); + add_action( 'wp_ajax_wpsdb_migrate_table', array( $this, 'ajax_migrate_table' ) ); + add_action( 'wp_ajax_wpsdb_finalize_migration', array( $this, 'ajax_finalize_migration' ) ); + add_action( 'wp_ajax_wpsdb_clear_log', array( $this, 'ajax_clear_log' ) ); + add_action( 'wp_ajax_wpsdb_get_log', array( $this, 'ajax_get_log' ) ); + add_action( 'wp_ajax_wpsdb_fire_migration_complete', array( $this, 'fire_migration_complete' ) ); + add_action( 'wp_ajax_wpsdb_update_max_request_size', array( $this, 'ajax_update_max_request_size' ) ); // external AJAX handlers - add_action( 'wp_ajax_nopriv_wpmdb_verify_connection_to_remote_site', array( $this, 'respond_to_verify_connection_to_remote_site' ) ); - add_action( 'wp_ajax_nopriv_wpmdb_remote_initiate_migration', array( $this, 'respond_to_remote_initiate_migration' ) ); - add_action( 'wp_ajax_nopriv_wpmdb_process_chunk', array( $this, 'ajax_process_chunk' ) ); - add_action( 'wp_ajax_nopriv_wpmdb_process_pull_request', array( $this, 'respond_to_process_pull_request' ) ); - add_action( 'wp_ajax_nopriv_wpmdb_fire_migration_complete', array( $this, 'fire_migration_complete' ) ); - add_action( 'wp_ajax_nopriv_wpmdb_backup_remote_table', array( $this, 'respond_to_backup_remote_table' ) ); - add_action( 'wp_ajax_nopriv_wpmdb_remote_finalize_migration', array( $this, 'respond_to_remote_finalize_migration' ) ); + add_action( 'wp_ajax_nopriv_wpsdb_verify_connection_to_remote_site', array( $this, 'respond_to_verify_connection_to_remote_site' ) ); + add_action( 'wp_ajax_nopriv_wpsdb_remote_initiate_migration', array( $this, 'respond_to_remote_initiate_migration' ) ); + add_action( 'wp_ajax_nopriv_wpsdb_process_chunk', array( $this, 'ajax_process_chunk' ) ); + add_action( 'wp_ajax_nopriv_wpsdb_process_pull_request', array( $this, 'respond_to_process_pull_request' ) ); + add_action( 'wp_ajax_nopriv_wpsdb_fire_migration_complete', array( $this, 'fire_migration_complete' ) ); + add_action( 'wp_ajax_nopriv_wpsdb_backup_remote_table', array( $this, 'respond_to_backup_remote_table' ) ); + add_action( 'wp_ajax_nopriv_wpsdb_remote_finalize_migration', array( $this, 'respond_to_remote_finalize_migration' ) ); $absolute_path = rtrim( ABSPATH, '\\/' ); $site_url = rtrim( site_url( '', 'http' ), '\\/' ); @@ -153,21 +153,21 @@ function __construct( $plugin_file_path ) { add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) ); // this is how many DB rows are processed at a time, allow devs to change this value - $this->rows_per_segment = apply_filters( 'wpmdb_rows_per_segment', $this->rows_per_segment ); + $this->rows_per_segment = apply_filters( 'wpsdb_rows_per_segment', $this->rows_per_segment ); if ( is_multisite() ) { add_action( 'network_admin_menu', array( $this, 'network_admin_menu' ) ); - $this->plugin_base = 'settings.php?page=wp-migrate-db'; + $this->plugin_base = 'settings.php?page=wp-sync-db'; } else { add_action( 'admin_menu', array( $this, 'admin_menu' ) ); - $this->plugin_base = 'tools.php?page=wp-migrate-db'; + $this->plugin_base = 'tools.php?page=wp-sync-db'; } } function check_again_clear_transients( $current_screen ) { if( ! isset( $current_screen->id ) || strpos( $current_screen->id, 'update-core' ) === false || ! isset( $_GET['force-check'] ) ) return; - delete_site_transient( 'wpmdb_upgrade_data' ); + delete_site_transient( 'wpsdb_upgrade_data' ); delete_site_transient( 'update_plugins' ); } @@ -176,7 +176,7 @@ function get_alter_table_name() { return $this->alter_table_name; } global $wpdb; - $this->alter_table_name = apply_filters( 'wpmdb_alter_table_name', $wpdb->prefix . 'wpmdb_alter_statements' ); + $this->alter_table_name = apply_filters( 'wpsdb_alter_table_name', $wpdb->prefix . 'wpsdb_alter_statements' ); return $this->alter_table_name; } @@ -187,7 +187,7 @@ function get_create_alter_table_query() { $alter_table_name = $this->get_alter_table_name(); $this->create_alter_table_query = sprintf( "DROP TABLE IF EXISTS `%s`;\n", $alter_table_name ); $this->create_alter_table_query .= sprintf( "CREATE TABLE `%s` ( `query` longtext NOT NULL );\n", $alter_table_name ); - $this->create_alter_table_query = apply_filters( 'wpmdb_create_alter_table_query', $this->create_alter_table_query ); + $this->create_alter_table_query = apply_filters( 'wpsdb_create_alter_table_query', $this->create_alter_table_query ); return $this->create_alter_table_query; } @@ -203,7 +203,7 @@ function get_upload_info( $type = 'path' ) { // 'path' => '/path/to/custom/uploads/directory', <- note missing end trailing slash // 'url' => 'http://yourwebsite.com/custom/uploads/directory' <- note missing end trailing slash // ); - $upload_info = apply_filters( 'wpmdb_upload_info', array() ); + $upload_info = apply_filters( 'wpsdb_upload_info', array() ); if ( !empty( $upload_info ) ) { return $upload_info[$type]; } @@ -213,10 +213,10 @@ function get_upload_info( $type = 'path' ) { $upload_info['path'] = $upload_dir['basedir']; $upload_info['url'] = $upload_dir['baseurl']; - $upload_dir_name = apply_filters( 'wpmdb_upload_dir_name', 'wp-migrate-db' ); + $upload_dir_name = apply_filters( 'wpsdb_upload_dir_name', 'wp-sync-db' ); if( ! file_exists( $upload_dir['basedir'] . DS . $upload_dir_name ) ) { - $url = wp_nonce_url( $this->plugin_base, 'wp-migrate-db-nonce' ); + $url = wp_nonce_url( $this->plugin_base, 'wp-sync-db-nonce' ); if( false === @mkdir( $upload_dir['basedir'] . DS . $upload_dir_name, 0755 ) ) { return $upload_info[$type]; @@ -236,7 +236,7 @@ function get_upload_info( $type = 'path' ) { function ajax_update_max_request_size() { $this->settings['max_request'] = (int) $_POST['max_request_size'] * 1024; - update_option( 'wpmdb_settings', $this->settings ); + update_option( 'wpsdb_settings', $this->settings ); $result = $this->end_ajax(); return $result; } @@ -258,7 +258,7 @@ function get_sql_dump_info( $migration_type, $info_type ) { function parse_migration_form_data( $data ) { parse_str( $data, $form_data ); - $this->accepted_fields = apply_filters( 'wpmdb_accepted_profile_fields', $this->accepted_fields ); + $this->accepted_fields = apply_filters( 'wpsdb_accepted_profile_fields', $this->accepted_fields ); $form_data = array_intersect_key( $form_data, array_flip( $this->accepted_fields ) ); unset( $form_data['replace_old'][0] ); unset( $form_data['replace_new'][0] ); @@ -266,13 +266,13 @@ function parse_migration_form_data( $data ) { } function plugin_action_links( $links ) { - $link = sprintf( '%s', network_admin_url( $this->plugin_base ), __( 'Settings', 'wp-migrate-db' ) ); + $link = sprintf( '%s', network_admin_url( $this->plugin_base ), __( 'Settings', 'wp-sync-db' ) ); array_unshift( $links, $link ); return $links; } function ajax_clear_log() { - delete_option( 'wpmdb_error_log' ); + delete_option( 'wpsdb_error_log' ); $result = $this->end_ajax(); return $result; } @@ -287,7 +287,7 @@ function ajax_get_log() { } function output_log_file() { - $log = get_option( 'wpmdb_error_log' ); + $log = get_option( 'wpsdb_error_log' ); if( $log ) { echo $log; } @@ -328,7 +328,7 @@ function output_diagnostic_info() { echo WP_MEMORY_LIMIT; echo "\r\n"; - _e( 'WPMDB Bottleneck', 'wp-app-store' ); echo ': '; + _e( 'WPSDB Bottleneck', 'wp-app-store' ); echo ': '; echo size_format( $this->get_bottleneck() ); echo "\r\n"; @@ -420,7 +420,7 @@ function fire_migration_complete() { return $result; } - do_action( 'wpmdb_migration_complete', 'pull', $_POST['url'] ); + do_action( 'wpsdb_migration_complete', 'pull', $_POST['url'] ); $result = $this->end_ajax(); return $result; } @@ -446,9 +446,9 @@ function ajax_finalize_migration() { $return = $this->finalize_migration(); } else { - do_action( 'wpmdb_migration_complete', 'push', $_POST['url'] ); + do_action( 'wpsdb_migration_complete', 'push', $_POST['url'] ); $data = $_POST; - $data['action'] = 'wpmdb_remote_finalize_migration'; + $data['action'] = 'wpsdb_remote_finalize_migration'; $data['intent'] = 'pull'; $data['prefix'] = $wpdb->prefix; $data['type'] = 'push'; @@ -489,14 +489,14 @@ function finalize_migration() { $sql = "SET FOREIGN_KEY_CHECKS=0;\n"; - $preserved_options = array( 'wpmdb_settings', 'wpmdb_error_log' ); + $preserved_options = array( 'wpsdb_settings', 'wpsdb_error_log' ); $this->form_data = $this->parse_migration_form_data( $_POST['form_data'] ); if( isset( $this->form_data['keep_active_plugins'] ) ) { $preserved_options[] = 'active_plugins'; } - $preserved_options = apply_filters( 'wpmdb_preserved_options', $preserved_options ); + $preserved_options = apply_filters( 'wpsdb_preserved_options', $preserved_options ); foreach ( $temp_tables as $table ) { $sql .= 'DROP TABLE IF EXISTS ' . $this->backquote( substr( $table, strlen( $temp_prefix ) ) ) . ';'; @@ -527,7 +527,7 @@ function finalize_migration() { if( ! isset( $_POST['location'] ) ) { $data = array(); - $data['action'] = 'wpmdb_fire_migration_complete'; + $data['action'] = 'wpsdb_fire_migration_complete'; $data['url'] = home_url(); $data['sig'] = $this->create_signature( $data, $_POST['key'] ); $ajax_url = trailingslashit( $_POST['url'] ) . 'wp-admin/admin-ajax.php'; @@ -545,7 +545,7 @@ function finalize_migration() { // flush rewrite rules to prevent 404s and other oddities flush_rewrite_rules( true ); // true = hard refresh, recreates the .htaccess file - do_action( 'wpmdb_migration_complete', $type, $location ); + do_action( 'wpsdb_migration_complete', $type, $location ); } function ajax_process_chunk() { @@ -627,7 +627,7 @@ function ajax_migrate_table() { // if performing a push we need to backup the REMOTE machine's DB if ( $_POST['intent'] == 'push' ) { $data = $_POST; - $data['action'] = 'wpmdb_backup_remote_table'; + $data['action'] = 'wpsdb_backup_remote_table'; $data['intent'] = 'pull'; $ajax_url = trailingslashit( $_POST['url'] ) . 'wp-admin/admin-ajax.php'; $data['primary_keys'] = stripslashes( $data['primary_keys'] ); @@ -676,7 +676,7 @@ function ajax_migrate_table() { } else { $data = $_POST; - $data['action'] = 'wpmdb_process_pull_request'; + $data['action'] = 'wpsdb_process_pull_request'; $data['pull_limit'] = $this->get_sensible_pull_limit(); if( is_multisite() ) { $data['path_current_site'] = $this->get_path_current_site(); @@ -834,7 +834,7 @@ function ajax_initiate_migration() { else { // does one last check that our verification string is valid $data = array( - 'action' => 'wpmdb_remote_initiate_migration', + 'action' => 'wpsdb_remote_initiate_migration', 'intent' => $_POST['intent'], 'form_data' => $_POST['form_data'], ); @@ -844,7 +844,7 @@ function ajax_initiate_migration() { $response = $this->remote_post( $ajax_url, $data, __FUNCTION__ ); if ( false === $response ) { - $return = array( 'wpmdb_error' => 1, 'body' => $this->error ); + $return = array( 'wpsdb_error' => 1, 'body' => $this->error ); $result = $this->end_ajax( json_encode( $return ) ); return $result; } @@ -928,14 +928,14 @@ function ajax_save_profile() { $this->settings['profiles'][$key] = $profile; $this->settings['profiles'][$key]['name'] = $name; } - update_option( 'wpmdb_settings', $this->settings ); + update_option( 'wpsdb_settings', $this->settings ); $result = $this->end_ajax( count( $this->settings['profiles'] ) - 1 ); return $result; } function ajax_save_setting() { $this->settings[$_POST['setting']] = ( $_POST['checked'] == 'false' ? false : true ); - update_option( 'wpmdb_settings', $this->settings ); + update_option( 'wpsdb_settings', $this->settings ); $result = $this->end_ajax(); return $result; } @@ -945,7 +945,7 @@ function ajax_delete_migration_profile() { $return = ''; if ( isset( $this->settings['profiles'][$key] ) ) { unset( $this->settings['profiles'][$key] ); - update_option( 'wpmdb_settings', $this->settings ); + update_option( 'wpsdb_settings', $this->settings ); } else { $return = '-1'; @@ -956,7 +956,7 @@ function ajax_delete_migration_profile() { function ajax_reset_api_key() { $this->settings['key'] = $this->generate_key(); - update_option( 'wpmdb_settings', $this->settings ); + update_option( 'wpsdb_settings', $this->settings ); $result = $this->end_ajax( sprintf( "%s\n%s", site_url( '', 'https' ), $this->settings['key'] ) ); return $result; } @@ -965,13 +965,13 @@ function ajax_reset_api_key() { // Responsible for contacting the remote website and retrieving info and testing the verification string function ajax_verify_connection_to_remote_site() { $data = array( - 'action' => 'wpmdb_verify_connection_to_remote_site', + 'action' => 'wpsdb_verify_connection_to_remote_site', 'intent' => $_POST['intent'] ); $data['sig'] = $this->create_signature( $data, $_POST['key'] ); $ajax_url = trailingslashit( $_POST['url'] ) . 'wp-admin/admin-ajax.php'; - $timeout = apply_filters( 'wpmdb_prepare_remote_connection_timeout', 10 ); + $timeout = apply_filters( 'wpsdb_prepare_remote_connection_timeout', 10 ); $response = $this->remote_post( $ajax_url, $data, __FUNCTION__, compact( 'timeout' ), true ); $url_bits = parse_url( $this->attempting_to_connect_to ); $return = $response; @@ -979,7 +979,7 @@ function ajax_verify_connection_to_remote_site() { $alt_action = ''; if ( false === $response ) { - $return = array( 'wpmdb_error' => 1, 'body' => $this->error ); + $return = array( 'wpsdb_error' => 1, 'body' => $this->error ); $result = $this->end_ajax( json_encode( $return ) ); return $result; } @@ -987,7 +987,7 @@ function ajax_verify_connection_to_remote_site() { $response = unserialize( trim( $response ) ); if ( isset( $response['error'] ) && $response['error'] == 1 ) { - $return = array( 'wpmdb_error' => 1, 'body' => $response['message'] ); + $return = array( 'wpsdb_error' => 1, 'body' => $response['message'] ); $result = $this->end_ajax( json_encode( $return ) ); return $result; } @@ -1039,7 +1039,7 @@ function respond_to_verify_connection_to_remote_site() { $return['write_permissions'] = ( is_writeable( $this->get_upload_info( 'path' ) ) ? '1' : '0' ); $return['upload_dir_long'] = $this->get_upload_info( 'path' ); $return['temp_prefix'] = $this->temp_prefix; - $return = apply_filters( 'wpmdb_establish_remote_connection_data', $return ); + $return = apply_filters( 'wpsdb_establish_remote_connection_data', $return ); $result = $this->end_ajax( serialize( $return ) ); return $result; } @@ -1084,7 +1084,7 @@ function get_post_types() { foreach( $post_types as $post_type ) { $return[] = $post_type['post_type']; } - return apply_filters( 'wpmdb_post_types', array_unique( $return ) ); + return apply_filters( 'wpsdb_post_types', array_unique( $return ) ); } // Retrieves the specified profile, if -1, returns the default profile @@ -1126,7 +1126,7 @@ function get_table_sizes( $scope = 'regular' ) { $return[$result['table']] = $result['size']; } - return apply_filters( 'wpmdb_table_sizes', $return, $scope ); + return apply_filters( 'wpsdb_table_sizes', $return, $scope ); } function get_post_max_size() { @@ -1144,7 +1144,7 @@ function get_post_max_size() { } function get_sensible_pull_limit() { - return apply_filters( 'wpmdb_sensible_pull_limit', min( 26214400, $this->settings['max_request'] ) ); + return apply_filters( 'wpsdb_sensible_pull_limit', min( 26214400, $this->settings['max_request'] ) ); } function get_bottleneck( $type = 'regular' ) { @@ -1162,7 +1162,7 @@ function get_bottleneck( $type = 'regular' ) { } // we have to account for HTTP headers and other bloating, here we minus 1kb for bloat - $post_max_upper_size = apply_filters( 'wpmdb_post_max_upper_size', 26214400 ); + $post_max_upper_size = apply_filters( 'wpsdb_post_max_upper_size', 26214400 ); $calculated_bottleneck = min( ( $this->get_post_max_size() - 1024 ), $post_max_upper_size ); if ( $suhosin_limit ) { @@ -1173,7 +1173,7 @@ function get_bottleneck( $type = 'regular' ) { $calculated_bottleneck = min( $calculated_bottleneck, $this->settings['max_request'] ); } - return apply_filters( 'wpmdb_bottleneck', $calculated_bottleneck ); + return apply_filters( 'wpsdb_bottleneck', $calculated_bottleneck ); } function format_dump_name( $dump_name ) { @@ -1188,16 +1188,16 @@ function format_dump_name( $dump_name ) { function options_page() { ?> -
    +

    Migrate DB

    - + addons as $addon_basename => $addon ) { if( false == $this->is_addon_outdated( $addon_basename ) || false == is_plugin_active( $addon_basename ) ) continue; @@ -1212,7 +1212,7 @@ function options_page() {
    @@ -1244,7 +1244,7 @@ function options_page() {
    set_time_limit_available() && !$hide_warning && !$safe_mode ) { ?>
    @@ -1263,11 +1263,11 @@ function options_page() { } ?> -
    +
    1 profile saved - if ( ! empty( $this->settings['profiles'] ) && ! isset( $_GET['wpmdb-profile'] ) ) { + if ( ! empty( $this->settings['profiles'] ) && ! isset( $_GET['wpsdb-profile'] ) ) { $this->template( 'profile' ); } else { @@ -1282,7 +1282,7 @@ function options_page() { $this->template( 'help' ); ?> -
    +
    form_data['action'] == 'savefile' || $_POST['stage'] == 'backup' ) { $this->stow( "\n\n" ); $this->stow( "#\n" ); - $this->stow( "# " . sprintf( __( 'Delete any existing table %s', 'wp-migrate-db' ), $this->backquote( $table ) ) . "\n" ); + $this->stow( "# " . sprintf( __( 'Delete any existing table %s', 'wp-sync-db' ), $this->backquote( $table ) ) . "\n" ); $this->stow( "#\n" ); $this->stow( "\n" ); $this->stow( "DROP TABLE IF EXISTS " . $this->backquote( $table ) . ";\n" ); @@ -1450,7 +1450,7 @@ function export_table( $table ) { if ( $this->form_data['action'] == 'savefile' || $_POST['stage'] == 'backup' ) { $this->stow( "\n\n" ); $this->stow( "#\n" ); - $this->stow( "# " . sprintf( __( 'Table structure of table %s', 'wp-migrate-db' ), $this->backquote( $table ) ) . "\n" ); + $this->stow( "# " . sprintf( __( 'Table structure of table %s', 'wp-sync-db' ), $this->backquote( $table ) ) . "\n" ); $this->stow( "#\n" ); $this->stow( "\n" ); } @@ -1470,7 +1470,7 @@ function export_table( $table ) { $alter_table_query = ''; $create_table[0][1] = $this->process_sql_constraint( $create_table[0][1], $table, $alter_table_query ); - $create_table[0][1] = apply_filters( 'wpmdb_create_table_query', $create_table[0][1], $table ); + $create_table[0][1] = apply_filters( 'wpsdb_create_table_query', $create_table[0][1], $table ); $this->stow( $create_table[0][1] . ";\n" ); @@ -1493,7 +1493,7 @@ function export_table( $table ) { if ( $this->form_data['action'] == 'savefile' || $_POST['stage'] == 'backup' ) { $this->stow( "\n\n" ); $this->stow( "#\n" ); - $this->stow( '# ' . sprintf( __( 'Data contents of table %s', 'wp-migrate-db' ), $this->backquote( $table ) ) . "\n" ); + $this->stow( '# ' . sprintf( __( 'Data contents of table %s', 'wp-sync-db' ), $this->backquote( $table ) ) . "\n" ); $this->stow( "#\n" ); } } @@ -1602,7 +1602,7 @@ function export_table( $table ) { } } - if ( true === apply_filters( 'wpmdb_exclude_transients', true ) && ( $this->table_is( 'options', $table ) || ( isset( $wpdb->sitemeta ) && $wpdb->sitemeta == $table ) ) ) { + if ( true === apply_filters( 'wpsdb_exclude_transients', true ) && ( $this->table_is( 'options', $table ) || ( isset( $wpdb->sitemeta ) && $wpdb->sitemeta == $table ) ) ) { $col_name = 'option_name'; if( isset( $wpdb->sitemeta ) && $wpdb->sitemeta == $table ) { @@ -1655,13 +1655,13 @@ function export_table( $table ) { } $join = implode( ' ', array_unique( $join ) ); - $join = apply_filters( 'wpmdb_rows_join', $join, $table ); - $where = apply_filters( 'wpmdb_rows_where', $where, $table ); - $order_by = apply_filters( 'wpmdb_rows_order_by', $order_by, $table ); - $limit = apply_filters( 'wpmdb_rows_limit', $limit, $table ); + $join = apply_filters( 'wpsdb_rows_join', $join, $table ); + $where = apply_filters( 'wpsdb_rows_where', $where, $table ); + $order_by = apply_filters( 'wpsdb_rows_order_by', $order_by, $table ); + $limit = apply_filters( 'wpsdb_rows_limit', $limit, $table ); $sql = "SELECT " . $this->backquote( $table ) . ".* FROM " . $this->backquote( $table ) . " $join $where $order_by $limit"; - $sql = apply_filters( 'wpmdb_rows_sql', $sql, $table ); + $sql = apply_filters( 'wpsdb_rows_sql', $sql, $table ); $table_data = $wpdb->get_results( $sql ); @@ -1706,7 +1706,7 @@ function export_table( $table ) { $main_domain_find = sprintf( "/%s/", $this->get_domain_current_site() ); $domain_replaces[$main_domain_find] = $main_domain_replace; - $domain_replaces = apply_filters( 'wpmdb_domain_replaces', $domain_replaces ); + $domain_replaces = apply_filters( 'wpsdb_domain_replaces', $domain_replaces ); $value = preg_replace( array_keys( $domain_replaces ), array_values( $domain_replaces ), $value ); } @@ -1781,7 +1781,7 @@ function export_table( $table ) { if ( $this->form_data['action'] == 'savefile' || $_POST['stage'] == 'backup' ) { $this->stow( "\n" ); $this->stow( "#\n" ); - $this->stow( "# " . sprintf( __( 'End of data contents of table %s', 'wp-migrate-db' ), $this->backquote( $table ) ) . "\n" ); + $this->stow( "# " . sprintf( __( 'End of data contents of table %s', 'wp-sync-db' ), $this->backquote( $table ) ) . "\n" ); $this->stow( "# --------------------------------------------------------\n" ); $this->stow( "\n" ); @@ -1895,11 +1895,11 @@ function recursive_unserialize_replace( $data, $serialized = false, $parent_seri function db_backup_header() { $charset = ( defined( 'DB_CHARSET' ) ? DB_CHARSET : 'utf8' ); - $this->stow( "# " . __( 'WordPress MySQL database migration', 'wp-migrate-db' ) . "\n", false ); + $this->stow( "# " . __( 'WordPress MySQL database migration', 'wp-sync-db' ) . "\n", false ); $this->stow( "#\n", false ); - $this->stow( "# " . sprintf( __( 'Generated: %s', 'wp-migrate-db' ), date( "l j. F Y H:i T" ) ) . "\n", false ); - $this->stow( "# " . sprintf( __( 'Hostname: %s', 'wp-migrate-db' ), DB_HOST ) . "\n", false ); - $this->stow( "# " . sprintf( __( 'Database: %s', 'wp-migrate-db' ), $this->backquote( DB_NAME ) ) . "\n", false ); + $this->stow( "# " . sprintf( __( 'Generated: %s', 'wp-sync-db' ), date( "l j. F Y H:i T" ) ) . "\n", false ); + $this->stow( "# " . sprintf( __( 'Hostname: %s', 'wp-sync-db' ), DB_HOST ) . "\n", false ); + $this->stow( "# " . sprintf( __( 'Database: %s', 'wp-sync-db' ), $this->backquote( DB_NAME ) ) . "\n", false ); $this->stow( "# --------------------------------------------------------\n\n", false ); $this->stow( "/*!40101 SET NAMES $charset */;\n\n", false ); $this->stow( "SET sql_mode='NO_AUTO_VALUE_ON_ZERO';\n\n", false ); @@ -1970,7 +1970,7 @@ function transfer_chunk() { } $data = array( - 'action' => 'wpmdb_process_chunk', + 'action' => 'wpsdb_process_chunk', 'table' => $_POST['table'], 'chunk_gzipped' => $chunk_gzipped, 'chunk' => $this->current_chunk // NEEDS TO BE the last element in this array because of adding it back into the array in ajax_process_chunk() @@ -2029,12 +2029,12 @@ function sql_addslashes( $a_string = '', $is_like = false ) { } function network_admin_menu() { - $hook_suffix = add_submenu_page( 'settings.php', 'Migrate DB', 'Migrate DB', 'manage_network_options', 'wp-migrate-db', array( $this, 'options_page' ) ); + $hook_suffix = add_submenu_page( 'settings.php', 'Migrate DB', 'Migrate DB', 'manage_network_options', 'wp-sync-db', array( $this, 'options_page' ) ); $this->after_admin_menu( $hook_suffix ); } function admin_menu() { - $hook_suffix = add_management_page( 'Migrate DB', 'Migrate DB', 'export', 'wp-migrate-db', array( $this, 'options_page' ) ); + $hook_suffix = add_management_page( 'Migrate DB', 'Migrate DB', 'export', 'wp-sync-db', array( $this, 'options_page' ) ); $this->after_admin_menu( $hook_suffix ); } @@ -2072,18 +2072,18 @@ function load_assets() { $version = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? time() : $this->get_installed_version(); $src = $plugins_url . 'asset/css/styles.css'; - wp_enqueue_style( 'wp-migrate-db-styles', $src, array(), $version ); + wp_enqueue_style( 'wp-sync-db-styles', $src, array(), $version ); $src = $plugins_url . 'asset/js/common.js'; - wp_enqueue_script( 'wp-migrate-db-common', $src, NULL, $version, true ); + wp_enqueue_script( 'wp-sync-db-common', $src, NULL, $version, true ); $src = $plugins_url . 'asset/js/hook.js'; - wp_enqueue_script( 'wp-migrate-db-hook', $src, NULL, $version, true ); + wp_enqueue_script( 'wp-sync-db-hook', $src, NULL, $version, true ); - do_action( 'wpmdb_load_assets' ); + do_action( 'wpsdb_load_assets' ); $src = $plugins_url . 'asset/js/script.js'; - wp_enqueue_script( 'wp-migrate-db-script', $src, array( 'jquery' ), $version, true ); + wp_enqueue_script( 'wp-sync-db-script', $src, array( 'jquery' ), $version, true ); wp_enqueue_script('jquery'); wp_enqueue_script('jquery-ui-core'); @@ -2121,27 +2121,27 @@ function download_file() { function admin_head_connection_info() { global $table_prefix; ?> settings['profiles'][$profile_id] = $profile; - update_option( 'wpmdb_settings', $this->settings ); + update_option( 'wpsdb_settings', $this->settings ); return $profile; } @@ -2203,7 +2203,7 @@ function return_bytes($val) { } function end_ajax( $return = false ) { - if( defined( 'DOING_WPMDB_TESTS' ) ) { + if( defined( 'DOING_WPSDB_TESTS' ) ) { return ( false === $return ) ? NULL : $return; } diff --git a/template/help.php b/template/help.php index a98523e..bb89323 100755 --- a/template/help.php +++ b/template/help.php @@ -22,7 +22,7 @@

    Support

    -

    Please report bugs or ask questions in the GitHub Issue Tracker.

    +

    Please report bugs or ask questions in the GitHub Issue Tracker.

    Diagnostic Info & Error Log

    diff --git a/template/migrate.php b/template/migrate.php index 8c72e58..6321999 100644 --- a/template/migrate.php +++ b/template/migrate.php @@ -2,8 +2,8 @@ global $wpdb; global $loaded_profile; -if( isset( $_GET['wpmdb-profile'] ) ){ - $loaded_profile = $this->get_profile( $_GET['wpmdb-profile'] ); +if( isset( $_GET['wpsdb-profile'] ) ){ + $loaded_profile = $this->get_profile( $_GET['wpsdb-profile'] ); } else{ $loaded_profile = $this->default_profile; @@ -16,7 +16,7 @@ if( isset( $loaded_profile['exclude_revisions'] ) ) { $convert_exclude_revisions = true; } - $loaded_profile = $this->maybe_update_profile( $loaded_profile, $_GET['wpmdb-profile'] ); + $loaded_profile = $this->maybe_update_profile( $loaded_profile, $_GET['wpsdb-profile'] ); } if( false == $is_default_profile ) { @@ -24,16 +24,16 @@ } ?>
    @@ -355,7 +355,7 @@
    - +
    \ No newline at end of file +
    diff --git a/wp-migrate-db.php b/wp-sync-db.php similarity index 57% rename from wp-migrate-db.php rename to wp-sync-db.php index 4c7399a..c630ecd 100755 --- a/wp-migrate-db.php +++ b/wp-sync-db.php @@ -1,11 +1,11 @@ Date: Fri, 20 Jun 2014 23:16:12 -0400 Subject: [PATCH 25/52] remove sass it was removed from the distribution, and I don't really like sass much anyway --- asset/README.md | 4 - asset/sass/_mp6.scss | 331 ------------ asset/sass/styles.scss | 1167 ---------------------------------------- 3 files changed, 1502 deletions(-) delete mode 100644 asset/README.md delete mode 100755 asset/sass/_mp6.scss delete mode 100755 asset/sass/styles.scss diff --git a/asset/README.md b/asset/README.md deleted file mode 100644 index e81d6c6..0000000 --- a/asset/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# How to Compile the SASS -`cd` into this directory, and run `sass --compass ./sass/styles.scss ./css/styles.css` - -This project might be converted to use roots later, so nobody needs to remember what commands to use. diff --git a/asset/sass/_mp6.scss b/asset/sass/_mp6.scss deleted file mode 100755 index 73407c0..0000000 --- a/asset/sass/_mp6.scss +++ /dev/null @@ -1,331 +0,0 @@ -body.mp6 { - - input[type=checkbox]:disabled { - opacity: 1; - border-color: #ccc; - } - - #wpsdb-main { - margin-top: 15px; - font-size: 14px; - } - - p { - font-size: 14px; - } - - .wrap h2 { - float: left; - } - - .wpsdb { - input[type=checkbox], - input[type=radio]{ - vertical-align: middle; - margin-top: -4px; - } - - input[type=text], - input[type=password] { - padding: 3px 5px; - } - - input.code { - padding-top: 6px; - } - - label { - font-size: 14px; - } - - h2.nav-tab-wrapper { - float: none; - margin-bottom: 0; - width: 722px; - } - - .help-tab { - h3 { - margin-top: 0; - } - } - - .temp-disabled { - background-color: #f9f9f9; - } - - .migration-profile-options li a{ - border-color: #ccc; - color: #555; - background-color: #e4e4e4; - } - - .migration-profile-options li a:hover{ - background-color: #fff; - color: #464646; - } - - .settings-tab { - .slider-label { - span { - vertical-align: middle; - } - } - - .slider-label-wrapper { - font-size: 14px; - } - - .ui-slider { - border-color: #ccc; - background-color: #fff; - } - - .ui-slider-range { - background-color: #d8fcd1; - } - - .option-section { - li label { - font-size: 14px; - } - } - } - - .connection-info, - .migrate-tab .pull-push-connection-info { - font-weight: bold; - font-size: 14px; - } - - .general-helper { - border: 0; - width: auto; - height: auto; - top: auto; - margin: 0; - } - - .general-helper:after { - content: "\f223"; - display: inline-block; - -webkit-font-smoothing: antialiased; - font: normal 22px/1 'dashicons'; - vertical-align: top; - top: auto; - left: auto; - position: relative; - } - - .helper-message { - font-size: 14px; - line-height: 1.4em; - } - - .right-arrow { - display: none; - } - - .arrow-col { - width: 75px; - } - - .arrow-col:after { - content: "\f344"; - display: inline-block; - -webkit-font-smoothing: antialiased; - font: normal 22px/1 'dashicons'; - vertical-align: top; - color: #999; - } - - .find-heading { - width: 388px; - } - - .replace-fields { - input { - width: 304px; - } - } - - .replace-right-col { - span { - border-color: #999; - - &:hover { - border-color: #666; - } - } - } - - .replace-remove-row, .replace-add-row { - &:after, &:before { - background-color: #999; - } - - &:hover:after, &:hover:before { - background-color: #666; - } - } - - .option-group.migrate-selection { - > li > label { - font-size: 16px; - } - } - - .saved-migration-profile-label { - font-size: 16px; - } - - .option-heading, .checkbox-label { - font-size: 16px; - } - - .checkbox-label { - input[type=checkbox] { - top: auto; - } - } - - .return-to-profile-selection { - font-size: 14px; - } - - .option-description{ - font-size: 13px; - } - - .save-migration-profile-wrap { - li { - position: relative; - } - } - - .delete-profile { - border: 0; - border-radius: 0; - height: auto; - width: auto; - left: 0; - top: 50%; - margin-left: 0; - - &:after { - content: "\f153"; - display: inline-block; - -webkit-font-smoothing: antialiased; - font: normal 18px/1 'dashicons'; - vertical-align: middle; - color: #999; - } - - &:hover:after { - color: #666; - } - } - - .help-tab { - .support { - p, .email a { - font-size: 14px; - } - } - - .videos { - h4, p { - font-size: 14px; - } - } - } - - .inline-message, .notification-message { - border-radius: 0; - border: 0; - box-shadow: 0 1px 1px 0 rgba(0,0,0,.1); - padding: 10px 14px; - font-size: 13px; - } - - .notification-message { - margin-bottom: 20px; - background-color: #fff; - - p { - font-size: 13px; - margin-top: 0; - } - - p:last-child { - margin: 0; - } - - h4 { - margin-top: 0; - } - - a { - color: #0074a2; - text-decoration: none; - - &:hover { - color: #2ea2cc; - } - } - } - - .inline-message.error, .notification-message.error-notice { - border-left: 4px solid #dd3d36; - background-color: #fff; - } - - .inline-message.warning, .notification-message.warning-notice { - background-color: #fff; - border-left: 4px solid #ffba00; - } - - .inline-message.success, .notification-message.success-notice { - border-left: 4px solid #7ad03a; - } - - .ssl-notice { - margin-bottom: 0; - } - - .different-plugin-version-notice, .directory-permission-notice { - margin-bottom: 10px; - } - - } - - .progress-content { - font-size: 14px; - box-shadow: 0 0 10px rgba(0,0,0,0.5); - background-color: #eee; - - .progress-title { - font-family: 'Open Sans', sans-serif; - font-weight: normal; - font-size: 22px; - } - - .dashicons-yes { - font-size: 42px; - line-height: 0.5em; - } - - .progress-bar { - background-image: none; - background-color: #0074a2; - } - } - - #overlay { - background-color: rgba(0,0,0,0.5); - } - - .migration-progress-ajax-spinner { - top: 20px; - } -} diff --git a/asset/sass/styles.scss b/asset/sass/styles.scss deleted file mode 100755 index 678b4dc..0000000 --- a/asset/sass/styles.scss +++ /dev/null @@ -1,1167 +0,0 @@ -@import "compass"; - -#wpsdb-main { - width: 742px; -} - -#overlay { - background-color: rgba(255,255,255,0.9); -} - -.wpsdb{ - > div.updated.warning { - max-width: 742px; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - margin: 10px 0; - - p { - font-size: 13px; - } - } - - /* ============================================================================= - Common & Global - ========================================================================== */ - a { - text-decoration: none; - } - - li { - margin-bottom: 5px; - position: relative; - } - - ul { - margin: 0; - } - - input[type=checkbox], - input[type=radio]{ - margin-right: 5px; - vertical-align: baseline; - margin-top: 0; - } - - input[type=text], - input[type=password] { - padding: 5px; - } - - label.disabled { - color: #888; - cursor: default; - } - - .option-section { - border-bottom: 1px solid #ccc; - padding-bottom: 20px; - margin-bottom: 20px; - - h3 { - font-size: 18px; - font-weight: normal; - } - } - - p.migrate-db { - overflow: hidden; - - input { - float: left; - } - - img { - float: left; - margin: 3px 0 0 5px; - } - - .save-settings-button{ - margin-left: 10px; - display: none; - } - } - - .indent-wrap { - margin-left: 24px; - } - - .expandable-content{ - display: none; - margin-top: 10px; - } - - .expandable-content li:last-child{ - margin-bottom: 0px; - } - - .header-wrapper { - margin-bottom: 10px; - } - - .header-expand-collapse{ - cursor: pointer; - display: inline-block; - } - - .option-description{ - font-size: 12px; - color: #999; - margin-left: 8px; - font-weight: normal; - } - - .option-group li:last-child{ - margin-bottom: 0; - } - - .connection-status{ - display: none; - overflow: auto; - } - - .connection-status.error{ - color: #9D1818; - } - - .ajax-spinner{ - left: 6px; - position: relative; - top: 3px; - } - - div.message{ - margin: 15px 0 0; - } - - /* ============================================================================= - Migrate Tab - ========================================================================== */ - - /* Misc */ - - .return-to-profile-selection{ - margin-bottom: 15px; - display: inline-block; - } - - .return-to-profile-selection.bottom{ - margin-top: 10px; - } - - /* Tabs */ - - h2.nav-tab-wrapper { - margin-top: 10px; - margin-bottom: 20px; - padding-left: 5px; - - a { - margin-right: 4px; - } - - a.nav-tab-active { - color: #464646; - cursor: default; - } - } - - label { - display: inline-block; - clear: both; - } - - /* Saved migration profile selection */ - - .migration-profile-options li{ - position: relative; - width: 520px; - } - - .migration-profile-options li a{ - padding: 5px 10px; - width: 500px; - border: 1px solid #ddd; - margin: 0px 0px 7px; - display: block; - font-size: 14px; - color: #333; - } - - .migration-profile-options li a:hover{ - border-color: #bbb; - } - - .main-list-delete-profile-link{ - color: #999999; - font-family: "Times New Roman", serif; - font-size: 26px; - font-weight: 200; - position: absolute; - right: 7px; - top: 6px; - cursor: pointer; - } - - .main-list-delete-profile-link:hover{ - color: #444; - } - - /* Output Selection */ - - .option-group { - - li { - margin-bottom: 5px; - } - - > li { - margin-bottom: 8px; - } - - li > label { - font-size: 14px; - font-weight: bold; - } - - ul { - display: none; - margin: 10px 0px 10px 25px; - - label { - font-size: 12px; - font-weight: normal; - } - } - - } - - .import-file { - label { - margin-right: 1em; - } - - input { - - } - - .note { - display: block; - color: #999; - font-style: italic; - } - } - - .option-heading, .checkbox-label { - font-size: 14px; - font-weight: bold; - } - - .checkbox-label { - input[type=checkbox] { - margin-right: 7px; - position: relative; - top: -1px; - } - } - - .expand-collapse-arrow { - margin-right: 9px; - } - - .migrate-connection-info{ - min-width: 675px; - margin: 0; - } - - .migrate-tab .pull-push-connection-info { - width: 418px; - height: 65px; - color: #333; - font-family: Consolas, Monaco, monospace; - font-size: 15px; - line-height: 21px; - padding: 10px; - } - - .basic-access-auth-wrapper { - display: none; - margin-bottom: 5px; - } - - .auth-username, .auth-password { - width: 206px; - margin-top: 3px; - } - - .auth-password { - width: 207px; - } - - .connection-info-wrapper { - display: none; - width: 670px; - } - - .connect-button { - margin-top: 2px; - } - - .temp-disabled { - background-color: #EEEEEE; - color: #888888; - font-family: Consolas, Monaco, monospace; - text-shadow: 0 1px 0 #FFFFFF; - } - - .push-list ul{ - margin-bottom: 0px; - } - - /* Find and Replace */ - - .find-heading, .replace-heading { - float: left; - } - - .find-heading { - width: 400px; - } - - .replace-fields { - border-collapse: collapse; - border-spacing: 0px; - } - - .replace-fields input { - width: 295px; - } - - .replace-fields tr td{ - padding-bottom: 7px; - } - - .replace-fields tr:last-child td{ - padding-bottom: 0px; - } - - .arrow-col { - width: 93px; - text-align: center; - vertical-align: middle; - } - - .right-arrow { - font-size: 36px; - color: #aaa; - font-family: arial, sans-serif; - } - - .replace-right-col span { - border-radius: 50%; - border: 1px solid #ccc; - background-color: #eee; - width: 16px; - height: 16px; - display: inline-block; - position: relative; - top: 4px; - cursor: pointer; - } - - .replace-right-col span:hover { - border-color: #aaa; - } - - .replace-remove-row { - margin: 0px 2px; - } - - .replace-remove-row:after { - content: ''; - background-color: #aaa; - display: block; - height: 2px; - left: 5px; - position: absolute; - top: 7px; - width: 6px; - } - - .replace-add-row:after { - content: ''; - background-color: #aaa; - display: block; - height: 2px; - left: 5px; - position: absolute; - top: 7px; - width: 6px; - } - - .replace-add-row:before { - content: ''; - background-color: #aaa; - display: block; - height: 6px; - left: 7px; - position: absolute; - top: 5px; - width: 2px; - } - - .original-repeatable-field{ - display: none; - } - - .no-replaces-message{ - display: none; - margin-bottom: 0px; - } - - /* Select Tables */ - - .tables-header { - display: inline-block; - } - - .expand-collapse-arrow { - display: inline-block; - position: relative; - top: -2px; - font-size: 11px; - - } - - .collapsed { - -moz-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); - -webkit-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); - -o-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); - -ms-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); - transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); - } - - .select-deselect-divider { - margin: 0 6px; - } - - .select-wrap{ - display: none; - margin-top: 12px; - } - - .multiselect { - min-width: 420px; - min-height: 180px; - margin-bottom: 10px; - } - - .table-migrate-options li label{ - font-size: 12px; - font-weight: normal; - } - - .table-migrate-options li{ - margin-bottom: 5px; - } - - /* Advanced Options */ - - .general-helper { - border-radius: 50%; - border: 1px solid #ccc; - background-color: #eee; - width: 15px; - height: 15px; - display: inline-block; - position: relative; - top: 4px; - margin-top: -4px; - cursor: pointer; - margin-left: 2px; - } - - .general-helper:hover { - border-color: #aaa; - } - - .general-helper:after { - content: "?"; - color: #999999; - font-size: 10px; - font-weight: bold; - left: 4px; - position: absolute; - top: -1px; - } - - .helper-message { - padding: 10px; - border: 1px solid #ccc; - border-radius: 3px; - background-color: #fff; - position: absolute; - width: 500px; - z-index: 100; - display: none; - box-shadow: 0px 0px 5px #ccc; - } - - .inline-message { - padding: 10px; - border-radius: 3px; - margin-top: 5px; - } - - .inline-message.error { - border: 1px solid #CC0000; - background-color: #FFEBE8; - } - - .inline-message.warning { - background-color: #FFFFE0; - border: 1px solid #E6DB55; - } - - .helper-message:after { - content: ''; - border-bottom: 7px solid transparent; - border-right: 7px solid #fff; - border-top: 7px solid transparent; - display: block; - height: 0; - left: -7px; - position: absolute; - top: 11px; - width: 0; - } - - .helper-message:before { - content: ''; - border-bottom: 7px solid transparent; - border-right: 7px solid #aaa; - border-top: 7px solid transparent; - display: block; - height: 0; - left: -8px; - position: absolute; - top: 11px; - width: 0; - } - - .label-disabled { - color: #888; - } - - .prefix-notice, .ssl-notice, .different-plugin-version-notice, .directory-permission-notice { - background-color: #FFFFE0; - border: 1px solid #E6DB55; - padding: 15px; - border-radius: 3px; - margin-bottom: 15px; - display: none; - p{ - margin-top: 0px; - } - p:last-child { - margin: 0px; - } - } - - .different-plugin-version-notice, .directory-permission-notice { - background-color: #FFEBE8; - border-color: #CC0000; - a { - color: #CC0000; - text-decoration: underline; - } - } - - .ssl-notice { - margin-bottom: 0; - margin-top: 15px; - } - - /* Save migration profile */ - - .save-migration-profile-wrap { - - li label{ - font-size: 12px; - font-weight: normal; - } - - li{ - margin-bottom: 5px; - padding-left: 25px; - } - - } - - .save-migration-profile-wrap .indent-wrap { - margin-left: 0px; - } - - .create-new-label { - margin-right: 8px; - } - - .create-new-profile { - position: absolute; - top: -5px; - } - - .delete-profile { - background-color: #eee; - border: 1px solid #ccc; - border-radius: 50% 50% 50% 50%; - cursor: pointer; - height: 11px; - left: 5px; - margin-left: 2px; - position: absolute; - margin-top: -6px; - top: 50%; - width: 11px; - display: none; - background-position: 50% 50%; - background-size: 6px 6px; - background-repeat: no-repeat; - } - - .delete-profile:after { - content:"\00d7"; - left: 2px; - position: absolute; - top: -3px; - color: #aaa; - font-size: 12px; - } - - .delete-profile:hover { - border-color: #aaa; - } - - /* Action buttons */ - - .migrate-db .ajax-success-msg { - font-weight: bold; - margin: 3px 0 0 9px; - display: inline-block; - } - - p img.save-profile-ajax-spinner { - margin-left: 10px; - } - - .backup-description { - left: 20px; - position: relative; - } - .backup-option-disabled { - margin-bottom: 0px; - } - - /* Import DB */ - .import-button { - display: none; - } - - /* ============================================================================= - Settings Tab - ========================================================================== */ - - .settings-tab{ - display: none; - - .slider { - max-width: 416px; - } - - .slider-label { - display: block; - margin-bottom: 10px; - float: left; - width: 50%; - } - - .slider-label-wrapper { - max-width: 416px; - width: 100%; - position: relative; - } - - .amount { - width: 50%; - text-align: right; - display: block; - text-align: right; - float: left; - } - - .slider-spinner { - position: absolute; - right: -35px; - bottom: -13px; - } - - .slider-success-msg { - display: none; - right: -53px; - bottom: -13px; - position: absolute; - font-weight: bold; - } - - .ui-slider { - border: 1px solid #dfdfdf; - height: 10px; - border-radius: 2px; - position: relative; - } - - .ui-slider-handle { - width: 7px; - height: 20px; - background-color: #aaa; - display: block; - position: absolute; - top: -5px; - outline: none; - } - - .ui-slider-handle:active { - background-color: #999; - } - - .ui-slider-range { - background-color: #eee; - height: 100%; - } - - .option-section{ - - li label{ - font-size: 12px; - font-weight: normal; - position: relative; - } - - li{ - margin-bottom: 5px; - } - - li:last-child{ - margin-bottom: 0px; - } - - .ajax-spinner{ - right: -23px; - left: inherit; - top: 0px; - position: absolute; - } - - .ajax-success-msg{ - right: -42px; - left: inherit; - top: 0px; - position: absolute; - font-weight: bold; - } - - .verify-ssl .ajax-spinner { - right: -45px; - } - - .verify-ssl .ajax-success-msg { - right: -65px; - } - - } - } - - .allow-remote-reqeusts { - font-size: 14px; - font-weight: bold; - } - - .connection-info-label{ - margin-top: 15px; - margin-bottom: 5px; - display: block; - } - - .connection-info{ - clear: both; - font-size: 15px; - line-height: 21px; - font-family: Consolas, Monaco, monospace; - padding: 10px 10px; - height: 67px; - text-shadow: 0px 1px 0px #fff; - display: block; - margin-bottom: 7px; - width: 418px; - } - - .reset-button-wrap{ - width: 418px; - } - - .reset-api-key{ - float: left; - } - - .reset-api-key-ajax-spinner{ - float: left; - margin: 4px 7px; - } - - /* ============================================================================= - Help Tab - ========================================================================== */ - - .help-tab { - display: none; - - h3 { - font-size: 18px; - font-weight: normal; - } - - .support { - border-bottom: 1px solid #ccc; - margin-bottom: 25px; - padding-bottom: 18px; - - h3 { - - } - - p { - width: 640px; - } - - .email { - a { - font-size: 12px; - } - } - - .ajax-spinner { - top: 2px; - } - } - - .video-viewer { - margin-bottom: 30px; - } - - .videos { - width: 640px; - - ul > li { - margin-bottom: 30px; - overflow: hidden; - position: relative; - - a { - overflow: hidden; - display: block; - width: 320px; - height: 180px; - float: left; - margin-right: 15px; - position: relative; - z-index: 1; - } - - $size: 64px; - - a:before, a:after { - position: absolute; - content: " "; - margin: auto; - left: 0; - right: 0; - top: 0; - bottom: 0; - } - - a:before { - width: $size; - height: $size; - @include border-radius($size); - @include opacity(0.8); - border: 1px solid #ddd; - background-color: #fff; - z-index: 2; - } - - a:after { - @include opacity(0.8); - border: $size/3 solid transparent; - border-top-width: $size/5; - border-bottom-width: $size/5; - border-left-color: #333; - background: transparent; - display: block; - left: 25px; - width: 0px; - height: 0px; - z-index: 3; - } - } - - .video:last-child { - margin-bottom: 0px; - } - - img { - width: 320px; - height: 240px; - position: relative; - top: 50%; - margin-top: -120px; - } - - } - - .debug { - width: 640px; - border-bottom: 1px solid #CCCCCC; - margin-bottom: 25px; - padding-bottom: 28px; - - textarea{ - width: 100%; - min-height: 200px; - font-family: Consolas, Monaco, monospace; - margin-bottom: 5px; - } - } - - h4 { - margin: 0 0 0.2em 0; - } - - p { - margin: 0 0 0.5em 0; - } - - iframe { - display: none; - } - - } -} - -/* Progress Information */ - -/* Contain floats: h5bp.com/q */ -.clearfix:before, .clearfix:after { content: ""; display: table; } -.clearfix:after { clear: both; } -.clearfix { zoom: 1; } - -.general-spinner{ - width: 16px; - height: 16px; -} - -.migration-error { - color: #A21B1B; - display: block; - font-weight: bold; - max-height: 400px; - max-width: 100%; - overflow: scroll; - word-wrap: break-word; -} - -.progress-content{ - display: none; - position: relative; - margin: 0 auto; - background-color: #fff; - padding: 50px; - box-shadow: 0 0 10px #ccc; - cursor: default; - width: 80%; - z-index: 99999; - position: fixed; - left: 50%; - margin-left: -40%; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - - .progress-bar { - height: 10px; - background-color: #8cc1e9; - margin-bottom: 5px; - @include background-image(linear-gradient(bottom, #72a7cf, #8cc1e9)); - } - - .progress-title { - font-size: 18px; - font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", sans-serif; - font-weight: normal; - float: left; - } - - .progress-bar { - width: 0%; - } - - .progress-info-wrapper { - margin-bottom: 10px; - } - - .progress-text { - clear: left; - float: left; - width: 100%; - } - - .timer { - float: right; - } - - .progress-tables { - overflow: hidden; - margin-bottom: 2px; - padding: 0 0 20px 0; - } - - .progress-bar-wrapper { - position: relative; - } - - .progress-bar-wrapper:before{ - content: ''; - display: block; - height: 5px; - width: 1px; - background-color: #ccc; - position: absolute; - top: 15px; - left: 0px; - } - - .progress-tables-hover-boxes { - position: absolute; - top: 0px; - left: 0px; - display: block; - width: 100%; - } - - .progress-chunk-hover { - display: block; - float: left; - height: 35px; - position: relative; - top: -5px; - z-index: 1; - } - - .progress-chunk { - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - float: left; - display: block; - height: 6px; - border-right: 1px solid #ccc; - border-bottom: 1px solid #ccc; - color: #999; - position: relative; - text-align: center; - - > span { - padding: 0px 3px; - white-space: nowrap; - text-overflow: ellipsis; - margin-top: 10px; - display: inline-block; - } - } - - .progress-label { - padding: 5px 10px; - border: 1px solid #ccc; - border-radius: 3px; - background-color: #fff; - font-family: Consolas, Monaco, monospace; - font-size: 12px; - display: inline-block; - top: -35px; - position: absolute; - opacity: 0; - -webkit-transition: opacity 200ms ease-in-out; - -moz-transition: opacity 200ms ease-in-out; - -ms-transition: opacity 200ms ease-in-out; - -o-transition: opacity 200ms ease-in-out; - transition: opacity 200ms ease-in-out; - } - - .label-visible { - opacity: 1; - } - - .progress-label:before { - content: ""; - width: 0; - height: 0; - border-left: 4px solid transparent; - border-right: 4px solid transparent; - border-top: 4px solid #ccc; - display: block; - position: absolute; - bottom: -5px; - left: 50%; - margin-left: -2px; - } - - .progress-label:after { - content: ""; - width: 0; - height: 0; - border-left: 4px solid transparent; - border-right: 4px solid transparent; - border-top: 4px solid #fff; - display: block; - position: absolute; - bottom: -4px; - left: 50%; - margin-left: -2px; - } - - .migration-progress-ajax-spinner { - left: 7px; - position: relative; - top: 15px; - } - - .close-progress-content { - color: #999999; - cursor: pointer; - font-family: "Times New Roman",serif; - font-size: 26px; - font-weight: 200; - position: absolute; - right: 20px; - top: 20px; - padding: 5px; - display: none; - } - - .close-progress-content:hover { - color: #666; - border-color: #aaa; - } -} - -@import "mp6"; From 596a236c7fc979ed429ce52c29e16dd63a62143a Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Fri, 20 Jun 2014 23:34:17 -0400 Subject: [PATCH 26/52] reformat CSS --- asset/css/styles.css | 1905 ++++++++++++++++++++++++------------------ 1 file changed, 1073 insertions(+), 832 deletions(-) diff --git a/asset/css/styles.css b/asset/css/styles.css index fa96c64..d110e7f 100755 --- a/asset/css/styles.css +++ b/asset/css/styles.css @@ -1,637 +1,795 @@ #wpsdb-main { - width: 742px; } + width: 742px; +} #overlay { - background-color: rgba(255, 255, 255, 0.9); } + background-color: rgba(255, 255, 255, 0.9); +} .wpsdb { - /* ============================================================================= - Common & Global - ========================================================================== */ - /* ============================================================================= - Migrate Tab - ========================================================================== */ - /* Misc */ - /* Tabs */ - /* Saved migration profile selection */ - /* Output Selection */ - /* Find and Replace */ - /* Select Tables */ - /* Advanced Options */ - /* Save migration profile */ - /* Action buttons */ - /* Import DB */ - /* ============================================================================= - Settings Tab - ========================================================================== */ - /* ============================================================================= - Help Tab - ========================================================================== */ } - .wpsdb > div.updated.warning { - max-width: 742px; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - margin: 10px 0; } - .wpsdb > div.updated.warning p { - font-size: 13px; } - .wpsdb a { - text-decoration: none; } - .wpsdb li { - margin-bottom: 5px; - position: relative; } - .wpsdb ul { - margin: 0; } - .wpsdb input[type=checkbox], - .wpsdb input[type=radio] { - margin-right: 5px; - vertical-align: baseline; - margin-top: 0; } - .wpsdb input[type=text], - .wpsdb input[type=password] { - padding: 5px; } - .wpsdb label.disabled { - color: #888; - cursor: default; } - .wpsdb .option-section { - border-bottom: 1px solid #ccc; - padding-bottom: 20px; - margin-bottom: 20px; } - .wpsdb .option-section h3 { - font-size: 18px; - font-weight: normal; } - .wpsdb p.migrate-db { - overflow: hidden; } - .wpsdb p.migrate-db input { - float: left; } - .wpsdb p.migrate-db img { - float: left; - margin: 3px 0 0 5px; } - .wpsdb p.migrate-db .save-settings-button { - margin-left: 10px; - display: none; } - .wpsdb .indent-wrap { - margin-left: 24px; } - .wpsdb .expandable-content { - display: none; - margin-top: 10px; } - .wpsdb .expandable-content li:last-child { - margin-bottom: 0px; } - .wpsdb .header-wrapper { - margin-bottom: 10px; } - .wpsdb .header-expand-collapse { - cursor: pointer; - display: inline-block; } - .wpsdb .option-description { - font-size: 12px; - color: #999; - margin-left: 8px; - font-weight: normal; } - .wpsdb .option-group li:last-child { - margin-bottom: 0; } - .wpsdb .connection-status { - display: none; - overflow: auto; } - .wpsdb .connection-status.error { - color: #9D1818; } - .wpsdb .ajax-spinner { - left: 6px; - position: relative; - top: 3px; } - .wpsdb div.message { - margin: 15px 0 0; } - .wpsdb .return-to-profile-selection { - margin-bottom: 15px; - display: inline-block; } - .wpsdb .return-to-profile-selection.bottom { - margin-top: 10px; } - .wpsdb h2.nav-tab-wrapper { - margin-top: 10px; - margin-bottom: 20px; - padding-left: 5px; } - .wpsdb h2.nav-tab-wrapper a { - margin-right: 4px; } - .wpsdb h2.nav-tab-wrapper a.nav-tab-active { - color: #464646; - cursor: default; } - .wpsdb label { - display: inline-block; - clear: both; } - .wpsdb .migration-profile-options li { - position: relative; - width: 520px; } - .wpsdb .migration-profile-options li a { - padding: 5px 10px; - width: 500px; - border: 1px solid #ddd; - margin: 0px 0px 7px; - display: block; - font-size: 14px; - color: #333; } - .wpsdb .migration-profile-options li a:hover { - border-color: #bbb; } - .wpsdb .main-list-delete-profile-link { - color: #999999; - font-family: "Times New Roman", serif; - font-size: 26px; - font-weight: 200; - position: absolute; - right: 7px; - top: 6px; - cursor: pointer; } - .wpsdb .main-list-delete-profile-link:hover { - color: #444; } - .wpsdb .option-group li { - margin-bottom: 5px; } - .wpsdb .option-group > li { - margin-bottom: 8px; } - .wpsdb .option-group li > label { - font-size: 14px; - font-weight: bold; } - .wpsdb .option-group ul { - display: none; - margin: 10px 0px 10px 25px; } - .wpsdb .option-group ul label { - font-size: 12px; - font-weight: normal; } - .wpsdb .import-file label { - margin-right: 1em; } - .wpsdb .import-file .note { - display: block; - color: #999; - font-style: italic; } - .wpsdb .option-heading, .wpsdb .checkbox-label { - font-size: 14px; - font-weight: bold; } - .wpsdb .checkbox-label input[type=checkbox] { - margin-right: 7px; - position: relative; - top: -1px; } - .wpsdb .expand-collapse-arrow { - margin-right: 9px; } - .wpsdb .migrate-connection-info { - min-width: 675px; - margin: 0; } - .wpsdb .migrate-tab .pull-push-connection-info { - width: 418px; - height: 65px; - color: #333; - font-family: Consolas, Monaco, monospace; - font-size: 15px; - line-height: 21px; - padding: 10px; } - .wpsdb .basic-access-auth-wrapper { - display: none; - margin-bottom: 5px; } - .wpsdb .auth-username, .wpsdb .auth-password { - width: 206px; - margin-top: 3px; } - .wpsdb .auth-password { - width: 207px; } - .wpsdb .connection-info-wrapper { - display: none; - width: 670px; } - .wpsdb .connect-button { - margin-top: 2px; } - .wpsdb .temp-disabled { - background-color: #EEEEEE; - color: #888888; - font-family: Consolas, Monaco, monospace; - text-shadow: 0 1px 0 #FFFFFF; } - .wpsdb .push-list ul { - margin-bottom: 0px; } - .wpsdb .find-heading, .wpsdb .replace-heading { - float: left; } - .wpsdb .find-heading { - width: 400px; } - .wpsdb .replace-fields { - border-collapse: collapse; - border-spacing: 0px; } - .wpsdb .replace-fields input { - width: 295px; } - .wpsdb .replace-fields tr td { - padding-bottom: 7px; } - .wpsdb .replace-fields tr:last-child td { - padding-bottom: 0px; } - .wpsdb .arrow-col { - width: 93px; - text-align: center; - vertical-align: middle; } - .wpsdb .right-arrow { - font-size: 36px; - color: #aaa; - font-family: arial, sans-serif; } - .wpsdb .replace-right-col span { - border-radius: 50%; - border: 1px solid #ccc; - background-color: #eee; - width: 16px; - height: 16px; - display: inline-block; - position: relative; - top: 4px; - cursor: pointer; } - .wpsdb .replace-right-col span:hover { - border-color: #aaa; } - .wpsdb .replace-remove-row { - margin: 0px 2px; } - .wpsdb .replace-remove-row:after { - content: ''; - background-color: #aaa; - display: block; - height: 2px; - left: 5px; - position: absolute; - top: 7px; - width: 6px; } - .wpsdb .replace-add-row:after { - content: ''; - background-color: #aaa; - display: block; - height: 2px; - left: 5px; - position: absolute; - top: 7px; - width: 6px; } - .wpsdb .replace-add-row:before { - content: ''; - background-color: #aaa; - display: block; - height: 6px; - left: 7px; - position: absolute; - top: 5px; - width: 2px; } - .wpsdb .original-repeatable-field { - display: none; } - .wpsdb .no-replaces-message { - display: none; - margin-bottom: 0px; } - .wpsdb .tables-header { - display: inline-block; } - .wpsdb .expand-collapse-arrow { - display: inline-block; - position: relative; - top: -2px; - font-size: 11px; } - .wpsdb .collapsed { - -moz-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); - -webkit-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); - -o-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); - -ms-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); - transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); } - .wpsdb .select-deselect-divider { - margin: 0 6px; } - .wpsdb .select-wrap { - display: none; - margin-top: 12px; } - .wpsdb .multiselect { - min-width: 420px; - min-height: 180px; - margin-bottom: 10px; } - .wpsdb .table-migrate-options li label { - font-size: 12px; - font-weight: normal; } - .wpsdb .table-migrate-options li { - margin-bottom: 5px; } - .wpsdb .general-helper { - border-radius: 50%; - border: 1px solid #ccc; - background-color: #eee; - width: 15px; - height: 15px; - display: inline-block; - position: relative; - top: 4px; - margin-top: -4px; - cursor: pointer; - margin-left: 2px; } - .wpsdb .general-helper:hover { - border-color: #aaa; } - .wpsdb .general-helper:after { - content: "?"; - color: #999999; - font-size: 10px; - font-weight: bold; - left: 4px; - position: absolute; - top: -1px; } - .wpsdb .helper-message { - padding: 10px; - border: 1px solid #ccc; - border-radius: 3px; - background-color: #fff; - position: absolute; - width: 500px; - z-index: 100; - display: none; - box-shadow: 0px 0px 5px #ccc; } - .wpsdb .inline-message { - padding: 10px; - border-radius: 3px; - margin-top: 5px; } - .wpsdb .inline-message.error { - border: 1px solid #CC0000; - background-color: #FFEBE8; } - .wpsdb .inline-message.warning { - background-color: #FFFFE0; - border: 1px solid #E6DB55; } - .wpsdb .helper-message:after { - content: ''; - border-bottom: 7px solid transparent; - border-right: 7px solid #fff; - border-top: 7px solid transparent; - display: block; - height: 0; - left: -7px; - position: absolute; - top: 11px; - width: 0; } - .wpsdb .helper-message:before { - content: ''; - border-bottom: 7px solid transparent; - border-right: 7px solid #aaa; - border-top: 7px solid transparent; - display: block; - height: 0; - left: -8px; - position: absolute; - top: 11px; - width: 0; } - .wpsdb .label-disabled { - color: #888; } - .wpsdb .prefix-notice, .wpsdb .ssl-notice, .wpsdb .different-plugin-version-notice, .wpsdb .directory-permission-notice { - background-color: #FFFFE0; - border: 1px solid #E6DB55; - padding: 15px; - border-radius: 3px; - margin-bottom: 15px; - display: none; } - .wpsdb .prefix-notice p, .wpsdb .ssl-notice p, .wpsdb .different-plugin-version-notice p, .wpsdb .directory-permission-notice p { - margin-top: 0px; } - .wpsdb .prefix-notice p:last-child, .wpsdb .ssl-notice p:last-child, .wpsdb .different-plugin-version-notice p:last-child, .wpsdb .directory-permission-notice p:last-child { - margin: 0px; } - .wpsdb .different-plugin-version-notice, .wpsdb .directory-permission-notice { - background-color: #FFEBE8; - border-color: #CC0000; } - .wpsdb .different-plugin-version-notice a, .wpsdb .directory-permission-notice a { - color: #CC0000; - text-decoration: underline; } - .wpsdb .ssl-notice { - margin-bottom: 0; - margin-top: 15px; } - .wpsdb .save-migration-profile-wrap li label { - font-size: 12px; - font-weight: normal; } - .wpsdb .save-migration-profile-wrap li { - margin-bottom: 5px; - padding-left: 25px; } - .wpsdb .save-migration-profile-wrap .indent-wrap { - margin-left: 0px; } - .wpsdb .create-new-label { - margin-right: 8px; } - .wpsdb .create-new-profile { - position: absolute; - top: -5px; } - .wpsdb .delete-profile { - background-color: #eee; - border: 1px solid #ccc; - border-radius: 50% 50% 50% 50%; - cursor: pointer; - height: 11px; - left: 5px; - margin-left: 2px; - position: absolute; - margin-top: -6px; - top: 50%; - width: 11px; - display: none; - background-position: 50% 50%; - background-size: 6px 6px; - background-repeat: no-repeat; } - .wpsdb .delete-profile:after { - content: "\00d7"; - left: 2px; - position: absolute; - top: -3px; - color: #aaa; - font-size: 12px; } - .wpsdb .delete-profile:hover { - border-color: #aaa; } - .wpsdb .migrate-db .ajax-success-msg { - font-weight: bold; - margin: 3px 0 0 9px; - display: inline-block; } - .wpsdb p img.save-profile-ajax-spinner { - margin-left: 10px; } - .wpsdb .backup-description { - left: 20px; - position: relative; } - .wpsdb .backup-option-disabled { - margin-bottom: 0px; } - .wpsdb .import-button { - display: none; } - .wpsdb .settings-tab { - display: none; } - .wpsdb .settings-tab .slider { - max-width: 416px; } - .wpsdb .settings-tab .slider-label { - display: block; - margin-bottom: 10px; - float: left; - width: 50%; } - .wpsdb .settings-tab .slider-label-wrapper { - max-width: 416px; - width: 100%; - position: relative; } - .wpsdb .settings-tab .amount { - width: 50%; - text-align: right; - display: block; - text-align: right; - float: left; } - .wpsdb .settings-tab .slider-spinner { - position: absolute; - right: -35px; - bottom: -13px; } - .wpsdb .settings-tab .slider-success-msg { - display: none; - right: -53px; - bottom: -13px; - position: absolute; - font-weight: bold; } - .wpsdb .settings-tab .ui-slider { - border: 1px solid #dfdfdf; - height: 10px; - border-radius: 2px; - position: relative; } - .wpsdb .settings-tab .ui-slider-handle { - width: 7px; - height: 20px; - background-color: #aaa; - display: block; - position: absolute; - top: -5px; - outline: none; } - .wpsdb .settings-tab .ui-slider-handle:active { - background-color: #999; } - .wpsdb .settings-tab .ui-slider-range { - background-color: #eee; - height: 100%; } - .wpsdb .settings-tab .option-section li label { - font-size: 12px; - font-weight: normal; - position: relative; } - .wpsdb .settings-tab .option-section li { - margin-bottom: 5px; } - .wpsdb .settings-tab .option-section li:last-child { - margin-bottom: 0px; } - .wpsdb .settings-tab .option-section .ajax-spinner { - right: -23px; - left: inherit; - top: 0px; - position: absolute; } - .wpsdb .settings-tab .option-section .ajax-success-msg { - right: -42px; - left: inherit; - top: 0px; - position: absolute; - font-weight: bold; } - .wpsdb .settings-tab .option-section .verify-ssl .ajax-spinner { - right: -45px; } - .wpsdb .settings-tab .option-section .verify-ssl .ajax-success-msg { - right: -65px; } - .wpsdb .allow-remote-reqeusts { - font-size: 14px; - font-weight: bold; } - .wpsdb .connection-info-label { - margin-top: 15px; - margin-bottom: 5px; - display: block; } - .wpsdb .connection-info { - clear: both; - font-size: 15px; - line-height: 21px; - font-family: Consolas, Monaco, monospace; - padding: 10px 10px; - height: 67px; - text-shadow: 0px 1px 0px #fff; - display: block; - margin-bottom: 7px; - width: 418px; } - .wpsdb .reset-button-wrap { - width: 418px; } - .wpsdb .reset-api-key { - float: left; } - .wpsdb .reset-api-key-ajax-spinner { - float: left; - margin: 4px 7px; } - .wpsdb .help-tab { - display: none; } - .wpsdb .help-tab h3 { - font-size: 18px; - font-weight: normal; } - .wpsdb .help-tab .support { - border-bottom: 1px solid #ccc; - margin-bottom: 25px; - padding-bottom: 18px; } - .wpsdb .help-tab .support p { - width: 640px; } - .wpsdb .help-tab .support .email a { - font-size: 12px; } - .wpsdb .help-tab .support .ajax-spinner { - top: 2px; } - .wpsdb .help-tab .video-viewer { - margin-bottom: 30px; } - .wpsdb .help-tab .videos { - width: 640px; } - .wpsdb .help-tab .videos ul > li { - margin-bottom: 30px; - overflow: hidden; - position: relative; } - .wpsdb .help-tab .videos ul > li a { - overflow: hidden; - display: block; - width: 320px; - height: 180px; - float: left; - margin-right: 15px; - position: relative; - z-index: 1; } - .wpsdb .help-tab .videos ul > li a:before, .wpsdb .help-tab .videos ul > li a:after { - position: absolute; - content: " "; - margin: auto; - left: 0; - right: 0; - top: 0; - bottom: 0; } - .wpsdb .help-tab .videos ul > li a:before { - width: 64px; - height: 64px; - -webkit-border-radius: 64px; - -moz-border-radius: 64px; - -ms-border-radius: 64px; - -o-border-radius: 64px; - border-radius: 64px; - filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); - opacity: 0.8; - border: 1px solid #ddd; - background-color: #fff; - z-index: 2; } - .wpsdb .help-tab .videos ul > li a:after { - filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); - opacity: 0.8; - border: 21.33333px solid transparent; - border-top-width: 12.8px; - border-bottom-width: 12.8px; - border-left-color: #333; - background: transparent; - display: block; - left: 25px; - width: 0px; - height: 0px; - z-index: 3; } - .wpsdb .help-tab .videos .video:last-child { - margin-bottom: 0px; } - .wpsdb .help-tab .videos img { - width: 320px; - height: 240px; - position: relative; - top: 50%; - margin-top: -120px; } - .wpsdb .help-tab .debug { - width: 640px; - border-bottom: 1px solid #CCCCCC; - margin-bottom: 25px; - padding-bottom: 28px; } - .wpsdb .help-tab .debug textarea { - width: 100%; - min-height: 200px; - font-family: Consolas, Monaco, monospace; - margin-bottom: 5px; } - .wpsdb .help-tab h4 { - margin: 0 0 0.2em 0; } - .wpsdb .help-tab p { - margin: 0 0 0.5em 0; } - .wpsdb .help-tab iframe { - display: none; } +/* ============================================================================= + Common & Global + ========================================================================== */ +/* ============================================================================= + Migrate Tab + ========================================================================== */ +/* Misc */ +/* Tabs */ +/* Saved migration profile selection */ +/* Output Selection */ +/* Find and Replace */ +/* Select Tables */ +/* Advanced Options */ +/* Save migration profile */ +/* Action buttons */ +/* Import DB */ +/* ============================================================================= + Settings Tab + ========================================================================== */ +/* ============================================================================= + Help Tab + ========================================================================== */ } +.wpsdb > div.updated.warning { + max-width: 742px; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + margin: 10px 0; +} +.wpsdb > div.updated.warning p { + font-size: 13px; +} +.wpsdb a { + text-decoration: none; +} +.wpsdb li { + margin-bottom: 5px; + position: relative; +} +.wpsdb ul { + margin: 0; +} +.wpsdb input[type=checkbox], +.wpsdb input[type=radio] { + margin-right: 5px; + vertical-align: baseline; + margin-top: 0; +} +.wpsdb input[type=text], +.wpsdb input[type=password] { + padding: 5px; +} +.wpsdb label.disabled { + color: #888; + cursor: default; +} +.wpsdb .option-section { + border-bottom: 1px solid #ccc; + padding-bottom: 20px; + margin-bottom: 20px; +} +.wpsdb .option-section h3 { + font-size: 18px; + font-weight: normal; +} +.wpsdb p.migrate-db { + overflow: hidden; +} +.wpsdb p.migrate-db input { + float: left; +} +.wpsdb p.migrate-db img { + float: left; + margin: 3px 0 0 5px; +} +.wpsdb p.migrate-db .save-settings-button { + margin-left: 10px; + display: none; +} +.wpsdb .indent-wrap { + margin-left: 24px; +} +.wpsdb .expandable-content { + display: none; + margin-top: 10px; +} +.wpsdb .expandable-content li:last-child { + margin-bottom: 0px; +} +.wpsdb .header-wrapper { + margin-bottom: 10px; +} +.wpsdb .header-expand-collapse { + cursor: pointer; + display: inline-block; +} +.wpsdb .option-description { + font-size: 12px; + color: #999; + margin-left: 8px; + font-weight: normal; +} +.wpsdb .option-group li:last-child { + margin-bottom: 0; +} +.wpsdb .connection-status { + display: none; + overflow: auto; +} +.wpsdb .connection-status.error { + color: #9D1818; +} +.wpsdb .ajax-spinner { + left: 6px; + position: relative; + top: 3px; +} +.wpsdb div.message { + margin: 15px 0 0; +} +.wpsdb .return-to-profile-selection { + margin-bottom: 15px; + display: inline-block; +} +.wpsdb .return-to-profile-selection.bottom { + margin-top: 10px; +} +.wpsdb h2.nav-tab-wrapper { + margin-top: 10px; + margin-bottom: 20px; + padding-left: 5px; +} +.wpsdb h2.nav-tab-wrapper a { + margin-right: 4px; +} +.wpsdb h2.nav-tab-wrapper a.nav-tab-active { + color: #464646; + cursor: default; +} +.wpsdb label { + display: inline-block; + clear: both; +} +.wpsdb .migration-profile-options li { + position: relative; + width: 520px; +} +.wpsdb .migration-profile-options li a { + padding: 5px 10px; + width: 500px; + border: 1px solid #ddd; + margin: 0px 0px 7px; + display: block; + font-size: 14px; + color: #333; +} +.wpsdb .migration-profile-options li a:hover { + border-color: #bbb; +} +.wpsdb .main-list-delete-profile-link { + color: #999999; + font-family: "Times New Roman", serif; + font-size: 26px; + font-weight: 200; + position: absolute; + right: 7px; + top: 6px; + cursor: pointer; +} +.wpsdb .main-list-delete-profile-link:hover { + color: #444; +} +.wpsdb .option-group li { + margin-bottom: 5px; +} +.wpsdb .option-group > li { + margin-bottom: 8px; +} +.wpsdb .option-group li > label { + font-size: 14px; + font-weight: bold; +} +.wpsdb .option-group ul { + display: none; + margin: 10px 0px 10px 25px; +} +.wpsdb .option-group ul label { + font-size: 12px; + font-weight: normal; +} +.wpsdb .import-file label { + margin-right: 1em; +} +.wpsdb .import-file .note { + display: block; + color: #999; + font-style: italic; +} +.wpsdb .option-heading, .wpsdb .checkbox-label { + font-size: 14px; + font-weight: bold; +} +.wpsdb .checkbox-label input[type=checkbox] { + margin-right: 7px; + position: relative; + top: -1px; +} +.wpsdb .expand-collapse-arrow { + margin-right: 9px; +} +.wpsdb .migrate-connection-info { + min-width: 675px; + margin: 0; +} +.wpsdb .migrate-tab .pull-push-connection-info { + width: 418px; + height: 65px; + color: #333; + font-family: Consolas, Monaco, monospace; + font-size: 15px; + line-height: 21px; + padding: 10px; +} +.wpsdb .basic-access-auth-wrapper { + display: none; + margin-bottom: 5px; +} +.wpsdb .auth-username, .wpsdb .auth-password { + width: 206px; + margin-top: 3px; +} +.wpsdb .auth-password { + width: 207px; +} +.wpsdb .connection-info-wrapper { + display: none; + width: 670px; +} +.wpsdb .connect-button { + margin-top: 2px; +} +.wpsdb .temp-disabled { + background-color: #EEEEEE; + color: #888888; + font-family: Consolas, Monaco, monospace; + text-shadow: 0 1px 0 #FFFFFF; +} +.wpsdb .push-list ul { + margin-bottom: 0px; +} +.wpsdb .find-heading, .wpsdb .replace-heading { + float: left; +} +.wpsdb .find-heading { + width: 400px; +} +.wpsdb .replace-fields { + border-collapse: collapse; + border-spacing: 0px; +} +.wpsdb .replace-fields input { + width: 295px; +} +.wpsdb .replace-fields tr td { + padding-bottom: 7px; +} +.wpsdb .replace-fields tr:last-child td { + padding-bottom: 0px; +} +.wpsdb .arrow-col { + width: 93px; + text-align: center; + vertical-align: middle; +} +.wpsdb .right-arrow { + font-size: 36px; + color: #aaa; + font-family: arial, sans-serif; +} +.wpsdb .replace-right-col span { + border-radius: 50%; + border: 1px solid #ccc; + background-color: #eee; + width: 16px; + height: 16px; + display: inline-block; + position: relative; + top: 4px; + cursor: pointer; +} +.wpsdb .replace-right-col span:hover { + border-color: #aaa; +} +.wpsdb .replace-remove-row { + margin: 0px 2px; +} +.wpsdb .replace-remove-row:after { + content: ''; + background-color: #aaa; + display: block; + height: 2px; + left: 5px; + position: absolute; + top: 7px; + width: 6px; +} +.wpsdb .replace-add-row:after { + content: ''; + background-color: #aaa; + display: block; + height: 2px; + left: 5px; + position: absolute; + top: 7px; + width: 6px; +} +.wpsdb .replace-add-row:before { + content: ''; + background-color: #aaa; + display: block; + height: 6px; + left: 7px; + position: absolute; + top: 5px; + width: 2px; +} +.wpsdb .original-repeatable-field { + display: none; +} +.wpsdb .no-replaces-message { + display: none; + margin-bottom: 0px; +} +.wpsdb .tables-header { + display: inline-block; +} +.wpsdb .expand-collapse-arrow { + display: inline-block; + position: relative; + top: -2px; + font-size: 11px; +} +.wpsdb .collapsed { + -moz-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); + -webkit-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); + -o-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); + -ms-transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); + transform: scale(1) rotate(-90deg) translateX(0px) translateY(0px) skewX(0deg) skewY(0deg); +} +.wpsdb .select-deselect-divider { + margin: 0 6px; +} +.wpsdb .select-wrap { + display: none; + margin-top: 12px; +} +.wpsdb .multiselect { + min-width: 420px; + min-height: 180px; + margin-bottom: 10px; +} +.wpsdb .table-migrate-options li label { + font-size: 12px; + font-weight: normal; +} +.wpsdb .table-migrate-options li { + margin-bottom: 5px; +} +.wpsdb .general-helper { + border-radius: 50%; + border: 1px solid #ccc; + background-color: #eee; + width: 15px; + height: 15px; + display: inline-block; + position: relative; + top: 4px; + margin-top: -4px; + cursor: pointer; + margin-left: 2px; +} +.wpsdb .general-helper:hover { + border-color: #aaa; +} +.wpsdb .general-helper:after { + content: "?"; + color: #999999; + font-size: 10px; + font-weight: bold; + left: 4px; + position: absolute; + top: -1px; +} +.wpsdb .helper-message { + padding: 10px; + border: 1px solid #ccc; + border-radius: 3px; + background-color: #fff; + position: absolute; + width: 500px; + z-index: 100; + display: none; + box-shadow: 0px 0px 5px #ccc; +} +.wpsdb .inline-message { + padding: 10px; + border-radius: 3px; + margin-top: 5px; +} +.wpsdb .inline-message.error { + border: 1px solid #CC0000; + background-color: #FFEBE8; +} +.wpsdb .inline-message.warning { + background-color: #FFFFE0; + border: 1px solid #E6DB55; +} +.wpsdb .helper-message:after { + content: ''; + border-bottom: 7px solid transparent; + border-right: 7px solid #fff; + border-top: 7px solid transparent; + display: block; + height: 0; + left: -7px; + position: absolute; + top: 11px; + width: 0; +} +.wpsdb .helper-message:before { + content: ''; + border-bottom: 7px solid transparent; + border-right: 7px solid #aaa; + border-top: 7px solid transparent; + display: block; + height: 0; + left: -8px; + position: absolute; + top: 11px; + width: 0; +} +.wpsdb .label-disabled { + color: #888; +} +.wpsdb .prefix-notice, .wpsdb .ssl-notice, .wpsdb .different-plugin-version-notice, .wpsdb .directory-permission-notice { + background-color: #FFFFE0; + border: 1px solid #E6DB55; + padding: 15px; + border-radius: 3px; + margin-bottom: 15px; + display: none; +} +.wpsdb .prefix-notice p, .wpsdb .ssl-notice p, .wpsdb .different-plugin-version-notice p, .wpsdb .directory-permission-notice p { + margin-top: 0px; +} +.wpsdb .prefix-notice p:last-child, .wpsdb .ssl-notice p:last-child, .wpsdb .different-plugin-version-notice p:last-child, .wpsdb .directory-permission-notice p:last-child { + margin: 0px; +} +.wpsdb .different-plugin-version-notice, .wpsdb .directory-permission-notice { + background-color: #FFEBE8; + border-color: #CC0000; +} +.wpsdb .different-plugin-version-notice a, .wpsdb .directory-permission-notice a { + color: #CC0000; + text-decoration: underline; +} +.wpsdb .ssl-notice { + margin-bottom: 0; + margin-top: 15px; +} +.wpsdb .save-migration-profile-wrap li label { + font-size: 12px; + font-weight: normal; +} +.wpsdb .save-migration-profile-wrap li { + margin-bottom: 5px; + padding-left: 25px; +} +.wpsdb .save-migration-profile-wrap .indent-wrap { + margin-left: 0px; +} +.wpsdb .create-new-label { + margin-right: 8px; +} +.wpsdb .create-new-profile { + position: absolute; + top: -5px; +} +.wpsdb .delete-profile { + background-color: #eee; + border: 1px solid #ccc; + border-radius: 50% 50% 50% 50%; + cursor: pointer; + height: 11px; + left: 5px; + margin-left: 2px; + position: absolute; + margin-top: -6px; + top: 50%; + width: 11px; + display: none; + background-position: 50% 50%; + background-size: 6px 6px; + background-repeat: no-repeat; +} +.wpsdb .delete-profile:after { + content: "\00d7"; + left: 2px; + position: absolute; + top: -3px; + color: #aaa; + font-size: 12px; +} +.wpsdb .delete-profile:hover { + border-color: #aaa; +} +.wpsdb .migrate-db .ajax-success-msg { + font-weight: bold; + margin: 3px 0 0 9px; + display: inline-block; +} +.wpsdb p img.save-profile-ajax-spinner { + margin-left: 10px; +} +.wpsdb .backup-description { + left: 20px; + position: relative; +} +.wpsdb .backup-option-disabled { + margin-bottom: 0px; +} +.wpsdb .import-button { + display: none; +} +.wpsdb .settings-tab { + display: none; +} +.wpsdb .settings-tab .slider { + max-width: 416px; +} +.wpsdb .settings-tab .slider-label { + display: block; + margin-bottom: 10px; + float: left; + width: 50%; +} +.wpsdb .settings-tab .slider-label-wrapper { + max-width: 416px; + width: 100%; + position: relative; +} +.wpsdb .settings-tab .amount { + width: 50%; + text-align: right; + display: block; + text-align: right; + float: left; +} +.wpsdb .settings-tab .slider-spinner { + position: absolute; + right: -35px; + bottom: -13px; +} +.wpsdb .settings-tab .slider-success-msg { + display: none; + right: -53px; + bottom: -13px; + position: absolute; + font-weight: bold; +} +.wpsdb .settings-tab .ui-slider { + border: 1px solid #dfdfdf; + height: 10px; + border-radius: 2px; + position: relative; +} +.wpsdb .settings-tab .ui-slider-handle { + width: 7px; + height: 20px; + background-color: #aaa; + display: block; + position: absolute; + top: -5px; + outline: none; +} +.wpsdb .settings-tab .ui-slider-handle:active { + background-color: #999; +} +.wpsdb .settings-tab .ui-slider-range { + background-color: #eee; + height: 100%; +} +.wpsdb .settings-tab .option-section li label { + font-size: 12px; + font-weight: normal; + position: relative; +} +.wpsdb .settings-tab .option-section li { + margin-bottom: 5px; +} +.wpsdb .settings-tab .option-section li:last-child { + margin-bottom: 0px; +} +.wpsdb .settings-tab .option-section .ajax-spinner { + right: -23px; + left: inherit; + top: 0px; + position: absolute; +} +.wpsdb .settings-tab .option-section .ajax-success-msg { + right: -42px; + left: inherit; + top: 0px; + position: absolute; + font-weight: bold; +} +.wpsdb .settings-tab .option-section .verify-ssl .ajax-spinner { + right: -45px; +} +.wpsdb .settings-tab .option-section .verify-ssl .ajax-success-msg { + right: -65px; +} +.wpsdb .allow-remote-reqeusts { + font-size: 14px; + font-weight: bold; +} +.wpsdb .connection-info-label { + margin-top: 15px; + margin-bottom: 5px; + display: block; +} +.wpsdb .connection-info { + clear: both; + font-size: 15px; + line-height: 21px; + font-family: Consolas, Monaco, monospace; + padding: 10px 10px; + height: 67px; + text-shadow: 0px 1px 0px #fff; + display: block; + margin-bottom: 7px; + width: 418px; +} +.wpsdb .reset-button-wrap { + width: 418px; +} +.wpsdb .reset-api-key { + float: left; +} +.wpsdb .reset-api-key-ajax-spinner { + float: left; + margin: 4px 7px; +} +.wpsdb .help-tab { + display: none; +} +.wpsdb .help-tab h3 { + font-size: 18px; + font-weight: normal; +} +.wpsdb .help-tab .support { + border-bottom: 1px solid #ccc; + margin-bottom: 25px; + padding-bottom: 18px; +} +.wpsdb .help-tab .support p { + width: 640px; +} +.wpsdb .help-tab .support .email a { + font-size: 12px; +} +.wpsdb .help-tab .support .ajax-spinner { + top: 2px; +} +.wpsdb .help-tab .video-viewer { + margin-bottom: 30px; +} +.wpsdb .help-tab .videos { + width: 640px; +} +.wpsdb .help-tab .videos ul > li { + margin-bottom: 30px; + overflow: hidden; + position: relative; +} +.wpsdb .help-tab .videos ul > li a { + overflow: hidden; + display: block; + width: 320px; + height: 180px; + float: left; + margin-right: 15px; + position: relative; + z-index: 1; +} +.wpsdb .help-tab .videos ul > li a:before, .wpsdb .help-tab .videos ul > li a:after { + position: absolute; + content: " "; + margin: auto; + left: 0; + right: 0; + top: 0; + bottom: 0; +} +.wpsdb .help-tab .videos ul > li a:before { + width: 64px; + height: 64px; + -webkit-border-radius: 64px; + -moz-border-radius: 64px; + -ms-border-radius: 64px; + -o-border-radius: 64px; + border-radius: 64px; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); + opacity: 0.8; + border: 1px solid #ddd; + background-color: #fff; + z-index: 2; +} +.wpsdb .help-tab .videos ul > li a:after { + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); + opacity: 0.8; + border: 21.33333px solid transparent; + border-top-width: 12.8px; + border-bottom-width: 12.8px; + border-left-color: #333; + background: transparent; + display: block; + left: 25px; + width: 0px; + height: 0px; + z-index: 3; +} +.wpsdb .help-tab .videos .video:last-child { + margin-bottom: 0px; +} +.wpsdb .help-tab .videos img { + width: 320px; + height: 240px; + position: relative; + top: 50%; + margin-top: -120px; +} +.wpsdb .help-tab .debug { + width: 640px; + border-bottom: 1px solid #CCCCCC; + margin-bottom: 25px; + padding-bottom: 28px; +} +.wpsdb .help-tab .debug textarea { + width: 100%; + min-height: 200px; + font-family: Consolas, Monaco, monospace; + margin-bottom: 5px; +} +.wpsdb .help-tab h4 { + margin: 0 0 0.2em 0; +} +.wpsdb .help-tab p { + margin: 0 0 0.5em 0; +} +.wpsdb .help-tab iframe { + display: none; +} /* Progress Information */ /* Contain floats: h5bp.com/q */ .clearfix:before, .clearfix:after { content: ""; - display: table; } + display: table; +} .clearfix:after { - clear: both; } + clear: both; +} .clearfix { - zoom: 1; } + zoom: 1; +} .general-spinner { width: 16px; - height: 16px; } + height: 16px; +} .migration-error { color: #A21B1B; @@ -640,7 +798,8 @@ max-height: 400px; max-width: 100%; overflow: scroll; - word-wrap: break-word; } + word-wrap: break-word; +} .progress-content { display: none; @@ -657,195 +816,236 @@ margin-left: -40%; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; - box-sizing: border-box; } - .progress-content .progress-bar { - height: 10px; - background-color: #8cc1e9; - margin-bottom: 5px; - background-image: -webkit-gradient(linear, 50% 100%, 50% 0%, color-stop(0%, #72a7cf), color-stop(100%, #8cc1e9)); - background-image: -webkit-linear-gradient(bottom, #72a7cf, #8cc1e9); - background-image: -moz-linear-gradient(bottom, #72a7cf, #8cc1e9); - background-image: -o-linear-gradient(bottom, #72a7cf, #8cc1e9); - background-image: linear-gradient(bottom, #72a7cf, #8cc1e9); } - .progress-content .progress-title { - font-size: 18px; - font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", sans-serif; - font-weight: normal; - float: left; } - .progress-content .progress-bar { - width: 0%; } - .progress-content .progress-info-wrapper { - margin-bottom: 10px; } - .progress-content .progress-text { - clear: left; - float: left; - width: 100%; } - .progress-content .timer { - float: right; } - .progress-content .progress-tables { - overflow: hidden; - margin-bottom: 2px; - padding: 0 0 20px 0; } - .progress-content .progress-bar-wrapper { - position: relative; } - .progress-content .progress-bar-wrapper:before { - content: ''; - display: block; - height: 5px; - width: 1px; - background-color: #ccc; - position: absolute; - top: 15px; - left: 0px; } - .progress-content .progress-tables-hover-boxes { - position: absolute; - top: 0px; - left: 0px; - display: block; - width: 100%; } - .progress-content .progress-chunk-hover { - display: block; - float: left; - height: 35px; - position: relative; - top: -5px; - z-index: 1; } - .progress-content .progress-chunk { - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - float: left; - display: block; - height: 6px; - border-right: 1px solid #ccc; - border-bottom: 1px solid #ccc; - color: #999; - position: relative; - text-align: center; } - .progress-content .progress-chunk > span { - padding: 0px 3px; - white-space: nowrap; - text-overflow: ellipsis; - margin-top: 10px; - display: inline-block; } - .progress-content .progress-label { - padding: 5px 10px; - border: 1px solid #ccc; - border-radius: 3px; - background-color: #fff; - font-family: Consolas, Monaco, monospace; - font-size: 12px; - display: inline-block; - top: -35px; - position: absolute; - opacity: 0; - -webkit-transition: opacity 200ms ease-in-out; - -moz-transition: opacity 200ms ease-in-out; - -ms-transition: opacity 200ms ease-in-out; - -o-transition: opacity 200ms ease-in-out; - transition: opacity 200ms ease-in-out; } - .progress-content .label-visible { - opacity: 1; } - .progress-content .progress-label:before { - content: ""; - width: 0; - height: 0; - border-left: 4px solid transparent; - border-right: 4px solid transparent; - border-top: 4px solid #ccc; - display: block; - position: absolute; - bottom: -5px; - left: 50%; - margin-left: -2px; } - .progress-content .progress-label:after { - content: ""; - width: 0; - height: 0; - border-left: 4px solid transparent; - border-right: 4px solid transparent; - border-top: 4px solid #fff; - display: block; - position: absolute; - bottom: -4px; - left: 50%; - margin-left: -2px; } - .progress-content .migration-progress-ajax-spinner { - left: 7px; - position: relative; - top: 15px; } - .progress-content .close-progress-content { - color: #999999; - cursor: pointer; - font-family: "Times New Roman",serif; - font-size: 26px; - font-weight: 200; - position: absolute; - right: 20px; - top: 20px; - padding: 5px; - display: none; } - .progress-content .close-progress-content:hover { - color: #666; - border-color: #aaa; } + box-sizing: border-box; +} +.progress-content .progress-bar { + height: 10px; + background-color: #8cc1e9; + margin-bottom: 5px; + background-image: -webkit-gradient(linear, 50% 100%, 50% 0%, color-stop(0%, #72a7cf), color-stop(100%, #8cc1e9)); + background-image: -webkit-linear-gradient(bottom, #72a7cf, #8cc1e9); + background-image: -moz-linear-gradient(bottom, #72a7cf, #8cc1e9); + background-image: -o-linear-gradient(bottom, #72a7cf, #8cc1e9); + background-image: linear-gradient(bottom, #72a7cf, #8cc1e9); +} +.progress-content .progress-title { + font-size: 18px; + font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", sans-serif; + font-weight: normal; + float: left; +} +.progress-content .progress-bar { + width: 0%; +} +.progress-content .progress-info-wrapper { + margin-bottom: 10px; +} +.progress-content .progress-text { + clear: left; + float: left; + width: 100%; +} +.progress-content .timer { + float: right; +} +.progress-content .progress-tables { + overflow: hidden; + margin-bottom: 2px; + padding: 0 0 20px 0; +} +.progress-content .progress-bar-wrapper { + position: relative; +} +.progress-content .progress-bar-wrapper:before { + content: ''; + display: block; + height: 5px; + width: 1px; + background-color: #ccc; + position: absolute; + top: 15px; + left: 0px; +} +.progress-content .progress-tables-hover-boxes { + position: absolute; + top: 0px; + left: 0px; + display: block; + width: 100%; +} +.progress-content .progress-chunk-hover { + display: block; + float: left; + height: 35px; + position: relative; + top: -5px; + z-index: 1; +} +.progress-content .progress-chunk { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + float: left; + display: block; + height: 6px; + border-right: 1px solid #ccc; + border-bottom: 1px solid #ccc; + color: #999; + position: relative; + text-align: center; +} +.progress-content .progress-chunk > span { + padding: 0px 3px; + white-space: nowrap; + text-overflow: ellipsis; + margin-top: 10px; + display: inline-block; +} +.progress-content .progress-label { + padding: 5px 10px; + border: 1px solid #ccc; + border-radius: 3px; + background-color: #fff; + font-family: Consolas, Monaco, monospace; + font-size: 12px; + display: inline-block; + top: -35px; + position: absolute; + opacity: 0; + -webkit-transition: opacity 200ms ease-in-out; + -moz-transition: opacity 200ms ease-in-out; + -ms-transition: opacity 200ms ease-in-out; + -o-transition: opacity 200ms ease-in-out; + transition: opacity 200ms ease-in-out; +} +.progress-content .label-visible { + opacity: 1; +} +.progress-content .progress-label:before { + content: ""; + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #ccc; + display: block; + position: absolute; + bottom: -5px; + left: 50%; + margin-left: -2px; +} +.progress-content .progress-label:after { + content: ""; + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #fff; + display: block; + position: absolute; + bottom: -4px; + left: 50%; + margin-left: -2px; +} +.progress-content .migration-progress-ajax-spinner { + left: 7px; + position: relative; + top: 15px; +} +.progress-content .close-progress-content { + color: #999999; + cursor: pointer; + font-family: "Times New Roman",serif; + font-size: 26px; + font-weight: 200; + position: absolute; + right: 20px; + top: 20px; + padding: 5px; + display: none; +} +.progress-content .close-progress-content:hover { + color: #666; + border-color: #aaa; +} body.mp6 input[type=checkbox]:disabled { opacity: 1; - border-color: #ccc; } + border-color: #ccc; +} body.mp6 #wpsdb-main { margin-top: 15px; - font-size: 14px; } + font-size: 14px; +} body.mp6 p { - font-size: 14px; } + font-size: 14px; +} body.mp6 .wrap h2 { - float: left; } + float: left; +} body.mp6 .wpsdb input[type=checkbox], body.mp6 .wpsdb input[type=radio] { vertical-align: middle; - margin-top: -4px; } + margin-top: -4px; +} body.mp6 .wpsdb input[type=text], body.mp6 .wpsdb input[type=password] { - padding: 3px 5px; } + padding: 3px 5px; +} body.mp6 .wpsdb input.code { - padding-top: 6px; } + padding-top: 6px; +} body.mp6 .wpsdb label { - font-size: 14px; } + font-size: 14px; +} body.mp6 .wpsdb h2.nav-tab-wrapper { float: none; margin-bottom: 0; - width: 722px; } + width: 722px; +} body.mp6 .wpsdb .help-tab h3 { - margin-top: 0; } + margin-top: 0; +} body.mp6 .wpsdb .temp-disabled { - background-color: #f9f9f9; } + background-color: #f9f9f9; +} body.mp6 .wpsdb .migration-profile-options li a { border-color: #ccc; color: #555; - background-color: #e4e4e4; } + background-color: #e4e4e4; +} body.mp6 .wpsdb .migration-profile-options li a:hover { background-color: #fff; - color: #464646; } + color: #464646; +} body.mp6 .wpsdb .settings-tab .slider-label span { - vertical-align: middle; } + vertical-align: middle; +} body.mp6 .wpsdb .settings-tab .slider-label-wrapper { - font-size: 14px; } + font-size: 14px; +} body.mp6 .wpsdb .settings-tab .ui-slider { border-color: #ccc; - background-color: #fff; } + background-color: #fff; +} body.mp6 .wpsdb .settings-tab .ui-slider-range { - background-color: #d8fcd1; } + background-color: #d8fcd1; +} body.mp6 .wpsdb .settings-tab .option-section li label { - font-size: 14px; } + font-size: 14px; +} body.mp6 .wpsdb .connection-info, body.mp6 .wpsdb .migrate-tab .pull-push-connection-info { font-weight: bold; - font-size: 14px; } + font-size: 14px; +} body.mp6 .wpsdb .general-helper { border: 0; width: auto; height: auto; top: auto; - margin: 0; } + margin: 0; +} body.mp6 .wpsdb .general-helper:after { content: "\f223"; display: inline-block; @@ -854,47 +1054,65 @@ body.mp6 .wpsdb .general-helper:after { vertical-align: top; top: auto; left: auto; - position: relative; } + position: relative; +} body.mp6 .wpsdb .helper-message { font-size: 14px; - line-height: 1.4em; } + line-height: 1.4em; +} body.mp6 .wpsdb .right-arrow { - display: none; } + display: none; +} body.mp6 .wpsdb .arrow-col { - width: 75px; } + width: 75px; +} body.mp6 .wpsdb .arrow-col:after { content: "\f344"; display: inline-block; -webkit-font-smoothing: antialiased; font: normal 22px/1 'dashicons'; vertical-align: top; - color: #999; } + color: #999; +} body.mp6 .wpsdb .find-heading { - width: 388px; } + width: 388px; +} body.mp6 .wpsdb .replace-fields input { - width: 304px; } + width: 304px; +} body.mp6 .wpsdb .replace-right-col span { - border-color: #999; } - body.mp6 .wpsdb .replace-right-col span:hover { - border-color: #666; } + border-color: #999; +} +body.mp6 .wpsdb .replace-right-col span:hover { + border-color: #666; +} body.mp6 .wpsdb .replace-remove-row:after, body.mp6 .wpsdb .replace-remove-row:before, body.mp6 .wpsdb .replace-add-row:after, body.mp6 .wpsdb .replace-add-row:before { - background-color: #999; } + background-color: #999; +} body.mp6 .wpsdb .replace-remove-row:hover:after, body.mp6 .wpsdb .replace-remove-row:hover:before, body.mp6 .wpsdb .replace-add-row:hover:after, body.mp6 .wpsdb .replace-add-row:hover:before { - background-color: #666; } + background-color: #666; +} body.mp6 .wpsdb .option-group.migrate-selection > li > label { - font-size: 16px; } + font-size: 16px; +} body.mp6 .wpsdb .saved-migration-profile-label { - font-size: 16px; } + font-size: 16px; +} body.mp6 .wpsdb .option-heading, body.mp6 .wpsdb .checkbox-label { - font-size: 16px; } + font-size: 16px; +} body.mp6 .wpsdb .checkbox-label input[type=checkbox] { - top: auto; } + top: auto; +} body.mp6 .wpsdb .return-to-profile-selection { - font-size: 14px; } + font-size: 14px; +} body.mp6 .wpsdb .option-description { - font-size: 13px; } + font-size: 13px; +} body.mp6 .wpsdb .save-migration-profile-wrap li { - position: relative; } + position: relative; +} body.mp6 .wpsdb .delete-profile { border: 0; border-radius: 0; @@ -902,68 +1120,91 @@ body.mp6 .wpsdb .delete-profile { width: auto; left: 0; top: 50%; - margin-left: 0; } - body.mp6 .wpsdb .delete-profile:after { - content: "\f153"; - display: inline-block; - -webkit-font-smoothing: antialiased; - font: normal 18px/1 'dashicons'; - vertical-align: middle; - color: #999; } - body.mp6 .wpsdb .delete-profile:hover:after { - color: #666; } + margin-left: 0; +} +body.mp6 .wpsdb .delete-profile:after { + content: "\f153"; + display: inline-block; + -webkit-font-smoothing: antialiased; + font: normal 18px/1 'dashicons'; + vertical-align: middle; + color: #999; +} +body.mp6 .wpsdb .delete-profile:hover:after { + color: #666; +} body.mp6 .wpsdb .help-tab .support p, body.mp6 .wpsdb .help-tab .support .email a { - font-size: 14px; } + font-size: 14px; +} body.mp6 .wpsdb .help-tab .videos h4, body.mp6 .wpsdb .help-tab .videos p { - font-size: 14px; } + font-size: 14px; +} body.mp6 .wpsdb .inline-message, body.mp6 .wpsdb .notification-message { border-radius: 0; border: 0; box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1); padding: 10px 14px; - font-size: 13px; } + font-size: 13px; +} body.mp6 .wpsdb .notification-message { margin-bottom: 20px; - background-color: #fff; } - body.mp6 .wpsdb .notification-message p { - font-size: 13px; - margin-top: 0; } - body.mp6 .wpsdb .notification-message p:last-child { - margin: 0; } - body.mp6 .wpsdb .notification-message h4 { - margin-top: 0; } - body.mp6 .wpsdb .notification-message a { - color: #0074a2; - text-decoration: none; } - body.mp6 .wpsdb .notification-message a:hover { - color: #2ea2cc; } + background-color: #fff; +} +body.mp6 .wpsdb .notification-message p { + font-size: 13px; + margin-top: 0; +} +body.mp6 .wpsdb .notification-message p:last-child { + margin: 0; +} +body.mp6 .wpsdb .notification-message h4 { + margin-top: 0; +} +body.mp6 .wpsdb .notification-message a { + color: #0074a2; + text-decoration: none; +} +body.mp6 .wpsdb .notification-message a:hover { + color: #2ea2cc; +} body.mp6 .wpsdb .inline-message.error, body.mp6 .wpsdb .notification-message.error-notice { border-left: 4px solid #dd3d36; - background-color: #fff; } + background-color: #fff; +} body.mp6 .wpsdb .inline-message.warning, body.mp6 .wpsdb .notification-message.warning-notice { background-color: #fff; - border-left: 4px solid #ffba00; } + border-left: 4px solid #ffba00; +} body.mp6 .wpsdb .inline-message.success, body.mp6 .wpsdb .notification-message.success-notice { - border-left: 4px solid #7ad03a; } + border-left: 4px solid #7ad03a; +} body.mp6 .wpsdb .ssl-notice { - margin-bottom: 0; } + margin-bottom: 0; +} body.mp6 .wpsdb .different-plugin-version-notice, body.mp6 .wpsdb .directory-permission-notice { - margin-bottom: 10px; } + margin-bottom: 10px; +} body.mp6 .progress-content { font-size: 14px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); - background-color: #eee; } - body.mp6 .progress-content .progress-title { - font-family: 'Open Sans', sans-serif; - font-weight: normal; - font-size: 22px; } - body.mp6 .progress-content .dashicons-yes { - font-size: 42px; - line-height: 0.5em; } - body.mp6 .progress-content .progress-bar { - background-image: none; - background-color: #0074a2; } + background-color: #eee; +} +body.mp6 .progress-content .progress-title { + font-family: 'Open Sans', sans-serif; + font-weight: normal; + font-size: 22px; +} +body.mp6 .progress-content .dashicons-yes { + font-size: 42px; + line-height: 0.5em; +} +body.mp6 .progress-content .progress-bar { + background-image: none; + background-color: #0074a2; +} body.mp6 #overlay { - background-color: rgba(0, 0, 0, 0.5); } + background-color: rgba(0, 0, 0, 0.5); +} body.mp6 .migration-progress-ajax-spinner { - top: 20px; } + top: 20px; +} From 2b120fa0cdb3c914aec4516b9e18a8bbf7ef64fc Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Fri, 20 Jun 2014 23:49:04 -0400 Subject: [PATCH 27/52] update css to v1.4 --- asset/css/styles.css | 236 +++++++++++++++++++++++++++---------------- 1 file changed, 149 insertions(+), 87 deletions(-) diff --git a/asset/css/styles.css b/asset/css/styles.css index d110e7f..81dcc19 100755 --- a/asset/css/styles.css +++ b/asset/css/styles.css @@ -7,37 +7,44 @@ } .wpsdb { -/* ============================================================================= - Common & Global - ========================================================================== */ -/* ============================================================================= - Migrate Tab - ========================================================================== */ -/* Misc */ -/* Tabs */ -/* Saved migration profile selection */ -/* Output Selection */ -/* Find and Replace */ -/* Select Tables */ -/* Advanced Options */ -/* Save migration profile */ -/* Action buttons */ -/* Import DB */ -/* ============================================================================= - Settings Tab - ========================================================================== */ -/* ============================================================================= - Help Tab - ========================================================================== */ } -.wpsdb > div.updated.warning { + /* ============================================================================= + Common & Global + ========================================================================== */ + /* ============================================================================= + Migrate Tab + ========================================================================== */ + /* Misc */ + /* Tabs */ + /* Saved migration profile selection */ + /* Output Selection */ + /* Find and Replace */ + /* Select Tables */ + /* Advanced Options */ + /* Save migration profile */ + /* Action buttons */ + /* ============================================================================= + Settings Tab + ========================================================================== */ + /* ============================================================================= + Help Tab + ========================================================================== */ + /* ============================================================================= + Addons Tab + ========================================================================== */ +} +.wpsdb .updated { + clear: both; +} +.wpsdb div.updated.warning { max-width: 742px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; margin: 10px 0; } -.wpsdb > div.updated.warning p { +.wpsdb div.updated.warning p { font-size: 13px; + margin: 0.5em 0; } .wpsdb a { text-decoration: none; @@ -59,6 +66,9 @@ .wpsdb input[type=password] { padding: 5px; } +.wpsdb input[disabled=disabled] { + cursor: default; +} .wpsdb label.disabled { color: #888; cursor: default; @@ -197,14 +207,6 @@ font-size: 12px; font-weight: normal; } -.wpsdb .import-file label { - margin-right: 1em; -} -.wpsdb .import-file .note { - display: block; - color: #999; - font-style: italic; -} .wpsdb .option-heading, .wpsdb .checkbox-label { font-size: 14px; font-weight: bold; @@ -300,38 +302,19 @@ .wpsdb .replace-right-col span:hover { border-color: #aaa; } -.wpsdb .replace-remove-row { - margin: 0px 2px; +.wpsdb .sort-handle-col { + width: 20px; + cursor: -webkit-grab; + cursor: -moz-grab; } -.wpsdb .replace-remove-row:after { - content: ''; - background-color: #aaa; - display: block; - height: 2px; - left: 5px; - position: absolute; - top: 7px; - width: 6px; -} -.wpsdb .replace-add-row:after { - content: ''; - background-color: #aaa; - display: block; - height: 2px; - left: 5px; - position: absolute; - top: 7px; - width: 6px; -} -.wpsdb .replace-add-row:before { - content: ''; - background-color: #aaa; - display: block; - height: 6px; - left: 7px; - position: absolute; - top: 5px; - width: 2px; +.wpsdb .sort-handle:before { + content: "\f214"; + display: inline-block; + -webkit-font-smoothing: antialiased; + font: normal 16px/1 'dashicons'; + vertical-align: top; + color: #aaa; + background-color: transparent !important; } .wpsdb .original-repeatable-field { display: none; @@ -340,6 +323,13 @@ display: none; margin-bottom: 0px; } +.wpsdb .inline-message.missing-replace { + margin-top: 15px; + display: none; +} +.wpsdb #new-path-missing-warning { + margin-top: 5px; +} .wpsdb .tables-header { display: inline-block; } @@ -363,6 +353,9 @@ display: none; margin-top: 12px; } +.wpsdb .select-post-types-wrap { + display: block; +} .wpsdb .multiselect { min-width: 420px; min-height: 180px; @@ -407,9 +400,9 @@ background-color: #fff; position: absolute; width: 500px; - z-index: 100; + z-index: 9999; display: none; - box-shadow: 0px 0px 5px #ccc; + box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2); } .wpsdb .inline-message { padding: 10px; @@ -424,11 +417,23 @@ background-color: #FFFFE0; border: 1px solid #E6DB55; } +.wpsdb .helper-message:before { + content: ''; + border-bottom: 8px solid transparent; + border-right: 8px solid #aaa; + border-top: 8px solid transparent; + display: block; + height: 0; + left: -8px; + position: absolute; + top: 11px; + width: 0; +} .wpsdb .helper-message:after { content: ''; - border-bottom: 7px solid transparent; - border-right: 7px solid #fff; - border-top: 7px solid transparent; + border-bottom: 8px solid transparent; + border-right: 8px solid #fff; + border-top: 8px solid transparent; display: block; height: 0; left: -7px; @@ -436,16 +441,32 @@ top: 11px; width: 0; } -.wpsdb .helper-message:before { +.wpsdb .helper-message.bottom:before { content: ''; - border-bottom: 7px solid transparent; - border-right: 7px solid #aaa; - border-top: 7px solid transparent; + border-left: 8px solid transparent; + border-right: 8px solid transparent; + border-bottom: 8px solid #aaa; + border-top: 0; display: block; height: 0; - left: -8px; + left: 50%; + margin-left: -8px; position: absolute; - top: 11px; + top: -9px; + width: 0; +} +.wpsdb .helper-message.bottom:after { + content: ''; + border-left: 8px solid transparent; + border-right: 8px solid transparent; + border-bottom: 8px solid #fff; + border-top: 0; + display: block; + height: 0; + left: 50%; + margin-left: -8px; + position: absolute; + top: -8px; width: 0; } .wpsdb .label-disabled { @@ -473,10 +494,6 @@ color: #CC0000; text-decoration: underline; } -.wpsdb .ssl-notice { - margin-bottom: 0; - margin-top: 15px; -} .wpsdb .save-migration-profile-wrap li label { font-size: 12px; font-weight: normal; @@ -495,6 +512,7 @@ position: absolute; top: -5px; } +.wpsdb .replace-remove-row, .wpsdb .delete-profile { background-color: #eee; border: 1px solid #ccc; @@ -512,6 +530,7 @@ background-size: 6px 6px; background-repeat: no-repeat; } +.wpsdb .replace-remove-row:after, .wpsdb .delete-profile:after { content: "\00d7"; left: 2px; @@ -520,6 +539,10 @@ color: #aaa; font-size: 12px; } +.wpsdb .replace-remove-row:after { + position: relative; +} +.wpsdb .replace-remove-row:hover, .wpsdb .delete-profile:hover { border-color: #aaa; } @@ -536,10 +559,7 @@ position: relative; } .wpsdb .backup-option-disabled { - margin-bottom: 0px; -} -.wpsdb .import-button { - display: none; + margin-bottom: 0px !important; } .wpsdb .settings-tab { display: none; @@ -623,10 +643,10 @@ position: absolute; font-weight: bold; } -.wpsdb .settings-tab .option-section .verify-ssl .ajax-spinner { +.wpsdb .settings-tab .option-section .bubble .ajax-spinner { right: -45px; } -.wpsdb .settings-tab .option-section .verify-ssl .ajax-success-msg { +.wpsdb .settings-tab .option-section .bubble .ajax-success-msg { right: -65px; } .wpsdb .allow-remote-reqeusts { @@ -660,6 +680,29 @@ float: left; margin: 4px 7px; } +.wpsdb .plugin-compatibility-wrap { + padding: 18px 18px 18px 24px; + background-color: #e6e6e6; + margin-left: 0; +} +.wpsdb .plugin-compatibility-wrap p:last-of-type { + margin-bottom: 0; +} +.wpsdb ul.plugin-compatibility-options { + display: block; + margin: 10px 0 10px 0px; +} +.wpsdb .plugin-compatibility-spinner { + position: relative; + top: 3px; + left: 10px; +} +.wpsdb .plugin-compatibility-success-msg { + position: relative; + left: 10px; + font-weight: bold; + display: none; +} .wpsdb .help-tab { display: none; } @@ -968,6 +1011,19 @@ color: #666; border-color: #aaa; } +.progress-content .migration-controls { + display: block; + margin-top: 45px; +} +.progress-content .migration-controls span { + float: left; + text-align: center; + display: block; +} +.progress-content .migration-controls span:first-child { + margin-right: 10px; + width: 71px; +} body.mp6 input[type=checkbox]:disabled { opacity: 1; @@ -1075,7 +1131,7 @@ body.mp6 .wpsdb .arrow-col:after { color: #999; } body.mp6 .wpsdb .find-heading { - width: 388px; + width: 409px; } body.mp6 .wpsdb .replace-fields input { width: 304px; @@ -1086,10 +1142,10 @@ body.mp6 .wpsdb .replace-right-col span { body.mp6 .wpsdb .replace-right-col span:hover { border-color: #666; } -body.mp6 .wpsdb .replace-remove-row:after, body.mp6 .wpsdb .replace-remove-row:before, body.mp6 .wpsdb .replace-add-row:after, body.mp6 .wpsdb .replace-add-row:before { +body.mp6 .wpsdb .replace-add-row:after, body.mp6 .wpsdb .replace-add-row:before { background-color: #999; } -body.mp6 .wpsdb .replace-remove-row:hover:after, body.mp6 .wpsdb .replace-remove-row:hover:before, body.mp6 .wpsdb .replace-add-row:hover:after, body.mp6 .wpsdb .replace-add-row:hover:before { +body.mp6 .wpsdb .replace-add-row:hover:after, body.mp6 .wpsdb .replace-add-row:hover:before { background-color: #666; } body.mp6 .wpsdb .option-group.migrate-selection > li > label { @@ -1113,6 +1169,7 @@ body.mp6 .wpsdb .option-description { body.mp6 .wpsdb .save-migration-profile-wrap li { position: relative; } +body.mp6 .wpsdb .replace-remove-row, body.mp6 .wpsdb .delete-profile { border: 0; border-radius: 0; @@ -1122,6 +1179,7 @@ body.mp6 .wpsdb .delete-profile { top: 50%; margin-left: 0; } +body.mp6 .wpsdb .replace-remove-row:after, body.mp6 .wpsdb .delete-profile:after { content: "\f153"; display: inline-block; @@ -1130,12 +1188,16 @@ body.mp6 .wpsdb .delete-profile:after { vertical-align: middle; color: #999; } +body.mp6 .wpsdb .replace-remove-row:hover:after, body.mp6 .wpsdb .delete-profile:hover:after { color: #666; } body.mp6 .wpsdb .help-tab .support p, body.mp6 .wpsdb .help-tab .support .email a { font-size: 14px; } +body.mp6 .wpsdb .help-tab div.warning p { + font-size: 13px; +} body.mp6 .wpsdb .help-tab .videos h4, body.mp6 .wpsdb .help-tab .videos p { font-size: 14px; } From d2324a7c8eaa0aa319cccfcef6e6c98b7e18e8fd Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Fri, 20 Jun 2014 23:52:02 -0400 Subject: [PATCH 28/52] remove media files addon icon not needed because we don't have an addons/upsell tab --- asset/img/icon-media-files.svg | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 asset/img/icon-media-files.svg diff --git a/asset/img/icon-media-files.svg b/asset/img/icon-media-files.svg deleted file mode 100644 index 80a6ca2..0000000 --- a/asset/img/icon-media-files.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - From 3dc36cd2fa702a7504faf13d44fa252086530f82 Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Sat, 21 Jun 2014 01:05:04 -0400 Subject: [PATCH 29/52] reformat code --- asset/js/common.js | 49 +- asset/js/hook.js | 127 +- asset/js/script.js | 3810 +++++++++++++++++++++++--------------------- 3 files changed, 2061 insertions(+), 1925 deletions(-) diff --git a/asset/js/common.js b/asset/js/common.js index 0a5889b..6576157 100644 --- a/asset/js/common.js +++ b/asset/js/common.js @@ -6,34 +6,33 @@ var migration_error = false; var connection_data; function wpsdb_call_next_hook() { - if( ! call_stack.length ) { - call_stack = hooks; - } + if (!call_stack.length) { + call_stack = hooks; + } - var func = call_stack[0]; - call_stack.shift(); - window[func](); // Uses the string from the array to call the function of the same name + var func = call_stack[0]; + call_stack.shift(); + window[func](); // Uses the string from the array to call the function of the same name } -function wpsdb_add_commas( number_string ) { - number_string += ''; - x = number_string.split('.'); - x1 = x[0]; - x2 = x.length > 1 ? '.' + x[1] : ''; - var rgx = /(\d+)(\d{3})/; - while (rgx.test(x1)) { - x1 = x1.replace(rgx, '$1' + ',' + '$2'); - } - return x1 + x2; +function wpsdb_add_commas(number_string) { + number_string += ''; + x = number_string.split('.'); + x1 = x[0]; + x2 = x.length > 1 ? '.' + x[1] : ''; + var rgx = /(\d+)(\d{3})/; + while (rgx.test(x1)) { + x1 = x1.replace(rgx, '$1' + ',' + '$2'); + } + return x1 + x2; } -function wpsdb_parse_json( maybe_json ) { - try { - var json_object = jQuery.parseJSON( maybe_json ); - } - catch(e){ - // we simply return false here because the json data itself will never just contain a value of "false" - return false; - } - return json_object; +function wpsdb_parse_json(maybe_json) { + try { + var json_object = jQuery.parseJSON(maybe_json); + } catch (e) { + // we simply return false here because the json data itself will never just contain a value of "false" + return false; + } + return json_object; } diff --git a/asset/js/hook.js b/asset/js/hook.js index e1a4ea2..f5983e5 100644 --- a/asset/js/hook.js +++ b/asset/js/hook.js @@ -1,63 +1,68 @@ (function($) { - - $.wpsdb = { - /** - * Implement a WordPress-link Hook System for Javascript - * TODO: Change 'tag' to 'args', allow number (priority), string (tag), object (priority+tag) - */ - hooks: { action: {}, filter: {} }, - add_action: function( action, callable, tag ) { - jQuery.wpsdb.add_hook( 'action', action, callable, tag ); - }, - add_filter: function( action, callable, tag ) { - jQuery.wpsdb.add_hook( 'filter', action, callable, tag ); - }, - do_action: function( action, args ) { - jQuery.wpsdb.do_hook( 'action', action, null, args ); - }, - apply_filters: function( action, value, args ) { - return jQuery.wpsdb.do_hook( 'filter', action, value, args ); - }, - remove_action: function( action, tag ) { - jQuery.wpsdb.remove_hook( 'action', action, tag ); - }, - remove_filter: function( action, tag ) { - jQuery.wpsdb.remove_hook( 'filter', action, tag ); - }, - add_hook: function( hook_type, action, callable, tag ) { - if ( undefined == jQuery.wpsdb.hooks[hook_type][action] ) { - jQuery.wpsdb.hooks[hook_type][action] = []; - } - var hooks = jQuery.wpsdb.hooks[hook_type][action]; - if ( undefined == tag ) { - tag = action + '_' + hooks.length; - } - jQuery.wpsdb.hooks[hook_type][action].push( { tag:tag, callable:callable } ); - }, - do_hook: function( hook_type, action, value, args ) { - if ( undefined != jQuery.wpsdb.hooks[hook_type][action] ) { - var hooks = jQuery.wpsdb.hooks[hook_type][action]; - for( var i=0; i=0; i--) { - if (undefined==tag||tag==hooks[i].tag) - hooks.splice(i,1); - } - } - } - } - + $.wpsdb = { + /** + * Implement a WordPress-link Hook System for Javascript + * TODO: Change 'tag' to 'args', allow number (priority), string (tag), + object (priority+tag) + */ + hooks: { + action: {}, + filter: {} + }, + add_action: function(action, callable, tag) { + jQuery.wpsdb.add_hook('action', action, callable, tag); + }, + add_filter: function(action, callable, tag) { + jQuery.wpsdb.add_hook('filter', action, callable, tag); + }, + do_action: function(action, args) { + jQuery.wpsdb.do_hook('action', action, null, args); + }, + apply_filters: function(action, value, args) { + return jQuery.wpsdb.do_hook('filter', action, value, args); + }, + remove_action: function(action, tag) { + jQuery.wpsdb.remove_hook('action', action, tag); + }, + remove_filter: function(action, tag) { + jQuery.wpsdb.remove_hook('filter', action, tag); + }, + add_hook: function(hook_type, action, callable, tag) { + if (undefined == jQuery.wpsdb.hooks[hook_type][action]) { + jQuery.wpsdb.hooks[hook_type][action] = []; + } + var hooks = jQuery.wpsdb.hooks[hook_type][action]; + if (undefined == tag) { + tag = action + '_' + hooks.length; + } + jQuery.wpsdb.hooks[hook_type][action].push({ + tag: tag, + callable: callable + }); + }, + do_hook: function(hook_type, action, value, args) { + if (undefined != jQuery.wpsdb.hooks[hook_type][action]) { + var hooks = jQuery.wpsdb.hooks[hook_type][action]; + for (var i = 0; i < hooks.length; i++) { + if ('action' == hook_type) { + hooks[i].callable(args); + } else { + value = hooks[i].callable(value, args); + } + } + } + if ('filter' == hook_type) { + return value; + } + }, + remove_hook: function(hook_type, action, tag) { + if (undefined != jQuery.wpsdb.hooks[hook_type][action]) { + var hooks = jQuery.wpsdb.hooks[hook_type][action]; + for (var i = hooks.length - 1; i >= 0; i--) { + if (undefined == tag || tag == hooks[i].tag) + hooks.splice(i, 1); + } + } + } + }; })(jQuery); diff --git a/asset/js/script.js b/asset/js/script.js index 4721e1e..b52c89b 100755 --- a/asset/js/script.js +++ b/asset/js/script.js @@ -3,1843 +3,1975 @@ var migration_complete; var migration_complete_events; (function($) { - - var connection_established = false; - var last_replace_switch = ''; - var doing_ajax = false; - var doing_reset_api_key_ajax = false; - var doing_save_profile = false; - var profile_name_edited = false; - var show_prefix_notice = false; - var show_ssl_notice = false; - var show_version_notice = false; - var migration_completed = false; - var currently_migrating = false; - var dump_filename = ''; - var dump_url = ''; - var migration_intent; - var remote_site; - var secret_key; - var form_data; - var stage; - var elapsed_interval; - var completed_msg; - var tables_to_migrate = ''; - - var admin_url = ajaxurl.replace( '/admin-ajax.php', '' ), spinner_url = admin_url + '/images/wpspin_light'; - - if( window.devicePixelRatio >= 2 ){ - spinner_url += '-2x'; - } - - spinner_url += '.gif'; - - window.onbeforeunload = function (e) { - if( currently_migrating ){ - e = e || window.event; - - // For IE and Firefox prior to version 4 - if (e) { - e.returnValue = 'Sure?'; - } - - // For Safari - return 'Sure?'; - } - }; - - function pad(n, width, z) { - z = z || '0'; - n = n + ''; - return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n; - } - - function is_int(n) { - n = parseInt(n); - return typeof n === 'number' && n % 1 == 0; - } - - function setup_counter() { - var c = 0, - counter_display = $('.timer'), - label = 'Time Elapsed: '; - function display_count() { - hours = parseInt( c / 3600 ) % 24; - minutes = parseInt( c / 60 ) % 60; - seconds = c % 60; - var display = label + pad(hours,2,0) + ':' + pad(minutes,2,0) + ':' + pad(seconds,2,0); - counter_display.html(display); - } - - function count() { - c = c + 1; - display_count(); - } - - elapsed_interval = setInterval(count,1000); - } - - function get_intersect(arr1, arr2) { - var r = [], o = {}, l = arr2.length, i, v; - for (i = 0; i < l; i++) { - o[arr2[i]] = true; - } - l = arr1.length; - for (i = 0; i < l; i++) { - v = arr1[i]; - if (v in o) { - r.push(v); - } - } - return r; - } - - function get_query_var( name ){ - name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]"); - var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"), - results = regex.exec(location.search); - return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); - } - - function maybe_show_ssl_warning( url, key, remote_scheme ) { - var scheme = url.substr(0, url.indexOf(':')); - if( remote_scheme != scheme && url.indexOf('https') != -1 ) { - $('.ssl-notice').show(); - show_ssl_notice = true; - url = url.replace('https','http'); - $('.pull-push-connection-info').val( url + "\n" + key ); - return; - } - show_ssl_notice = false; - return; - } - - function maybe_show_version_warning( plugin_version, url ) { - if( typeof plugin_version != 'undefined' && plugin_version != wpsdb_plugin_version ) { - $('.different-plugin-version-notice').show(); - $('.remote-version').html( plugin_version ); - $('.remote-location').html( url ); - $('.step-two').hide(); - show_version_notice = true; - } - } - - function maybe_show_prefix_notice( prefix ) { - if( prefix != wpsdb_this_prefix ) { - $('.remote-prefix').html( prefix ); - show_prefix_notice = true; - if( $('#pull').is(':checked') ){ - $('.prefix-notice.pull').show(); - } - else { - $('.prefix-notice.push').show(); - } - } - } - - function get_domain_name( url ){ - var temp_url = url; - var domain = temp_url.replace( /\/\/(.*)@/, '//' ).replace('http://','').replace('https://','').replace('www.','').split(/[/?#]/)[0]; - return domain; - } - - function get_default_profile_name( url, intent, ing_suffix ){ - var domain = get_domain_name(url); - var action = intent; - action = action.charAt(0).toUpperCase() + action.slice(1); - if( ing_suffix ){ - action += 'ing'; - } - var preposition = 'to'; - if( intent == 'pull' ){ - preposition = 'from'; - } - - return profile_name = action + ' ' + preposition + ' ' + domain; - } - - function remove_protocol( url ) { - return url.replace(/^https?:/i, ""); - } - - $(document).ready(function() { - - if ( navigator.userAgent.indexOf('MSIE') > 0 || navigator.userAgent.indexOf('Trident') > 0 ) { - $('.ie-warning').show(); - } - - $('.slider').slider({ - range: 'min', - value: wpsdb_max_request / 1024, - min: 512, - max: wpsdb_bottleneck / 1024, - step: 512, - slide: function( event, ui ) { - $('.amount').html( wpsdb_add_commas( ui.value ) + ' kB' ); - }, - change: function( event, ui ) { - $('.amount').after( '' ); - $('.slider').slider('disable'); - $.ajax({ - url: ajaxurl, - type: 'POST', - dataType: 'json', - cache: false, - data: { - action : 'wpsdb_update_max_request_size', - max_request_size : parseInt( ui.value ), - }, - error: function(jqXHR, textStatus, errorThrown){ - $('.slider').slider('enable'); - $('.slider-spinner').remove(); - alert( 'A problem occurred when trying to change the maximum request size, please try again.' ); - }, - success: function(data){ - $('.slider').slider('enable'); - $('.slider-spinner').remove(); - $('.slider-success-msg').show(); - $('.slider-success-msg').fadeOut(2000,function(){ - $(this).hide(); - }); - } - }); - } - }); - $('.amount').html( wpsdb_add_commas( $('.slider').slider('value') ) + ' kB' ); - - var progress_content_original = $('.progress-content').clone(); - $('.progress-content').remove(); - - var this_tables = $.parseJSON(wpsdb_this_tables); - var this_prefixed_tables = $.parseJSON(wpsdb_this_prefixed_tables); - var push_select = $('#select-tables').clone(); - var pull_select = $('#select-tables').clone(); - var push_post_type_select = $('#select-post-types').clone(); - var pull_post_type_select = $('#select-post-types').clone(); - var push_select_backup = $('#select-backup').clone(); - var pull_select_backup = $('#select-backup').clone(); - - $('.help-tab .video').each(function() { - var $container = $(this), - $viewer = $('.video-viewer'); - - $('a', this).click(function() { - $viewer.attr('src', '//www.youtube.com/embed/' + $container.data('video-id') + '?autoplay=1'); - $viewer.show(); - var offset = $viewer.offset(); - $(window).scrollTop(offset.top - 50); - return false; - }); - }); - - $('.backup-options').show(); - $('.keep-active-plugins').show(); - if( $('#savefile').is(':checked') ){ - $('.backup-options').hide(); - $('.keep-active-plugins').hide(); - } - - function disable_export_type_controls() { - $('.option-group').each(function(index){ - $('input', this).attr('disabled','disabled'); - $('label', this).css('cursor','default'); - }); - } - - function enable_export_type_controls() { - $('.option-group').each(function(index){ - $('input', this).removeAttr('disabled'); - $('label', this).css('cursor','pointer'); - }); - } - - // automatically validate connnection info if we're loading a saved profile - establish_remote_connection_from_saved_profile(); - - function establish_remote_connection_from_saved_profile(){ - var action = $('input[name=action]:checked').val(); - var connection_info = $.trim( $('.pull-push-connection-info').val() ).split("\n"); - if( typeof wpsdb_default_profile == 'undefined' || wpsdb_default_profile == true || action == 'savefile' || doing_ajax ){ - return; - } - - last_replace_switch = action; - - doing_ajax = true; - disable_export_type_controls(); - - $('.connection-status').html( 'Establishing connection to remote server, please wait' ); - $('.connection-status').removeClass( 'notification-message error-notice migration-error' ); - $('.connection-status').append( '' ); - - var intent = $('input[name=action]:checked').val(); - - $.ajax({ - url: ajaxurl, - type: 'POST', - dataType: 'json', - cache: false, - data: { - action: 'wpsdb_verify_connection_to_remote_site', - url: connection_info[0], - key: connection_info[1], - intent: intent, - }, - error: function(jqXHR, textStatus, errorThrown){ - $('.connection-status').html( 'A problem occurred when attempting to connect to the local server, please check the details and try again. (#102)' ); - $('.connection-status').addClass( 'notification-message error-notice migration-error' ); - $('.ajax-spinner').remove(); - doing_ajax = false; - enable_export_type_controls(); - }, - success: function(data){ - $('.ajax-spinner').remove(); - doing_ajax = false; - enable_export_type_controls(); - - if( typeof data.wpsdb_error != 'undefined' && data.wpsdb_error == 1 ){ - $('.connection-status').html( data.body ); - $('.connection-status').addClass( 'notification-message error-notice migration-error' ); - - if( data.body.indexOf( '401 Unauthorized' ) > -1 ) { - $('.basic-access-auth-wrapper').show(); - } - - return; - } - - maybe_show_ssl_warning( connection_info[0], connection_info[1], data.scheme ); - maybe_show_version_warning( data.plugin_version, connection_info[0] ); - maybe_show_prefix_notice( data.prefix ); - - $('.pull-push-connection-info').addClass('temp-disabled'); - $('.pull-push-connection-info').attr('readonly','readonly'); - $('.connect-button').hide(); - - $('.connection-status').hide(); - $('.step-two').show(); - connection_established = true; - connection_data = data; - move_connection_info_box(); - - var loaded_tables = ''; - if( wpsdb_default_profile == false && typeof wpsdb_loaded_tables != 'undefined' ){ - loaded_tables = $.parseJSON( wpsdb_loaded_tables ); - } - - var table_select = document.createElement('select'); - $(table_select).attr({ - multiple: 'multiple', - name: 'select_tables[]', - id: 'select-tables', - class: 'multiselect' - }); - - $.each(connection_data.tables, function(index, value) { - var selected = $.inArray( value, loaded_tables ); - if( selected != -1 ){ - selected = ' selected="selected" '; - } - else{ - selected = ' '; - } - $(table_select).append('' + value + ' (' + connection_data.table_sizes_hr[value] + ')'); - }); - - pull_select = table_select; - - var loaded_post_prefixes = ''; - if( wpsdb_default_profile == false && typeof wpsdb_loaded_post_types != 'undefined' ){ - loaded_post_prefixes = $.parseJSON( wpsdb_loaded_post_types ); - } - - var post_type_select = document.createElement('select'); - $(post_type_select).attr({ - multiple: 'multiple', - name: 'select_post_types[]', - id: 'select-post-types', - class: 'multiselect' - }); - - $.each(connection_data.post_types, function(index, value) { - var selected = $.inArray( value, loaded_post_prefixes ); - if( selected != -1 || ( wpsdb_convert_exclude_revisions == true && value != 'revision' ) ){ - selected = ' selected="selected" '; - } - else{ - selected = ' '; - } - $(post_type_select).append('' + value + ''); - }); - - pull_post_type_select = post_type_select; - - var loaded_tables_backup = ''; - if( wpsdb_default_profile == false && typeof wpsdb_loaded_tables_backup != 'undefined' ){ - loaded_tables_backup = $.parseJSON( wpsdb_loaded_tables_backup ); - } - - var table_select_backup = document.createElement('select'); - $(table_select_backup).attr({ - multiple: 'multiple', - name: 'select_backup[]', - id: 'select-backup', - class: 'multiselect' - }); - - $.each(connection_data.tables, function(index, value) { - var selected = $.inArray( value, loaded_tables_backup ); - if( selected != -1 ){ - selected = ' selected="selected" '; - } - else{ - selected = ' '; - } - $(table_select_backup).append('' + value + ' (' + connection_data.table_sizes_hr[value] + ')'); - }); - - push_select_backup = table_select_backup; - - if( $('#pull').is(':checked') ){ - $('#select-tables').remove(); - $('.select-tables-wrap').prepend(pull_select); - $('#select-post-types').remove(); - $('.select-post-types-wrap').prepend(pull_post_type_select); - $('#select-backup').remove(); - $('.backup-tables-wrap').prepend(pull_select_backup); - $('.table-prefix').html(data.prefix); - $('.uploads-dir').html(wpsdb_this_uploads_dir); - } - else { - $('#select-backup').remove(); - $('.backup-tables-wrap').prepend(push_select_backup); - } - - $.wpsdb.do_action( 'verify_connection_to_remote_site', connection_data ); - - } - - }); - - } - - // add to tags which act as JS event buttons, will not jump page to top and will deselect the button - $('.js-action-link').click(function(event){ - $(this).blur(); - return false; - }); - - // clears the debug log - $('.clear-log').click(function(){ - $('.debug-log-textarea').val(''); - $.ajax({ - url: ajaxurl, - type: 'POST', - dataType: 'text', - cache: false, - data: { - action : 'wpsdb_clear_log', - }, - error: function(jqXHR, textStatus, errorThrown){ - alert('An error occurred when trying to clear the debug log. Please contact support. (#132)'); - }, - success: function(data){ - } - }); - }); - - // updates the debug log when the user switches to the help tab - function refresh_debug_log(){ - $.ajax({ - url: ajaxurl, - type: 'POST', - dataType: 'text', - cache: false, - data: { - action : 'wpsdb_get_log', - }, - error: function(jqXHR, textStatus, errorThrown){ - alert('An error occurred when trying to update the debug log. Please contact support. (#133)'); - }, - success: function(data){ - $('.debug-log-textarea').val(data); - } - }); - } - - // select all tables - $('.multiselect-select-all').click(function(){ - var multiselect = $(this).parents('.select-wrap').children('.multiselect'); - $(multiselect).focus(); - $('option', multiselect).attr('selected',1); - }); - - // deselect all tables - $('.multiselect-deselect-all').click(function(){ - var multiselect = $(this).parents('.select-wrap').children('.multiselect'); - $(multiselect).focus(); - $('option', multiselect).removeAttr('selected'); - }); - - // invert table selection - $('.multiselect-invert-selection').click(function(){ - var multiselect = $(this).parents('.select-wrap').children('.multiselect'); - $(multiselect).focus(); - $('option', multiselect).each(function(){ - $(this).attr('selected', ! $(this).attr('selected')); - }); - }); - - // on option select hide all "advanced" option divs and show the correct div for the option selected - $('.option-group input[type=radio]').change(function() { - group = $(this).closest('.option-group'); - $('ul', group).hide(); - parent = $(this).closest('li'); - $('ul', parent).show(); - }); - - // on page load, expand hidden divs for selected options (browser form cache) - $('.option-group').each(function(){ - $('.option-group input[type=radio]').each(function(){ - if( $(this).is(':checked') ){ - parent = $(this).closest('li'); - $('ul', parent).show(); - } - }); - }); - - // expand and collapse content on click - $('.header-expand-collapse').click(function(){ - if( $('.expand-collapse-arrow', this).hasClass('collapsed') ){ - $('.expand-collapse-arrow', this).removeClass('collapsed'); - $(this).next().show(); - } - else{ - $('.expand-collapse-arrow', this).addClass('collapsed'); - $(this).next().hide(); - } - }); - - $('.checkbox-label input[type=checkbox]').change(function() { - if( $(this).is(':checked') ){ - $(this).parent().next().show(); - } - else { - $(this).parent().next().hide(); - } - }); - - // special expand and collapse content on click for save migration profile - $('#save-migration-profile').change(function() { - if( $(this).is(':checked') ){ - $('.save-settings-button').show(); - $('.migrate-db .button-primary').val('Migrate DB & Save'); - } - else{ - $('.save-settings-button').hide(); - $('.migrate-db .button-primary').val('Migrate DB'); - } - }); - - if( $('#save-migration-profile').is(':checked') ){ - $('.save-settings-button').show(); - $('.migrate-db .button-primary').val('Migrate DB & Save'); - }; - - $('.checkbox-label input[type=checkbox]').each(function(){ - if( $(this).is(':checked') ){ - $(this).parent().next().show(); - } - }); - - // AJAX migrate button - $('.migrate-db-button').click(function(event){ - $(this).blur(); - event.preventDefault(); - - // check that they've selected some tables to migrate - if( $('#migrate-selected').is(':checked') && $('#select-tables').val() == null ){ - alert( 'Please select at least one table to migrate.'); - return; - } - - // also save profile - if( $('#save-migration-profile').is(':checked') ){ - - if( $.trim( $('.create-new-profile').val() ) == '' && $('#create_new').is(':checked') ){ - alert('Please enter a name for your migration profile.'); - $('.create-new-profile').focus(); - return; - } - - var create_new_profile = false; - - if( $('#create_new').is(':checked') ){ - create_new_profile = true; - } - var profile_name = $('.create-new-profile').val(); - - profile = $('#migrate-form').serialize(); - - $.ajax({ - url: ajaxurl, - type: 'POST', - dataType: 'text', - cache: false, - data: { - action: 'wpsdb_save_profile', - profile: profile, - }, - error: function(jqXHR, textStatus, errorThrown){ - alert('An error occurred when attempting to save the migration profile. Please see the Help tab for details on how to request support. (#118)'); - }, - success: function(data){ - if(create_new_profile){ - var new_li = '
  • '; - $('#create_new').parents('li').before(new_li); - $('#profile-' + data).attr('checked','checked'); - $('.create-new-profile').val(''); - } - } - }); - } - - form_data = $('#migrate-form').serialize(); - - var doc_height = $(document).height(); - - $('body').append('
    '); - - $('#overlay') - .height(doc_height) - .css({ - 'position': 'fixed', - 'top': 0, - 'left': 0, - 'width': '100%', - 'z-index': 99999, - 'display': 'none', - }); - - $progress_content = progress_content_original.clone(); - migration_intent = $('input[name=action]:checked').val(); - - stage = 'backup'; - - if( migration_intent == 'savefile' ){ - stage = 'migrate'; - } - - if( $('#create-backup').is(':checked') == false ){ - stage = 'migrate'; - } - - var table_intent = $('input[name=table_migrate_option]:checked').val(); - var connection_info = $.trim( $('.pull-push-connection-info').val() ).split("\n"); - var table_rows = ''; - - remote_site = connection_info[0]; - secret_key = connection_info[1]; - - var static_migration_label = ''; - - $('#overlay').after($progress_content); - - completed_msg = 'Exporting complete'; - - if( migration_intent == 'savefile' ){ - static_migration_label = 'Exporting, please wait...'; - } - else{ - static_migration_label = get_default_profile_name(remote_site, migration_intent, true) + ', please wait...'; - completed_msg = get_default_profile_name(remote_site, migration_intent, true) + ' complete'; - } - - $('.progress-title').html(static_migration_label); - - $('#overlay').show(); - backup_option = $('input[name=backup_option]:checked').val(); - table_option = $('input[name=table_migrate_option]:checked').val(); - - if( stage == 'backup' ) { - if( table_option == 'migrate_only_with_prefix' && backup_option == 'backup_selected' ) { - backup_option = 'backup_only_with_prefix'; - } - if( migration_intent == 'push' ){ - table_rows = connection_data.table_rows; - if( backup_option == 'backup_only_with_prefix' ) { - tables_to_migrate = connection_data.prefixed_tables; - } - else if( backup_option == 'backup_selected' ) { - selected_tables = $('#select-tables').val(); - tables_to_migrate = get_intersect( selected_tables, connection_data.tables ); - } - else if( backup_option == 'backup_manual_select' ) { - tables_to_migrate = $('#select-backup').val(); - } - } - else{ - table_rows = $.parseJSON(wpsdb_this_table_rows); - if( backup_option == 'backup_only_with_prefix' ) { - tables_to_migrate = $.parseJSON( wpsdb_this_prefixed_tables ); - } - else if( backup_option == 'backup_selected' ) { - selected_tables = $('#select-tables').val(); - local_tables = $.parseJSON( wpsdb_this_tables ); - tables_to_migrate = get_intersect( selected_tables, local_tables ); - } - else if( backup_option == 'backup_manual_select' ) { - tables_to_migrate = $('#select-backup').val(); - } - } - } - else { - if( table_intent == 'migrate_select' ){ // user has elected to migrate only certain tables - // grab tables as per what the user has selected from the multiselect box - tables_to_migrate = $('#select-tables').val(); - // user is pushing or exporting - if( migration_intent == 'push' || migration_intent == 'savefile' ){ - // default value, assuming we're not backing up - table_rows = $.parseJSON(wpsdb_this_table_rows); - } - else{ - table_rows = connection_data.table_rows; - } - } - else{ - if( migration_intent == 'push' || migration_intent == 'savefile' ){ - tables_to_migrate = this_prefixed_tables; - table_rows = $.parseJSON(wpsdb_this_table_rows); - } - else{ - tables_to_migrate = connection_data.prefixed_tables; - table_rows = connection_data.table_rows; - } - } - } - - function decide_tables_to_display_rows( tables_to_migrate, table_rows ){ - - var total_size = 0; - $.each(tables_to_migrate, function(index, value) { - total_size += parseInt(table_rows[value]); - }); - - var last_element = ''; - $.each(tables_to_migrate, function(index, value) { - var percent = table_rows[value] / total_size * 100; - var percent_rounded = Math.round(percent*1000)/1000; - $('.progress-tables').append('
    ' + value + '
    '); - $('.progress-tables-hover-boxes').append('
    '); - var label = $('.progress-tables .progress-chunk:last span'); - last_element = value; - }); - - $('.progress-chunk').each(function(index){ - if( $(this).width() < 1 && tables_to_migrate[index] != last_element ){ - $(this).hide(); - $('.progress-chunk-hover[data-table=' + tables_to_migrate[index] + ']').hide(); - table_rows[last_element] = Number(table_rows[last_element]); - table_rows[last_element] += Number(table_rows[tables_to_migrate[index]]); - table_rows[tables_to_migrate[index]] = 0; - } - var element = this; - setTimeout(function(){ - hide_overflowing_elements(element); - }, 0); - - function hide_overflowing_elements(element){ - if( $('span', element).innerWidth() > $(element).width() ){ - $('span', element).hide(); - } - } - - }); - - percent_rounded = 0; - if( table_rows[last_element] != 0 ){ - var percent = table_rows[last_element] / total_size * 100; - var percent_rounded = Math.round(percent*1000)/1000; - } - $('.progress-tables .progress-chunk:last').css('width',percent_rounded + '%'); - $('.progress-chunk-hover:last').css('width',percent_rounded + '%'); - - var return_vals = [table_rows,total_size]; - - return return_vals; - - } - - table_details = decide_tables_to_display_rows( tables_to_migrate, table_rows ); - table_rows = table_details[0]; - total_size = table_details[1]; - - $('.progress-title').after( '' ); - - var height = $('.progress-content').outerHeight(); - $('.progress-content').css('top', '-' + height + 'px').show().animate({'top': '0px'}); - - setup_counter(); - currently_migrating = true; - - $.ajax({ - url: ajaxurl, - type: 'POST', - dataType: 'json', - cache: false, - data: { - action : 'wpsdb_initiate_migration', - intent : migration_intent, - url : remote_site, - key : secret_key, - form_data : form_data, - stage : stage, - }, - error: function(jqXHR, textStatus, errorThrown){ - $('.progress-title').html('Migration failed'); - $('.progress-text').html( 'A problem occurred when attempting to connect to the local server, please check the details and try again. (#112)' ); - $('.progress-text').addClass( 'migration-error' ); - console.log( jqXHR ); - console.log( textStatus ); - console.log( errorThrown ); - migration_error = true; - migration_complete_events(); - return; - }, - success: function(data){ - if( typeof data.wpsdb_error != 'undefined' && data.wpsdb_error == 1 ){ - migration_complete_events(); - $('.progress-title').html('Migration failed'); - $('.progress-text').addClass( 'migration-error' ); - $('.progress-text').html( data.body ); - return; - } - - dump_url = data.dump_url; - dump_filename = data.dump_filename; - - var i = 0; - var progress_size = 0; - var overall_percent = 0; - var table_progress = 0; - var temp_progress = 0; - var last_progress = 0; - var overall_table_progress = 0; - - function migrate_table_recursive( current_row, primary_keys ){ - - if( i >= tables_to_migrate.length ){ - if( stage == 'backup' ) { - stage = 'migrate'; - i = 0; - progress_size = 0; - $('.progress-bar').width('0px'); - - if( table_intent == 'migrate_select' ){ - tables_to_migrate = $('#select-tables').val(); - if( migration_intent == 'push' || migration_intent == 'savefile' ){ - table_rows = $.parseJSON(wpsdb_this_table_rows); - } - else{ - table_rows = connection_data.table_rows; - } - } - else{ - if( migration_intent == 'push' || migration_intent == 'savefile' ){ - tables_to_migrate = this_prefixed_tables; - table_rows = $.parseJSON(wpsdb_this_table_rows); - } - else{ - tables_to_migrate = connection_data.prefixed_tables; - table_rows = connection_data.table_rows; - } - } - - $('.progress-tables').empty(); - $('.progress-tables-hover-boxes').empty(); - - table_details = decide_tables_to_display_rows( tables_to_migrate, table_rows ); - table_rows = table_details[0]; - total_size = table_details[1]; - - } - else { - hooks = $.wpsdb.apply_filters( 'wpsdb_before_migration_complete_hooks', hooks ); - hooks.push( 'migration_complete' ); - hooks = $.wpsdb.apply_filters( 'wpsdb_after_migration_complete_hooks', hooks ); - hooks.push( 'migration_complete_events' ); - wpsdb_call_next_hook(); - return; - } - } - - if( stage == 'backup' ){ - $('.progress-text').html( overall_percent + '% - Backing up "' + tables_to_migrate[i] + '"' ); - } - else{ - $('.progress-text').html( overall_percent + '% - Migrating "' + tables_to_migrate[i] + '"'); - } - - last_table = 0; - if( i == ( tables_to_migrate.length - 1 ) ) { - last_table = 1; - } - - gzip = 0; - if( migration_intent != 'savefile' && parseInt( connection_data.gzip ) == 1 ) { - gzip = 1; - } - - var request_data = { - action : 'wpsdb_migrate_table', - intent : migration_intent, - url : remote_site, - key : secret_key, - table : tables_to_migrate[i], - form_data : form_data, - stage : stage, - current_row : current_row, - dump_filename : dump_filename, - last_table : last_table, - primary_keys : primary_keys, - gzip : gzip, - }; - - if( migration_intent != 'savefile' ) { - request_data.bottleneck = connection_data.bottleneck; - request_data.prefix = connection_data.prefix; - } - - if( connection_data && connection_data.path_current_site && connection_data.domain ) { - request_data.path_current_site = connection_data.path_current_site; - request_data.domain_current_site = connection_data.domain; - } - - $.ajax({ - url: ajaxurl, - type: 'POST', - dataType: 'text', - cache: false, - timeout: 0, - data: request_data, - error: function(jqXHR, textStatus, errorThrown){ - $('.progress-title').html('Migration failed'); - $('.progress-text').html( 'A problem occurred when processing the ' + tables_to_migrate[i] + ' table. (#113)' ); - $('.progress-text').append( '

    Status: ' + jqXHR.status + ' ' + jqXHR.statusText + '

    Response:
    ' + jqXHR.responseText ); - $('.progress-text').addClass( 'migration-error' ); - console.log( jqXHR ); - console.log( textStatus ); - console.log( errorThrown ); - migration_error = true; - migration_complete_events(); - return; - }, - success: function(data){ - data = $.trim( data ); - row_information = wpsdb_parse_json( data ); - if( false == row_information || null == row_information ){ - $('.progress-title').html('Migration failed'); - if( '' == data || null == data ) { - $('.progress-text').html( 'A problem occurred when processing the ' + tables_to_migrate[i] + ' table. We were expecting a response in JSON format but instead received an empty response.' ); - } - else { - $('.progress-text').html(data); - } - $('.progress-text').addClass('migration-error'); - migration_error = true; - migration_complete_events(); - return; - } - - if( row_information.current_row == '-1' ) { - progress_size -= overall_table_progress; - overall_table_progress = 0; - last_progress = 0; - progress_size += parseInt(table_rows[tables_to_migrate[i]]); - i++; - row_information.current_row = ''; - row_information.primary_keys = ''; - } - else { - temp_progress = parseInt( row_information.current_row ); - table_progress = temp_progress - last_progress; - last_progress = temp_progress; - progress_size += table_progress; - overall_table_progress += table_progress; - } - var percent = 100 * progress_size / total_size; - $('.progress-bar').width(percent + '%'); - overall_percent = Math.floor(percent); - migrate_table_recursive( row_information.current_row, row_information.primary_keys ); - } - }); - - } - - migrate_table_recursive( '-1', '' ); - - } - - }); // end ajax - - }); - - migration_complete_events = function() { - if( false == migration_error ) { - if( non_fatal_errors == '' ) { - if( 'savefile' != migration_intent && true == $('#save_computer').is(':checked') ) { - $('.progress-text').css('visibility','hidden'); - } - $('.progress-title').html(completed_msg).append('
    '); - } - else { - $('.progress-text').html(non_fatal_errors); - $('.progress-text').addClass('migration-error'); - $('.progress-title').html('Migration completed with some errors'); - } - - $('.progress-bar-wrapper').hide(); - } - - // reset migration variables so consecutive migrations work correctly - hooks = []; - call_stack = []; - migration_error = false; - currently_migrating = false; - migration_completed = true; - non_fatal_errors = ''; - - $('.progress-label').remove(); - $('.migration-progress-ajax-spinner').remove(); - $('.close-progress-content').show(); - $('#overlay').css('cursor','pointer'); - clearInterval( elapsed_interval ); - } - - migration_complete = function() { - if( migration_intent == 'savefile' ){ - currently_migrating = false; - var migrate_complete_text = 'Migration complete'; - if( $('#save_computer').is(':checked') ){ - var url = wpsdb_this_download_url + encodeURIComponent( dump_filename ); - if( $('#gzip_file').is(':checked') ){ - url += '&gzip=1'; - } - window.location = url; - } - else{ - migrate_complete_text = 'Migration complete, your backup is located at:
    ' + dump_url + '.'; - } - - if( migration_error == false ){ - $('.progress-text').html(migrate_complete_text); - migration_complete_events(); - $('.progress-title').html(completed_msg); - } - - } - else{ // rename temp tables, delete old tables - $('.progress-text').html('Finalizing migration'); - $.ajax({ - url: ajaxurl, - type: 'POST', - dataType: 'text', - cache: false, - data: { - action : 'wpsdb_finalize_migration', - intent : migration_intent, - url : remote_site, - key : secret_key, - form_data : form_data, - prefix : connection_data.prefix, - temp_prefix : connection_data.temp_prefix, - tables : tables_to_migrate.join(','), - }, - error: function(jqXHR, textStatus, errorThrown){ - $('.progress-title').html('Migration failed'); - $('.progress-text').html('A problem occurred when finalizing the backup. (#132)'); - $('.progress-text').addClass('migration-error'); - alert( jqXHR + ' : ' + textStatus + ' : ' + errorThrown ); - migration_error = true; - migration_complete_events(); - return; - }, - success: function(data){ - if( $.trim( data ) != '' ){ - $('.progress-title').html('Migration failed'); - $('.progress-text').html(data); - $('.progress-text').addClass('migration-error'); - migration_error = true; - migration_complete_events(); - return; - } - wpsdb_call_next_hook(); - } - }); - } - - } - - // close progress pop up once migration is completed - $('body').delegate('.close-progress-content-button', 'click', function(e){ - hide_overlay(); - }); - - $('body').delegate('#overlay', 'click', function(){ - if( migration_completed == true ){ - hide_overlay(); - } - }); - - function hide_overlay(){ - var height = $('.progress-content').outerHeight(); - $('.progress-content').animate({'top' : '-' + height + 'px'}, 400, 'swing', function(){ $('#overlay').remove(); $('.progress-content').remove(); } ); - migration_completed = false; - } - - // AJAX save button profile - $('.save-settings-button').click(function(event){ - var profile; - $(this).blur(); - event.preventDefault(); - - if( doing_save_profile ){ - return; - } - - // check that they've selected some tables to migrate - if( $('#migrate-selected').is(':checked') && $('#select-tables').val() == null ){ - alert( 'Please select at least one table to migrate.'); - return; - } - - if( $.trim( $('.create-new-profile').val() ) == '' && $('#create_new').is(':checked') ){ - alert('Please enter a name for your migration profile.'); - $('.create-new-profile').focus(); - return; - } - - var create_new_profile = false; - - if( $('#create_new').is(':checked') ){ - create_new_profile = true; - } - var profile_name = $('.create-new-profile').val(); - - doing_save_profile = true; - profile = $('#migrate-form').serialize(); - - $('.save-settings-button').after( '' ); - $(this).attr('disabled','disabled'); - - $.ajax({ - url: ajaxurl, - type: 'POST', - dataType: 'text', - cache: false, - data: { - action: 'wpsdb_save_profile', - profile: profile, - }, - error: function(jqXHR, textStatus, errorThrown){ - alert('An error occurred when attempting to save the migration profile. Please see the Help tab for details on how to request support. (#104)'); - $('.save-settings-button').removeAttr('disabled'); - $('.save-profile-ajax-spinner').remove(); - $('.save-settings-button').after('Saved'); - $('.ajax-success-msg').fadeOut(2000,function(){ - $(this).remove(); - }); - doing_save_profile = false; - }, - success: function(data){ - $('.save-settings-button').removeAttr('disabled'); - $('.save-profile-ajax-spinner').remove(); - $('.save-settings-button').after('Saved'); - $('.ajax-success-msg').fadeOut(2000,function(){ - $(this).remove(); - }); - doing_save_profile = false; - $('.create-new-profile').val(''); - - if(create_new_profile){ - var new_li = '
  • '; - $('#create_new').parents('li').before(new_li); - $('#profile-' + data).attr('checked','checked'); - } - - } - }); - - }); - - // progress label updating - $('body').delegate('.progress-chunk-hover', 'mousemove', function(e) { - mX = e.pageX; - offset = $('.progress-bar-wrapper').offset(); - label_offset = $('.progress-label').outerWidth() / 2; - mX = ( mX - offset.left ) - label_offset; - $('.progress-label').css('left', mX + 'px'); - $('.progress-label').html($(this).attr('data-table')); - }); - - // show / hide progress lavel on hover - $('body').delegate('.progress-chunk-hover', 'hover', function(event) { - if( event.type === 'mouseenter' ){ - $('.progress-label').addClass('label-visible'); - } - else{ - $('.progress-label').removeClass('label-visible'); - } - }); - - // move around textarea depending on whether or not the push/pull options are selected - connection_info_box = $('.connection-info-wrapper'); - move_connection_info_box(); - - $('.migrate-selection.option-group input[type=radio]').change(function() { - move_connection_info_box(); - if( connection_established ){ - change_replace_values(); - } - }); - - // save file (export) / import / push / pull special conditions - function move_connection_info_box(){ - $('.import-button').hide(); - $('.connection-status').hide(); - $('.prefix-notice').hide(); - $('.ssl-notice').hide(); - $('.different-plugin-version-notice').hide(); - $('.step-two').show(); - $('.backup-options').show(); - $('.keep-active-plugins').show(); - $('.directory-permission-notice').hide(); - $('#create-backup').removeAttr('disabled'); - $('#create-backup-label').removeClass('disabled'); - $('.backup-option-disabled').hide(); - var connection_info = $.trim( $('.pull-push-connection-info').val() ).split("\n"); - if( $('#pull').is(':checked') ){ - $('.pull-list li').append( connection_info_box ); - connection_info_box.show(); - if( connection_established ){ - $('.connection-status').hide(); - $('.step-two').show(); - $('.table-prefix').html(connection_data.prefix); - $('.uploads-dir').html(wpsdb_this_uploads_dir); - if( profile_name_edited == false ){ - var profile_name = get_domain_name( connection_info[0] ); - $('.create-new-profile').val(profile_name); - } - if( show_prefix_notice == true ) { - $('.prefix-notice.pull').show(); - } - if( show_ssl_notice == true ) { - $('.ssl-notice').show(); - } - if( show_version_notice == true ) { - $('.different-plugin-version-notice').show(); - $('.step-two').hide(); - } - $('.directory-scope').html('local'); - if( false == wpsdb_write_permission ) { - $('#create-backup').prop('checked',false); - $('#create-backup').attr('disabled','disabled'); - $('#create-backup-label').addClass('disabled'); - $('.backup-option-disabled').show(); - $('.upload-directory-location').html(wpsdb_this_upload_dir_long); - } - } - else{ - $('.connection-status').show(); - $('.step-two').hide(); - } - } - else if( $('#push').is(':checked') ){ - $('.push-list li').append( connection_info_box ); - connection_info_box.show(); - if( connection_established ){ - $('.connection-status').hide(); - $('.step-two').show(); - $('.table-prefix').html(wpsdb_this_prefix); - $('.uploads-dir').html(connection_data.uploads_dir); - if( profile_name_edited == false ){ - var profile_name = get_domain_name( connection_info[0] ); - $('.create-new-profile').val(profile_name); - } - if( show_prefix_notice == true ) { - $('.prefix-notice.push').show(); - } - if( show_ssl_notice == true ) { - $('.ssl-notice').show(); - } - if( show_version_notice == true ) { - $('.different-plugin-version-notice').show(); - $('.step-two').hide(); - } - $('.directory-scope').html('remote'); - if( '0' == connection_data.write_permissions ) { - $('#create-backup').prop('checked',false); - $('#create-backup').attr('disabled','disabled'); - $('#create-backup-label').addClass('disabled'); - $('.backup-option-disabled').show(); - $('.upload-directory-location').html(connection_data.upload_dir_long); - } - } - else{ - $('.connection-status').show(); - $('.step-two').hide(); - } - } - else if( $('#savefile').is(':checked') ){ - $('.connection-status').hide(); - $('.step-two').show(); - $('.table-prefix').html(wpsdb_this_prefix); - if( profile_name_edited == false ){ - $('.create-new-profile').val(''); - } - $('.backup-options').hide(); - $('.keep-active-plugins').hide(); - if( false == wpsdb_write_permission ) { - $('.directory-permission-notice').show(); - $('.step-two').hide(); - } - } - $.wpsdb.do_action( 'move_connection_info_box' ); - } - - function change_replace_values(){ - if( $('#push').is(':checked') || $('#savefile').is(':checked') ){ - if( last_replace_switch == '' || last_replace_switch == 'pull' ){ - $('.replace-row').each(function(){ - var old_val = $('.old-replace-col input', this).val(); - $('.old-replace-col input', this).val( $('.replace-right-col input', this).val() ); - $('.replace-right-col input', this).val( old_val ); - }); - } - $('#select-tables').remove(); - $('.select-tables-wrap').prepend(push_select); - $('#select-post-types').remove(); - $('.select-post-types-wrap').prepend(push_post_type_select); - $('#select-backup').remove(); - $('.backup-tables-wrap').prepend(push_select_backup); - last_replace_switch = 'push'; - } - else if( $('#pull').is(':checked') ){ - if( last_replace_switch == '' || last_replace_switch == 'push' ){ - $('.replace-row').each(function(){ - var old_val = $('.old-replace-col input', this).val(); - $('.old-replace-col input', this).val( $('.replace-right-col input', this).val() ); - $('.replace-right-col input', this).val( old_val ); - }); - } - $('#select-tables').remove(); - $('.select-tables-wrap').prepend(pull_select); - $('#select-post-types').remove(); - $('.select-post-types-wrap').prepend(pull_post_type_select); - $('#select-backup').remove(); - $('.backup-tables-wrap').prepend(pull_select_backup); - last_replace_switch = 'pull'; - } - - } - - // hide second section if pull or push is selected with no connection established - if( ( $('#pull').is(':checked') || $('#push').is(':checked') ) && ! connection_established ){ - $('.step-two').hide(); - $('.connection-status').show(); - } - - // show / hide GUID helper description - $('.general-helper').click(function(){ - var $icon = $(this), - $bubble = $(this).next(); - - // Close any that are already open - $('.helper-message').not($bubble).hide(); - - var position = $icon.position(); - $bubble.css({ - 'left': (position.left + $icon.width() + 8) + 'px', - 'top': (position.top + $icon.height()/2 - 18) + 'px' - }); - - $bubble.toggle(); - }); - - $('body').click(function(){ - $('.helper-message').hide(); - }); - - $('.helper-message').click(function(e){ - e.stopPropagation(); - }); - - // migrate / settings tabs - $('.nav-tab').click(function(){ - $('.nav-tab').removeClass('nav-tab-active'); - $(this).addClass('nav-tab-active'); - $('.content-tab').hide(); - $('.' + $(this).attr('data-div-name')).show(); - - var hash = $(this).attr('data-div-name'); - hash = hash.replace('-tab',''); - window.location.hash = hash; - - if( $(this).hasClass('help') ) { - refresh_debug_log(); - } - }); - - // repeatable fields - $('body').delegate('.replace-add-row', 'click', function() { - $(this).parents('tr').after( $('.original-repeatable-field').clone().removeClass('original-repeatable-field') ); - }); - - // repeatable fields - $('body').delegate('.replace-remove-row', 'click', function() { - $(this).parents('tr').remove(); - if( $('.replace-row').length < 2 ){ - $('.no-replaces-message').show(); - } - }); - - $('.add-replace').click(function(){ - $('.replace-fields').append( $('.original-repeatable-field').clone().removeClass('original-repeatable-field') ); - $('.no-replaces-message').hide(); - }); - - // delete saved profiles - $('body').delegate('.save-migration-profile-wrap li', 'hover', function(event) { - if( event.type === 'mouseenter' ){ - $('.delete-profile', this).show(); - } - else{ - $('.delete-profile', this).hide(); - } - }); - - function validate_url( url ){ - return /^([a-z]([a-z]|\d|\+|-|\.)*):(\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?((\[(|(v[\da-f]{1,}\.(([a-z]|\d|-|\.|_|~)|[!\$&'\(\)\*\+,;=]|:)+))\])|((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=])*)(:\d*)?)(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*|(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)){0})(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(url); - } - - // check for hash in url (settings || migrate) switch tabs accordingly - if(window.location.hash) { - var hash = window.location.hash.substring(1); - switch_to_plugin_tab(hash); - } - - function switch_to_plugin_tab(hash) { - $('.nav-tab').removeClass('nav-tab-active'); - $('.nav-tab.' + hash).addClass('nav-tab-active'); - $('.content-tab').hide(); - $('.' + hash + '-tab').show(); - } - - // regenerates the saved secret key - $('.reset-api-key').click(function(){ - var answer = confirm('Any sites setup to use the current API key will no longer be able to connect. You will need to update those sites with the newly generated API key. Do you wish to continue?'); - - if( ! answer || doing_reset_api_key_ajax ){ - return; - } - - doing_reset_api_key_ajax = true; - $('.reset-api-key').after( '' ); - - $.ajax({ - url: ajaxurl, - type: 'POST', - dataType: 'text', - cache: false, - data: { - action: 'wpsdb_reset_api_key', - }, - error: function(jqXHR, textStatus, errorThrown){ - alert('An error occurred when trying to generate the API key. Please see the Help tab for details on how to request support. (#105)'); - $('.reset-api-key-ajax-spinner').remove(); - doing_reset_api_key_ajax = false; - }, - success: function(data){ - $('.reset-api-key-ajax-spinner').remove(); - doing_reset_api_key_ajax = false; - $('.connection-info').html(data); - } - }); - - }); - - var this_connection_info = $.parseJSON( wpsdb_connection_info ); - - // show / hide table select box when specific settings change - $('input.multiselect-toggle').change(function(){ - $(this).parents('.expandable-content').children('.select-wrap').toggle(); - }); - - $('.show-multiselect').each(function(){ - if( $(this).is(':checked') ){ - $(this).parents('.option-section').children('.header-expand-collapse').children('.expand-collapse-arrow').removeClass('collapsed'); - $(this).parents('.expandable-content').show(); - $(this).parents('.expandable-content').children('.select-wrap').toggle(); - } - }); - - $('input[name=backup_option]').change(function(){ - $('.backup-tables-wrap').hide(); - if( $(this).val() == 'backup_manual_select' ) { - $('.backup-tables-wrap').show(); - } - }); - - if( $('#backup-manual-select').is(':checked') ) { - $('.backup-tables-wrap').show(); - } - - // delete a profile from the migrate form area - $('body').delegate('.delete-profile', 'click', function(){ - var name = $(this).next().clone(); - $('input',name).remove(); - var name = $.trim($(name).html()); - var answer = confirm('You are removing the "' + name + '" migration profile. This cannot be undone. Do you wish to continue?'); - - if(!answer){ - return; - } - - $(this).parent().fadeOut(500); - - $.ajax({ - url: ajaxurl, - type: 'POST', - dataType: 'text', - cache: false, - data: { - action : 'wpsdb_delete_migration_profile', - profile_id : $(this).attr('data-profile-id') - }, - error: function(jqXHR, textStatus, errorThrown){ - alert('An error occurred when trying to delete the profile. Please see the Help tab for details on how to request support. (#106)'); - }, - success: function(data){ - if( data == '-1' ){ - alert('The selected migration profile could not be deleted because it was not found.\nPlease refresh this page to see an accurate list of the currently available migration profiles.'); - } - } - }); - - }); - - // deletes a profile from the main profile selection screen - $('.main-list-delete-profile-link').click(function(){ - var name = $(this).prev().html(); - var answer = confirm('You are removing the "' + name + '" migration profile. This cannot be undone. Do you wish to continue?'); - - if(!answer){ - return; - } - - $(this).parent().fadeOut(500); - - $.ajax({ - url: ajaxurl, - type: 'POST', - dataType: 'text', - cache: false, - data: { - action : 'wpsdb_delete_migration_profile', - profile_id : $(this).attr('data-profile-id') - }, - error: function(jqXHR, textStatus, errorThrown){ - alert('An error occurred when trying to delete the profile. Please see the Help tab for details on how to request support. (#107)'); - } - }); - - }); - - // warn the user when editing the connection info after a connection has been established - $('body').delegate('.temp-disabled', 'click', function() { - var answer = confirm('If you change the connection details, you will lose any replaces and table selections you have made below. Do you wish to continue?'); - - if( ! answer ){ - return; - } - else{ - $('.ssl-notice').hide(); - $('.different-plugin-version-notice').hide(); - $('.migrate-db-button').show(); - $('.temp-disabled').removeAttr('readonly'); - $('.temp-disabled').removeClass('temp-disabled'); - $('.connect-button').show(); - $('.step-two').hide(); - $('.connection-status').show().html('Please enter the connection information above to continue.'); - connection_established = false; - } - }); - - // ajax request for settings page when checking/unchecking setting radio buttons - $('.settings-tab input[type=checkbox]').change(function(){ - var checked = $(this).is(':checked'); - var setting = $(this).attr('id'); - - $(this).parent().append( '' ); - var $label = $(this).parent(); - - $.ajax({ - url: ajaxurl, - type: 'POST', - dataType: 'text', - cache: false, - data: { - action : 'wpsdb_save_setting', - checked : checked, - setting : setting - }, - error: function(jqXHR, textStatus, errorThrown){ - alert('An error occurred when trying to save the settings. Please try again. If the problem persists, please see the Help tab for details on how to request support. (#108)'); - $('.ajax-spinner').remove(); - }, - success: function(data){ - $('.ajax-spinner').remove(); - $($label).append('Saved'); - $('.ajax-success-msg').fadeOut(2000,function(){ - $(this).remove(); - }); - } - }); - - }); - - // disable form submissions - $('.migrate-form').submit(function(){ - return false; - }); - - // fire connection_box_changed when the connect button is pressed - $('.connect-button').click(function(event){ - event.preventDefault(); - $(this).blur(); - connection_box_changed(); - }); - - // send paste even to connection_box_changed() function - $('.pull-push-connection-info').bind('paste', function(e) { - var $this = this; - setTimeout(function () { - connection_box_changed(); - }, 0); - - }); - - $('body').delegate('.try-again','click',function(){ - connection_box_changed(); - }); - - $('body').delegate('.try-http','click',function(){ - var connection_info = $.trim( $('.pull-push-connection-info').val() ).split("\n"); - var new_url = connection_info[0].replace( 'https', 'http' ); - var new_contents = new_url + "\n" + connection_info[1]; - $('.pull-push-connection-info').val( new_contents ); - connection_box_changed(); - }); - - $('.create-new-profile').change(function(){ - profile_name_edited = true; - }); - - // fired when the connection info box changes (e.g. gets pasted into) - function connection_box_changed(data){ - var $this = $('.pull-push-connection-info'); - - if( doing_ajax || $($this).hasClass('temp-disabled') ){ - return; - } - - var data = $('.pull-push-connection-info').val(); - - var connection_info = $.trim(data).split("\n"); - var error = false; - var error_message = ''; - - if( connection_info == '' ){ - error = true; - error_message = 'The connection information appears to be missing, please enter it to continue.'; - } - - if( connection_info.length != 2 && ! error ){ - error = true; - error_message = 'The connection information appears to be incorrect, it should consist of two lines. The first being the remote server\'s URL and the second being the secret key.'; - } - - if( ! error && ! validate_url( connection_info[0] ) ){ - error = true; - error_message = 'The URL on the first line appears to be invalid, please check it and try again.'; - } - - if( ! error && connection_info[1].length != 32 ){ - error = true; - error_message = 'The secret key on the second line appears to be invalid. It should be a 32 character string that consists of letters, numbers and special characters only.'; - } - - if( ! error && connection_info[0] == this_connection_info[0] ){ - error = true; - error_message = 'It appears you\'ve entered the URL for this website, you need to provide the URL of the remote website instead.'; - } - - if( ! error && connection_info[1] == this_connection_info[1] ){ - error = true; - error_message = 'It appears you\'ve entered the secret key for this website, you need to provide the secret key for the remote website instead.'; - } - - if( error ){ - $('.connection-status').html( error_message ); - $('.connection-status').addClass( 'notification-message error-notice migration-error' ); - return; - } - - if( wpsdb_openssl_available == false ) { - connection_info[0] = connection_info[0].replace('https://','http://'); - var new_connection_info_contents = connection_info[0] + "\n" + connection_info[1]; - $('.pull-push-connection-info').val(new_connection_info_contents); - } - - show_prefix_notice = false; - doing_ajax = true; - disable_export_type_controls(); - - if( $('.basic-access-auth-wrapper').is(':visible') ) { - connection_info[0] = connection_info[0].replace( /\/\/(.*)@/, '//' ); - connection_info[0] = connection_info[0].replace( '//', '//' + encodeURIComponent( $.trim( $('.auth-username').val() ) ) + ':' + encodeURIComponent( $.trim( $('.auth-password').val() ) ) + '@' ); - var new_connection_info_contents = connection_info[0] + "\n" + connection_info[1]; - $('.pull-push-connection-info').val(new_connection_info_contents); - $('.basic-access-auth-wrapper').hide(); - } - - $('.step-two').hide(); - $('.ssl-notice').hide(); - $('.prefix-notice').hide(); - $('.connection-status').show(); - - $('.connection-status').html( 'Establishing connection to remote server, please wait' ); - $('.connection-status').removeClass( 'notification-message error-notice migration-error' ); - $('.connection-status').append( '' ); - - var intent = $('input[name=action]:checked').val(); - - profile_name_edited = false; - - $.ajax({ - url: ajaxurl, - type: 'POST', - dataType: 'json', - cache: false, - data: { - action: 'wpsdb_verify_connection_to_remote_site', - url: connection_info[0], - key: connection_info[1], - intent: intent, - }, - error: function(jqXHR, textStatus, errorThrown){ - $('.connection-status').html( 'A problem occurred when attempting to connect to the local server, please check the details and try again. (#100)' ); - $('.connection-status').addClass( 'notification-message error-notice migration-error' ); - $('.ajax-spinner').remove(); - doing_ajax = false; - enable_export_type_controls(); - }, - success: function(data){ - $('.ajax-spinner').remove(); - doing_ajax = false; - enable_export_type_controls(); - - if( typeof data.wpsdb_error != 'undefined' && data.wpsdb_error == 1 ){ - $('.connection-status').html( data.body ); - $('.connection-status').addClass( 'notification-message error-notice migration-error' ); - - if( data.body.indexOf( '401 Unauthorized' ) > -1 ) { - $('.basic-access-auth-wrapper').show(); - } - - return; - } - - var profile_name = get_domain_name( connection_info[0] ); - $('.create-new-profile').val(profile_name); - - $('.pull-push-connection-info').addClass('temp-disabled'); - $('.pull-push-connection-info').attr('readonly','readonly'); - $('.connect-button').hide(); - - $('.connection-status').hide(); - $('.step-two').show(); - - maybe_show_ssl_warning( connection_info[0], connection_info[1], data.scheme ); - maybe_show_version_warning( data.plugin_version, connection_info[0] ); - maybe_show_prefix_notice( data.prefix ); - - connection_established = true; - connection_data = data; - move_connection_info_box(); - - var table_select = document.createElement('select'); - $(table_select).attr({ - multiple: 'multiple', - name: 'select_tables[]', - id: 'select-tables', - class: 'multiselect' - }); - - $.each(connection_data.tables, function(index, value) { - $(table_select).append(''); - }); - - pull_select = table_select; - push_select_backup = $(table_select).clone(); - $(push_select_backup).attr({ - name : 'select_backup[]', - id : 'select-backup' - }); - - var post_type_select = document.createElement('select'); - $(post_type_select).attr({ - multiple : 'multiple', - name : 'select_post_types[]', - id : 'select-post-types', - class : 'multiselect' - }); - - $.each(connection_data.post_types, function(index, value) { - $(post_type_select).append(''); - }); - - pull_post_type_select = post_type_select; - - if( $('#pull').is(':checked') ){ - $('#new-url').val( remove_protocol( wpsdb_this_url ) ); - $('#new-path').val( wpsdb_this_path ); - if( wpsdb_is_multisite == true ) { - $('#new-domain').val( wpsdb_this_domain ); - } - $('#old-url').val( remove_protocol( data.url ) ); - $('#old-path').val( data.path ); - $('#select-tables').remove(); - $('.select-tables-wrap').prepend(pull_select); - $('#select-post-types').remove(); - $('.select-post-types-wrap').prepend(pull_post_type_select); - $('.table-prefix').html(data.prefix); - $('.uploads-dir').html(wpsdb_this_uploads_dir); - } - else{ - $('#select-backup').remove(); - $('.backup-tables-wrap').prepend(push_select_backup); - $('#new-url').val( remove_protocol( data.url ) ); - $('#new-path').val( data.path ); - } - - $.wpsdb.do_action( 'verify_connection_to_remote_site', connection_data ); - } - - }); - - } - - }); - + var connection_established = false; + var last_replace_switch = ''; + var doing_ajax = false; + var doing_reset_api_key_ajax = false; + var doing_save_profile = false; + var profile_name_edited = false; + var show_prefix_notice = false; + var show_ssl_notice = false; + var show_version_notice = false; + var migration_completed = false; + var currently_migrating = false; + var dump_filename = ''; + var dump_url = ''; + var migration_intent; + var remote_site; + var secret_key; + var form_data; + var stage; + var elapsed_interval; + var completed_msg; + var tables_to_migrate = ''; + + var admin_url = ajaxurl.replace('/admin-ajax.php', ''), + spinner_url = admin_url + '/images/wpspin_light'; + + if (window.devicePixelRatio >= 2) { + spinner_url += '-2x'; + } + + spinner_url += '.gif'; + + window.onbeforeunload = function(e) { + if (currently_migrating) { + e = e || window.event; + + // For IE and Firefox prior to version 4 + if (e) { + e.returnValue = 'Sure?'; + } + + // For Safari + return 'Sure?'; + } + }; + + function pad(n, width, z) { + z = z || '0'; + n = n + ''; + return n.length >= width ? n : new Array(width - n.length + 1).join(z) + + n; + } + + function is_int(n) { + n = parseInt(n); + return typeof n === 'number' && n % 1 == 0; + } + + function setup_counter() { + var c = 0, + counter_display = $('.timer'), + label = 'Time Elapsed: '; + + function display_count() { + hours = parseInt(c / 3600) % 24; + minutes = parseInt(c / 60) % 60; + seconds = c % 60; + var display = label + pad(hours, 2, 0) + ':' + pad(minutes, 2, 0) + ':' + + pad(seconds, 2, 0); + counter_display.html(display); + } + + function count() { + c = c + 1; + display_count(); + } + + elapsed_interval = setInterval(count, 1000); + } + + function get_intersect(arr1, arr2) { + var r = [], + o = {}, l = arr2.length, + i, v; + for (i = 0; i < l; i++) { + o[arr2[i]] = true; + } + l = arr1.length; + for (i = 0; i < l; i++) { + v = arr1[i]; + if (v in o) { + r.push(v); + } + } + return r; + } + + function get_query_var(name) { + name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]"); + var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"), + results = regex.exec(location.search); + return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, + " ")); + } + + function maybe_show_ssl_warning(url, key, remote_scheme) { + var scheme = url.substr(0, url.indexOf(':')); + if (remote_scheme != scheme && url.indexOf('https') != -1) { + $('.ssl-notice').show(); + show_ssl_notice = true; + url = url.replace('https', 'http'); + $('.pull-push-connection-info').val(url + "\n" + key); + return; + } + show_ssl_notice = false; + return; + } + + function maybe_show_version_warning(plugin_version, url) { + if (typeof plugin_version != 'undefined' && plugin_version != + wpsdb_plugin_version) { + $('.different-plugin-version-notice').show(); + $('.remote-version').html(plugin_version); + $('.remote-location').html(url); + $('.step-two').hide(); + show_version_notice = true; + } + } + + function maybe_show_prefix_notice(prefix) { + if (prefix != wpsdb_this_prefix) { + $('.remote-prefix').html(prefix); + show_prefix_notice = true; + if ($('#pull').is(':checked')) { + $('.prefix-notice.pull').show(); + } else { + $('.prefix-notice.push').show(); + } + } + } + + function get_domain_name(url) { + var temp_url = url; + var domain = temp_url.replace(/\/\/(.*)@/, '//').replace('http://', '').replace( + 'https://', '').replace('www.', '').split(/[/?#]/)[0]; + return domain; + } + + function get_default_profile_name(url, intent, ing_suffix) { + var domain = get_domain_name(url); + var action = intent; + action = action.charAt(0).toUpperCase() + action.slice(1); + if (ing_suffix) { + action += 'ing'; + } + var preposition = 'to'; + if (intent == 'pull') { + preposition = 'from'; + } + + return profile_name = action + ' ' + preposition + ' ' + domain; + } + + function remove_protocol(url) { + return url.replace(/^https?:/i, ""); + } + + $(document).ready(function() { + if (navigator.userAgent.indexOf('MSIE') > 0 || navigator.userAgent.indexOf( + 'Trident') > 0) { + $('.ie-warning').show(); + } + + $('.slider').slider({ + range: 'min', + value: wpsdb_max_request / 1024, + min: 512, + max: wpsdb_bottleneck / 1024, + step: 512, + slide: function(event, ui) { + $('.amount').html(wpsdb_add_commas(ui.value) + ' kB'); + }, + change: function(event, ui) { + $('.amount').after(''); + $('.slider').slider('disable'); + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'json', + cache: false, + data: { + action: 'wpsdb_update_max_request_size', + max_request_size: parseInt(ui.value), + }, + error: function(jqXHR, textStatus, errorThrown) { + $('.slider').slider('enable'); + $('.slider-spinner').remove(); + alert( + 'A problem occurred when trying to change the maximum request size, please try again.' + ); + }, + success: function(data) { + $('.slider').slider('enable'); + $('.slider-spinner').remove(); + $('.slider-success-msg').show(); + $('.slider-success-msg').fadeOut(2000, function() { + $(this).hide(); + }); + } + }); + } + }); + $('.amount').html(wpsdb_add_commas($('.slider').slider('value')) + + ' kB'); + + var progress_content_original = $('.progress-content').clone(); + $('.progress-content').remove(); + + var this_tables = $.parseJSON(wpsdb_this_tables); + var this_prefixed_tables = $.parseJSON(wpsdb_this_prefixed_tables); + var push_select = $('#select-tables').clone(); + var pull_select = $('#select-tables').clone(); + var push_post_type_select = $('#select-post-types').clone(); + var pull_post_type_select = $('#select-post-types').clone(); + var push_select_backup = $('#select-backup').clone(); + var pull_select_backup = $('#select-backup').clone(); + + $('.help-tab .video').each(function() { + var $container = $(this), + $viewer = $('.video-viewer'); + + $('a', this).click(function() { + $viewer.attr('src', '//www.youtube.com/embed/' + $container.data( + 'video-id') + '?autoplay=1'); + $viewer.show(); + var offset = $viewer.offset(); + $(window).scrollTop(offset.top - 50); + return false; + }); + }); + + $('.backup-options').show(); + $('.keep-active-plugins').show(); + if ($('#savefile').is(':checked')) { + $('.backup-options').hide(); + $('.keep-active-plugins').hide(); + } + + function disable_export_type_controls() { + $('.option-group').each(function(index) { + $('input', this).attr('disabled', 'disabled'); + $('label', this).css('cursor', 'default'); + }); + } + + function enable_export_type_controls() { + $('.option-group').each(function(index) { + $('input', this).removeAttr('disabled'); + $('label', this).css('cursor', 'pointer'); + }); + } + + // automatically validate connnection info if we're loading a saved profile + establish_remote_connection_from_saved_profile(); + + function establish_remote_connection_from_saved_profile() { + var action = $('input[name=action]:checked').val(); + var connection_info = $.trim($('.pull-push-connection-info').val()).split( + "\n"); + if (typeof wpsdb_default_profile == 'undefined' || + wpsdb_default_profile == true || action == 'savefile' || doing_ajax + ) { + return; + } + + last_replace_switch = action; + + doing_ajax = true; + disable_export_type_controls(); + + $('.connection-status').html( + 'Establishing connection to remote server, please wait'); + $('.connection-status').removeClass( + 'notification-message error-notice migration-error'); + $('.connection-status').append(''); + + var intent = $('input[name=action]:checked').val(); + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'json', + cache: false, + data: { + action: 'wpsdb_verify_connection_to_remote_site', + url: connection_info[0], + key: connection_info[1], + intent: intent, + }, + error: function(jqXHR, textStatus, errorThrown) { + $('.connection-status').html( + 'A problem occurred when attempting to connect to the local server, please check the details and try again. (#102)' + ); + $('.connection-status').addClass( + 'notification-message error-notice migration-error'); + $('.ajax-spinner').remove(); + doing_ajax = false; + enable_export_type_controls(); + }, + success: function(data) { + $('.ajax-spinner').remove(); + doing_ajax = false; + enable_export_type_controls(); + + if (typeof data.wpsdb_error != 'undefined' && data.wpsdb_error == + 1) { + $('.connection-status').html(data.body); + $('.connection-status').addClass( + 'notification-message error-notice migration-error'); + + if (data.body.indexOf('401 Unauthorized') > -1) { + $('.basic-access-auth-wrapper').show(); + } + return; + } + + maybe_show_ssl_warning(connection_info[0], connection_info[1], + data.scheme); + maybe_show_version_warning(data.plugin_version, connection_info[ + 0]); + maybe_show_prefix_notice(data.prefix); + + $('.pull-push-connection-info').addClass('temp-disabled'); + $('.pull-push-connection-info').attr('readonly', 'readonly'); + $('.connect-button').hide(); + + $('.connection-status').hide(); + $('.step-two').show(); + connection_established = true; + connection_data = data; + move_connection_info_box(); + + var loaded_tables = ''; + if (wpsdb_default_profile == false && typeof wpsdb_loaded_tables != + 'undefined') { + loaded_tables = $.parseJSON(wpsdb_loaded_tables); + } + + var table_select = document.createElement('select'); + $(table_select).attr({ + multiple: 'multiple', + name: 'select_tables[]', + id: 'select-tables', + class: 'multiselect' + }); + + $.each(connection_data.tables, function(index, value) { + var selected = $.inArray(value, loaded_tables); + if (selected != -1) { + selected = ' selected="selected" '; + } else { + selected = ' '; + } + $(table_select).append('' + value + ' (' + connection_data.table_sizes_hr[ + value] + ')'); + }); + + pull_select = table_select; + + var loaded_post_prefixes = ''; + if (wpsdb_default_profile == false && typeof wpsdb_loaded_post_types != + 'undefined') { + loaded_post_prefixes = $.parseJSON(wpsdb_loaded_post_types); + } + + var post_type_select = document.createElement('select'); + $(post_type_select).attr({ + multiple: 'multiple', + name: 'select_post_types[]', + id: 'select-post-types', + class: 'multiselect' + }); + + $.each(connection_data.post_types, function(index, value) { + var selected = $.inArray(value, loaded_post_prefixes); + if (selected != -1 || (wpsdb_convert_exclude_revisions == + true && value != 'revision')) { + selected = ' selected="selected" '; + } else { + selected = ' '; + } + $(post_type_select).append('' + value + ''); + }); + + pull_post_type_select = post_type_select; + + var loaded_tables_backup = ''; + if (wpsdb_default_profile == false && typeof wpsdb_loaded_tables_backup != + 'undefined') { + loaded_tables_backup = $.parseJSON(wpsdb_loaded_tables_backup); + } + + var table_select_backup = document.createElement('select'); + $(table_select_backup).attr({ + multiple: 'multiple', + name: 'select_backup[]', + id: 'select-backup', + class: 'multiselect' + }); + + $.each(connection_data.tables, function(index, value) { + var selected = $.inArray(value, loaded_tables_backup); + if (selected != -1) { + selected = ' selected="selected" '; + } else { + selected = ' '; + } + $(table_select_backup).append('' + value + ' (' + connection_data + .table_sizes_hr[value] + ')'); + }); + + push_select_backup = table_select_backup; + + if ($('#pull').is(':checked')) { + $('#select-tables').remove(); + $('.select-tables-wrap').prepend(pull_select); + $('#select-post-types').remove(); + $('.select-post-types-wrap').prepend(pull_post_type_select); + $('#select-backup').remove(); + $('.backup-tables-wrap').prepend(pull_select_backup); + $('.table-prefix').html(data.prefix); + $('.uploads-dir').html(wpsdb_this_uploads_dir); + } else { + $('#select-backup').remove(); + $('.backup-tables-wrap').prepend(push_select_backup); + } + + $.wpsdb.do_action('verify_connection_to_remote_site', + connection_data); + + } + + }); + + } + + // add to tags which act as JS event buttons, will not jump page to top + // and will deselect the button + $('.js-action-link').click(function(event) { + $(this).blur(); + return false; + }); + + // clears the debug log + $('.clear-log').click(function() { + $('.debug-log-textarea').val(''); + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action: 'wpsdb_clear_log', + }, + error: function(jqXHR, textStatus, errorThrown) { + alert( + 'An error occurred when trying to clear the debug log. Please contact support. (#132)' + ); + }, + success: function(data) {} + }); + }); + + // updates the debug log when the user switches to the help tab + function refresh_debug_log() { + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action: 'wpsdb_get_log', + }, + error: function(jqXHR, textStatus, errorThrown) { + alert( + 'An error occurred when trying to update the debug log. Please contact support. (#133)' + ); + }, + success: function(data) { + $('.debug-log-textarea').val(data); + } + }); + } + + // select all tables + $('.multiselect-select-all').click(function() { + var multiselect = $(this).parents('.select-wrap').children( + '.multiselect'); + $(multiselect).focus(); + $('option', multiselect).attr('selected', 1); + }); + + // deselect all tables + $('.multiselect-deselect-all').click(function() { + var multiselect = $(this).parents('.select-wrap').children( + '.multiselect'); + $(multiselect).focus(); + $('option', multiselect).removeAttr('selected'); + }); + + // invert table selection + $('.multiselect-invert-selection').click(function() { + var multiselect = $(this).parents('.select-wrap').children( + '.multiselect'); + $(multiselect).focus(); + $('option', multiselect).each(function() { + $(this).attr('selected', !$(this).attr('selected')); + }); + }); + + // on option select hide all "advanced" option divs and show the correct div + // for the option selected + $('.option-group input[type=radio]').change(function() { + group = $(this).closest('.option-group'); + $('ul', group).hide(); + parent = $(this).closest('li'); + $('ul', parent).show(); + }); + + // on page load, expand hidden divs for selected options (browser form + // cache) + $('.option-group').each(function() { + $('.option-group input[type=radio]').each(function() { + if ($(this).is(':checked')) { + parent = $(this).closest('li'); + $('ul', parent).show(); + } + }); + }); + + // expand and collapse content on click + $('.header-expand-collapse').click(function() { + if ($('.expand-collapse-arrow', this).hasClass('collapsed')) { + $('.expand-collapse-arrow', this).removeClass('collapsed'); + $(this).next().show(); + } else { + $('.expand-collapse-arrow', this).addClass('collapsed'); + $(this).next().hide(); + } + }); + + $('.checkbox-label input[type=checkbox]').change(function() { + if ($(this).is(':checked')) { + $(this).parent().next().show(); + } else { + $(this).parent().next().hide(); + } + }); + + // special expand and collapse content on click for save migration profile + $('#save-migration-profile').change(function() { + if ($(this).is(':checked')) { + $('.save-settings-button').show(); + $('.migrate-db .button-primary').val('Migrate DB & Save'); + } else { + $('.save-settings-button').hide(); + $('.migrate-db .button-primary').val('Migrate DB'); + } + }); + + if ($('#save-migration-profile').is(':checked')) { + $('.save-settings-button').show(); + $('.migrate-db .button-primary').val('Migrate DB & Save'); + }; + + $('.checkbox-label input[type=checkbox]').each(function() { + if ($(this).is(':checked')) { + $(this).parent().next().show(); + } + }); + + // AJAX migrate button + $('.migrate-db-button').click(function(event) { + $(this).blur(); + event.preventDefault(); + + // check that they've selected some tables to migrate + if ($('#migrate-selected').is(':checked') && $('#select-tables').val() == + null) { + alert('Please select at least one table to migrate.'); + return; + } + + // also save profile + if ($('#save-migration-profile').is(':checked')) { + + if ($.trim($('.create-new-profile').val()) == '' && $( + '#create_new').is(':checked')) { + alert('Please enter a name for your migration profile.'); + $('.create-new-profile').focus(); + return; + } + + var create_new_profile = false; + + if ($('#create_new').is(':checked')) { + create_new_profile = true; + } + var profile_name = $('.create-new-profile').val(); + + profile = $('#migrate-form').serialize(); + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action: 'wpsdb_save_profile', + profile: profile, + }, + error: function(jqXHR, textStatus, errorThrown) { + alert( + 'An error occurred when attempting to save the migration profile. Please see the Help tab for details on how to request support. (#118)' + ); + }, + success: function(data) { + if (create_new_profile) { + var new_li = + '
  • '; + $('#create_new').parents('li').before(new_li); + $('#profile-' + data).attr('checked', 'checked'); + $('.create-new-profile').val(''); + } + } + }); + } + + form_data = $('#migrate-form').serialize(); + + var doc_height = $(document).height(); + + $('body').append('
    '); + + $('#overlay') + .height(doc_height) + .css({ + 'position': 'fixed', + 'top': 0, + 'left': 0, + 'width': '100%', + 'z-index': 99999, + 'display': 'none', + }); + + $progress_content = progress_content_original.clone(); + migration_intent = $('input[name=action]:checked').val(); + + stage = 'backup'; + + if (migration_intent == 'savefile') { + stage = 'migrate'; + } + + if ($('#create-backup').is(':checked') == false) { + stage = 'migrate'; + } + + var table_intent = $('input[name=table_migrate_option]:checked').val(); + var connection_info = $.trim($('.pull-push-connection-info').val()) + .split("\n"); + var table_rows = ''; + + remote_site = connection_info[0]; + secret_key = connection_info[1]; + + var static_migration_label = ''; + + $('#overlay').after($progress_content); + + completed_msg = 'Exporting complete'; + + if (migration_intent == 'savefile') { + static_migration_label = 'Exporting, please wait...'; + } else { + static_migration_label = get_default_profile_name(remote_site, + migration_intent, true) + ', please wait...'; + completed_msg = get_default_profile_name(remote_site, + migration_intent, true) + ' complete'; + } + + $('.progress-title').html(static_migration_label); + + $('#overlay').show(); + backup_option = $('input[name=backup_option]:checked').val(); + table_option = $('input[name=table_migrate_option]:checked').val(); + + if (stage == 'backup') { + if (table_option == 'migrate_only_with_prefix' && backup_option == + 'backup_selected') { + backup_option = 'backup_only_with_prefix'; + } + if (migration_intent == 'push') { + table_rows = connection_data.table_rows; + if (backup_option == 'backup_only_with_prefix') { + tables_to_migrate = connection_data.prefixed_tables; + } else if (backup_option == 'backup_selected') { + selected_tables = $('#select-tables').val(); + tables_to_migrate = get_intersect(selected_tables, + connection_data.tables); + } else if (backup_option == 'backup_manual_select') { + tables_to_migrate = $('#select-backup').val(); + } + } else { + table_rows = $.parseJSON(wpsdb_this_table_rows); + if (backup_option == 'backup_only_with_prefix') { + tables_to_migrate = $.parseJSON(wpsdb_this_prefixed_tables); + } else if (backup_option == 'backup_selected') { + selected_tables = $('#select-tables').val(); + local_tables = $.parseJSON(wpsdb_this_tables); + tables_to_migrate = get_intersect(selected_tables, + local_tables); + } else if (backup_option == 'backup_manual_select') { + tables_to_migrate = $('#select-backup').val(); + } + } + } else { + if (table_intent == 'migrate_select') { // user has elected to migrate only certain tables + // grab tables as per what the user has selected from the multiselect box + tables_to_migrate = $('#select-tables').val(); + // user is pushing or exporting + if (migration_intent == 'push' || migration_intent == + 'savefile') { + // default value, assuming we're not backing up + table_rows = $.parseJSON(wpsdb_this_table_rows); + } else { + table_rows = connection_data.table_rows; + } + } else { + if (migration_intent == 'push' || migration_intent == + 'savefile') { + tables_to_migrate = this_prefixed_tables; + table_rows = $.parseJSON(wpsdb_this_table_rows); + } else { + tables_to_migrate = connection_data.prefixed_tables; + table_rows = connection_data.table_rows; + } + } + } + + function decide_tables_to_display_rows(tables_to_migrate, table_rows) { + var total_size = 0; + $.each(tables_to_migrate, function(index, value) { + total_size += parseInt(table_rows[value]); + }); + + var last_element = ''; + $.each(tables_to_migrate, function(index, value) { + var percent = table_rows[value] / total_size * 100; + var percent_rounded = Math.round(percent * 1000) / 1000; + $('.progress-tables').append('
    ' + value + + '
    '); + $('.progress-tables-hover-boxes').append( + '
    '); + var label = $('.progress-tables .progress-chunk:last span'); + last_element = value; + }); + + $('.progress-chunk').each(function(index) { + if ($(this).width() < 1 && tables_to_migrate[index] != + last_element) { + $(this).hide(); + $('.progress-chunk-hover[data-table=' + tables_to_migrate[ + index] + ']').hide(); + table_rows[last_element] = Number(table_rows[last_element]); + table_rows[last_element] += Number(table_rows[ + tables_to_migrate[index]]); + table_rows[tables_to_migrate[index]] = 0; + } + var element = this; + setTimeout(function() { + hide_overflowing_elements(element); + }, 0); + + function hide_overflowing_elements(element) { + if ($('span', element).innerWidth() > $(element).width()) { + $('span', element).hide(); + } + } + }); + + percent_rounded = 0; + if (table_rows[last_element] != 0) { + var percent = table_rows[last_element] / total_size * 100; + var percent_rounded = Math.round(percent * 1000) / 1000; + } + $('.progress-tables .progress-chunk:last').css('width', + percent_rounded + '%'); + $('.progress-chunk-hover:last').css('width', percent_rounded + + '%'); + + var return_vals = [table_rows, total_size]; + return return_vals; + + } + + table_details = decide_tables_to_display_rows(tables_to_migrate, + table_rows); + table_rows = table_details[0]; + total_size = table_details[1]; + + $('.progress-title').after('' + ); + + var height = $('.progress-content').outerHeight(); + $('.progress-content').css('top', '-' + height + 'px').show().animate({ + 'top': '0px' + }); + + setup_counter(); + currently_migrating = true; + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'json', + cache: false, + data: { + action: 'wpsdb_initiate_migration', + intent: migration_intent, + url: remote_site, + key: secret_key, + form_data: form_data, + stage: stage, + }, + error: function(jqXHR, textStatus, errorThrown) { + $('.progress-title').html('Migration failed'); + $('.progress-text').html( + 'A problem occurred when attempting to connect to the local server, please check the details and try again. (#112)' + ); + $('.progress-text').addClass('migration-error'); + console.log(jqXHR); + console.log(textStatus); + console.log(errorThrown); + migration_error = true; + migration_complete_events(); + return; + }, + success: function(data) { + if (typeof data.wpsdb_error != 'undefined' && data.wpsdb_error == + 1) { + migration_complete_events(); + $('.progress-title').html('Migration failed'); + $('.progress-text').addClass('migration-error'); + $('.progress-text').html(data.body); + return; + } + + dump_url = data.dump_url; + dump_filename = data.dump_filename; + + var i = 0; + var progress_size = 0; + var overall_percent = 0; + var table_progress = 0; + var temp_progress = 0; + var last_progress = 0; + var overall_table_progress = 0; + + function migrate_table_recursive(current_row, primary_keys) { + if (i >= tables_to_migrate.length) { + if (stage == 'backup') { + stage = 'migrate'; + i = 0; + progress_size = 0; + $('.progress-bar').width('0px'); + + if (table_intent == 'migrate_select') { + tables_to_migrate = $('#select-tables').val(); + if (migration_intent == 'push' || migration_intent == + 'savefile') { + table_rows = $.parseJSON(wpsdb_this_table_rows); + } else { + table_rows = connection_data.table_rows; + } + } else { + if (migration_intent == 'push' || migration_intent == + 'savefile') { + tables_to_migrate = this_prefixed_tables; + table_rows = $.parseJSON(wpsdb_this_table_rows); + } else { + tables_to_migrate = connection_data.prefixed_tables; + table_rows = connection_data.table_rows; + } + } + + $('.progress-tables').empty(); + $('.progress-tables-hover-boxes').empty(); + + table_details = decide_tables_to_display_rows( + tables_to_migrate, table_rows); + table_rows = table_details[0]; + total_size = table_details[1]; + + } else { + hooks = $.wpsdb.apply_filters( + 'wpsdb_before_migration_complete_hooks', hooks); + hooks.push('migration_complete'); + hooks = $.wpsdb.apply_filters( + 'wpsdb_after_migration_complete_hooks', hooks); + hooks.push('migration_complete_events'); + wpsdb_call_next_hook(); + return; + } + } + + if (stage == 'backup') { + $('.progress-text').html(overall_percent + + '% - Backing up "' + tables_to_migrate[i] + '"'); + } else { + $('.progress-text').html(overall_percent + + '% - Migrating "' + tables_to_migrate[i] + '"'); + } + + last_table = 0; + if (i == (tables_to_migrate.length - 1)) { + last_table = 1; + } + + gzip = 0; + if (migration_intent != 'savefile' && parseInt( + connection_data.gzip) == 1) { + gzip = 1; + } + + var request_data = { + action: 'wpsdb_migrate_table', + intent: migration_intent, + url: remote_site, + key: secret_key, + table: tables_to_migrate[i], + form_data: form_data, + stage: stage, + current_row: current_row, + dump_filename: dump_filename, + last_table: last_table, + primary_keys: primary_keys, + gzip: gzip, + }; + + if (migration_intent != 'savefile') { + request_data.bottleneck = connection_data.bottleneck; + request_data.prefix = connection_data.prefix; + } + + if (connection_data && connection_data.path_current_site && + connection_data.domain) { + request_data.path_current_site = connection_data.path_current_site; + request_data.domain_current_site = connection_data.domain; + } + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + timeout: 0, + data: request_data, + error: function(jqXHR, textStatus, errorThrown) { + $('.progress-title').html('Migration failed'); + $('.progress-text').html( + 'A problem occurred when processing the ' + + tables_to_migrate[i] + ' table. (#113)'); + $('.progress-text').append('

    Status: ' + + jqXHR.status + ' ' + jqXHR.statusText + + '

    Response:
    ' + jqXHR.responseText); + $('.progress-text').addClass('migration-error'); + console.log(jqXHR); + console.log(textStatus); + console.log(errorThrown); + migration_error = true; + migration_complete_events(); + return; + }, + success: function(data) { + data = $.trim(data); + row_information = wpsdb_parse_json(data); + if (false == row_information || null == + row_information) { + $('.progress-title').html('Migration failed'); + if ('' == data || null == data) { + $('.progress-text').html( + 'A problem occurred when processing the ' + + tables_to_migrate[i] + + ' table. We were expecting a response in JSON format but instead received an empty response.' + ); + } else { + $('.progress-text').html(data); + } + $('.progress-text').addClass('migration-error'); + migration_error = true; + migration_complete_events(); + return; + } + + if (row_information.current_row == '-1') { + progress_size -= overall_table_progress; + overall_table_progress = 0; + last_progress = 0; + progress_size += parseInt(table_rows[ + tables_to_migrate[i]]); + i++; + row_information.current_row = ''; + row_information.primary_keys = ''; + } else { + temp_progress = parseInt(row_information.current_row); + table_progress = temp_progress - last_progress; + last_progress = temp_progress; + progress_size += table_progress; + overall_table_progress += table_progress; + } + var percent = 100 * progress_size / total_size; + $('.progress-bar').width(percent + '%'); + overall_percent = Math.floor(percent); + migrate_table_recursive(row_information.current_row, + row_information.primary_keys); + } + }); + } + migrate_table_recursive('-1', ''); + } + }); // end ajax + }); + + migration_complete_events = function() { + if (false == migration_error) { + if (non_fatal_errors == '') { + if ('savefile' != migration_intent && true == $('#save_computer') + .is(':checked')) { + $('.progress-text').css('visibility', 'hidden'); + } + $('.progress-title').html(completed_msg).append( + '
    '); + } else { + $('.progress-text').html(non_fatal_errors); + $('.progress-text').addClass('migration-error'); + $('.progress-title').html('Migration completed with some errors'); + } + $('.progress-bar-wrapper').hide(); + } + + // reset migration variables so consecutive migrations work correctly + hooks = []; + call_stack = []; + migration_error = false; + currently_migrating = false; + migration_completed = true; + non_fatal_errors = ''; + + $('.progress-label').remove(); + $('.migration-progress-ajax-spinner').remove(); + $('.close-progress-content').show(); + $('#overlay').css('cursor', 'pointer'); + clearInterval(elapsed_interval); + } + + migration_complete = function() { + if (migration_intent == 'savefile') { + currently_migrating = false; + var migrate_complete_text = 'Migration complete'; + if ($('#save_computer').is(':checked')) { + var url = wpsdb_this_download_url + encodeURIComponent( + dump_filename); + if ($('#gzip_file').is(':checked')) { + url += '&gzip=1'; + } + window.location = url; + } else { + migrate_complete_text = + 'Migration complete, your backup is located at:
    ' + dump_url + '.'; + } + + if (migration_error == false) { + $('.progress-text').html(migrate_complete_text); + migration_complete_events(); + $('.progress-title').html(completed_msg); + } + + } else { // rename temp tables, delete old tables + $('.progress-text').html('Finalizing migration'); + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action: 'wpsdb_finalize_migration', + intent: migration_intent, + url: remote_site, + key: secret_key, + form_data: form_data, + prefix: connection_data.prefix, + temp_prefix: connection_data.temp_prefix, + tables: tables_to_migrate.join(','), + }, + error: function(jqXHR, textStatus, errorThrown) { + $('.progress-title').html('Migration failed'); + $('.progress-text').html( + 'A problem occurred when finalizing the backup. (#132)'); + $('.progress-text').addClass('migration-error'); + alert(jqXHR + ' : ' + textStatus + ' : ' + errorThrown); + migration_error = true; + migration_complete_events(); + return; + }, + success: function(data) { + if ($.trim(data) != '') { + $('.progress-title').html('Migration failed'); + $('.progress-text').html(data); + $('.progress-text').addClass('migration-error'); + migration_error = true; + migration_complete_events(); + return; + } + wpsdb_call_next_hook(); + } + }); + } + } + + // close progress pop up once migration is completed + $('body').delegate('.close-progress-content-button', 'click', function( + e) { + hide_overlay(); + }); + + $('body').delegate('#overlay', 'click', function() { + if (migration_completed == true) { + hide_overlay(); + } + }); + + function hide_overlay() { + var height = $('.progress-content').outerHeight(); + $('.progress-content').animate({ + 'top': '-' + height + 'px' + }, 400, 'swing', function() { + $('#overlay').remove(); + $('.progress-content').remove(); + }); + migration_completed = false; + } + + // AJAX save button profile + $('.save-settings-button').click(function(event) { + var profile; + $(this).blur(); + event.preventDefault(); + + if (doing_save_profile) { + return; + } + + // check that they've selected some tables to migrate + if ($('#migrate-selected').is(':checked') && $('#select-tables').val() == + null) { + alert('Please select at least one table to migrate.'); + return; + } + + if ($.trim($('.create-new-profile').val()) == '' && $('#create_new') + .is(':checked')) { + alert('Please enter a name for your migration profile.'); + $('.create-new-profile').focus(); + return; + } + + var create_new_profile = false; + + if ($('#create_new').is(':checked')) { + create_new_profile = true; + } + var profile_name = $('.create-new-profile').val(); + + doing_save_profile = true; + profile = $('#migrate-form').serialize(); + + $('.save-settings-button').after(''); + $(this).attr('disabled', 'disabled'); + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action: 'wpsdb_save_profile', + profile: profile, + }, + error: function(jqXHR, textStatus, errorThrown) { + alert( + 'An error occurred when attempting to save the migration profile. Please see the Help tab for details on how to request support. (#104)' + ); + $('.save-settings-button').removeAttr('disabled'); + $('.save-profile-ajax-spinner').remove(); + $('.save-settings-button').after( + 'Saved'); + $('.ajax-success-msg').fadeOut(2000, function() { + $(this).remove(); + }); + doing_save_profile = false; + }, + success: function(data) { + $('.save-settings-button').removeAttr('disabled'); + $('.save-profile-ajax-spinner').remove(); + $('.save-settings-button').after( + 'Saved'); + $('.ajax-success-msg').fadeOut(2000, function() { + $(this).remove(); + }); + doing_save_profile = false; + $('.create-new-profile').val(''); + + if (create_new_profile) { + var new_li = + '
  • '; + $('#create_new').parents('li').before(new_li); + $('#profile-' + data).attr('checked', 'checked'); + } + + } + }); + + }); + + // progress label updating + $('body').delegate('.progress-chunk-hover', 'mousemove', function(e) { + mX = e.pageX; + offset = $('.progress-bar-wrapper').offset(); + label_offset = $('.progress-label').outerWidth() / 2; + mX = (mX - offset.left) - label_offset; + $('.progress-label').css('left', mX + 'px'); + $('.progress-label').html($(this).attr('data-table')); + }); + + // show / hide progress lavel on hover + $('body').delegate('.progress-chunk-hover', 'hover', function(event) { + if (event.type === 'mouseenter') { + $('.progress-label').addClass('label-visible'); + } else { + $('.progress-label').removeClass('label-visible'); + } + }); + + // move around textarea depending on whether or not the push/pull options are selected + connection_info_box = $('.connection-info-wrapper'); + move_connection_info_box(); + + $('.migrate-selection.option-group input[type=radio]').change(function() { + move_connection_info_box(); + if (connection_established) { + change_replace_values(); + } + }); + + // save file (export) / import / push / pull special conditions + function move_connection_info_box() { + $('.import-button').hide(); + $('.connection-status').hide(); + $('.prefix-notice').hide(); + $('.ssl-notice').hide(); + $('.different-plugin-version-notice').hide(); + $('.step-two').show(); + $('.backup-options').show(); + $('.keep-active-plugins').show(); + $('.directory-permission-notice').hide(); + $('#create-backup').removeAttr('disabled'); + $('#create-backup-label').removeClass('disabled'); + $('.backup-option-disabled').hide(); + var connection_info = $.trim($('.pull-push-connection-info').val()).split( + "\n"); + if ($('#pull').is(':checked')) { + $('.pull-list li').append(connection_info_box); + connection_info_box.show(); + if (connection_established) { + $('.connection-status').hide(); + $('.step-two').show(); + $('.table-prefix').html(connection_data.prefix); + $('.uploads-dir').html(wpsdb_this_uploads_dir); + if (profile_name_edited == false) { + var profile_name = get_domain_name(connection_info[0]); + $('.create-new-profile').val(profile_name); + } + if (show_prefix_notice == true) { + $('.prefix-notice.pull').show(); + } + if (show_ssl_notice == true) { + $('.ssl-notice').show(); + } + if (show_version_notice == true) { + $('.different-plugin-version-notice').show(); + $('.step-two').hide(); + } + $('.directory-scope').html('local'); + if (false == wpsdb_write_permission) { + $('#create-backup').prop('checked', false); + $('#create-backup').attr('disabled', 'disabled'); + $('#create-backup-label').addClass('disabled'); + $('.backup-option-disabled').show(); + $('.upload-directory-location').html(wpsdb_this_upload_dir_long); + } + } else { + $('.connection-status').show(); + $('.step-two').hide(); + } + } else if ($('#push').is(':checked')) { + $('.push-list li').append(connection_info_box); + connection_info_box.show(); + if (connection_established) { + $('.connection-status').hide(); + $('.step-two').show(); + $('.table-prefix').html(wpsdb_this_prefix); + $('.uploads-dir').html(connection_data.uploads_dir); + if (profile_name_edited == false) { + var profile_name = get_domain_name(connection_info[0]); + $('.create-new-profile').val(profile_name); + } + if (show_prefix_notice == true) { + $('.prefix-notice.push').show(); + } + if (show_ssl_notice == true) { + $('.ssl-notice').show(); + } + if (show_version_notice == true) { + $('.different-plugin-version-notice').show(); + $('.step-two').hide(); + } + $('.directory-scope').html('remote'); + if ('0' == connection_data.write_permissions) { + $('#create-backup').prop('checked', false); + $('#create-backup').attr('disabled', 'disabled'); + $('#create-backup-label').addClass('disabled'); + $('.backup-option-disabled').show(); + $('.upload-directory-location').html(connection_data.upload_dir_long); + } + } else { + $('.connection-status').show(); + $('.step-two').hide(); + } + } else if ($('#savefile').is(':checked')) { + $('.connection-status').hide(); + $('.step-two').show(); + $('.table-prefix').html(wpsdb_this_prefix); + if (profile_name_edited == false) { + $('.create-new-profile').val(''); + } + $('.backup-options').hide(); + $('.keep-active-plugins').hide(); + if (false == wpsdb_write_permission) { + $('.directory-permission-notice').show(); + $('.step-two').hide(); + } + } + $.wpsdb.do_action('move_connection_info_box'); + } + + function change_replace_values() { + if ($('#push').is(':checked') || $('#savefile').is(':checked')) { + if (last_replace_switch == '' || last_replace_switch == 'pull') { + $('.replace-row').each(function() { + var old_val = $('.old-replace-col input', this).val(); + $('.old-replace-col input', this).val($( + '.replace-right-col input', this).val()); + $('.replace-right-col input', this).val(old_val); + }); + } + $('#select-tables').remove(); + $('.select-tables-wrap').prepend(push_select); + $('#select-post-types').remove(); + $('.select-post-types-wrap').prepend(push_post_type_select); + $('#select-backup').remove(); + $('.backup-tables-wrap').prepend(push_select_backup); + last_replace_switch = 'push'; + } else if ($('#pull').is(':checked')) { + if (last_replace_switch == '' || last_replace_switch == 'push') { + $('.replace-row').each(function() { + var old_val = $('.old-replace-col input', this).val(); + $('.old-replace-col input', this).val($( + '.replace-right-col input', this).val()); + $('.replace-right-col input', this).val(old_val); + }); + } + $('#select-tables').remove(); + $('.select-tables-wrap').prepend(pull_select); + $('#select-post-types').remove(); + $('.select-post-types-wrap').prepend(pull_post_type_select); + $('#select-backup').remove(); + $('.backup-tables-wrap').prepend(pull_select_backup); + last_replace_switch = 'pull'; + } + + } + + // hide second section if pull or push is selected with no connection established + if (($('#pull').is(':checked') || $('#push').is(':checked')) && ! + connection_established) { + $('.step-two').hide(); + $('.connection-status').show(); + } + + // show / hide GUID helper description + $('.general-helper').click(function() { + var $icon = $(this), + $bubble = $(this).next(); + + // Close any that are already open + $('.helper-message').not($bubble).hide(); + + var position = $icon.position(); + $bubble.css({ + 'left': (position.left + $icon.width() + 8) + 'px', + 'top': (position.top + $icon.height() / 2 - 18) + 'px' + }); + + $bubble.toggle(); + }); + + $('body').click(function() { + $('.helper-message').hide(); + }); + + $('.helper-message').click(function(e) { + e.stopPropagation(); + }); + + // migrate / settings tabs + $('.nav-tab').click(function() { + $('.nav-tab').removeClass('nav-tab-active'); + $(this).addClass('nav-tab-active'); + $('.content-tab').hide(); + $('.' + $(this).attr('data-div-name')).show(); + + var hash = $(this).attr('data-div-name'); + hash = hash.replace('-tab', ''); + window.location.hash = hash; + + if ($(this).hasClass('help')) { + refresh_debug_log(); + } + }); + + // repeatable fields + $('body').delegate('.replace-add-row', 'click', function() { + $(this).parents('tr').after($('.original-repeatable-field').clone() + .removeClass('original-repeatable-field')); + }); + + // repeatable fields + $('body').delegate('.replace-remove-row', 'click', function() { + $(this).parents('tr').remove(); + if ($('.replace-row').length < 2) { + $('.no-replaces-message').show(); + } + }); + + $('.add-replace').click(function() { + $('.replace-fields').append($('.original-repeatable-field').clone() + .removeClass('original-repeatable-field')); + $('.no-replaces-message').hide(); + }); + + // delete saved profiles + $('body').delegate('.save-migration-profile-wrap li', 'hover', function( + event) { + if (event.type === 'mouseenter') { + $('.delete-profile', this).show(); + } else { + $('.delete-profile', this).hide(); + } + }); + + /*function validate_url(url) { + return /^([a-z]([a-z]|\d|\+|-|\.)*):(\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?((\[(|(v[\da-f]{1,}\.(([a-z]|\d|-|\.|_|~)|[!\$&'\(\)\*\+,;=]|:)+))\])|((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=])*)(:\d*)?)(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*|(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)){0})(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i + .test(url); + }*/ + + // check for hash in url (settings || migrate) switch tabs accordingly + if (window.location.hash) { + var hash = window.location.hash.substring(1); + switch_to_plugin_tab(hash); + } + + function switch_to_plugin_tab(hash) { + $('.nav-tab').removeClass('nav-tab-active'); + $('.nav-tab.' + hash).addClass('nav-tab-active'); + $('.content-tab').hide(); + $('.' + hash + '-tab').show(); + } + + // regenerates the saved secret key + $('.reset-api-key').click(function() { + var answer = confirm( + 'Any sites setup to use the current API key will no longer be able to connect. You will need to update those sites with the newly generated API key. Do you wish to continue?' + ); + + if (!answer || doing_reset_api_key_ajax) { + return; + } + + doing_reset_api_key_ajax = true; + $('.reset-api-key').after(''); + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action: 'wpsdb_reset_api_key', + }, + error: function(jqXHR, textStatus, errorThrown) { + alert( + 'An error occurred when trying to generate the API key. Please see the Help tab for details on how to request support. (#105)' + ); + $('.reset-api-key-ajax-spinner').remove(); + doing_reset_api_key_ajax = false; + }, + success: function(data) { + $('.reset-api-key-ajax-spinner').remove(); + doing_reset_api_key_ajax = false; + $('.connection-info').html(data); + } + }); + + }); + + var this_connection_info = $.parseJSON(wpsdb_connection_info); + + // show / hide table select box when specific settings change + $('input.multiselect-toggle').change(function() { + $(this).parents('.expandable-content').children('.select-wrap').toggle(); + }); + + $('.show-multiselect').each(function() { + if ($(this).is(':checked')) { + $(this).parents('.option-section').children( + '.header-expand-collapse').children('.expand-collapse-arrow').removeClass( + 'collapsed'); + $(this).parents('.expandable-content').show(); + $(this).parents('.expandable-content').children('.select-wrap').toggle(); + } + }); + + $('input[name=backup_option]').change(function() { + $('.backup-tables-wrap').hide(); + if ($(this).val() == 'backup_manual_select') { + $('.backup-tables-wrap').show(); + } + }); + + if ($('#backup-manual-select').is(':checked')) { + $('.backup-tables-wrap').show(); + } + + // delete a profile from the migrate form area + $('body').delegate('.delete-profile', 'click', function() { + var name = $(this).next().clone(); + $('input', name).remove(); + var name = $.trim($(name).html()); + var answer = confirm('You are removing the "' + name + + '" migration profile. This cannot be undone. Do you wish to continue?' + ); + + if (!answer) { + return; + } + + $(this).parent().fadeOut(500); + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action: 'wpsdb_delete_migration_profile', + profile_id: $(this).attr('data-profile-id') + }, + error: function(jqXHR, textStatus, errorThrown) { + alert( + 'An error occurred when trying to delete the profile. Please see the Help tab for details on how to request support. (#106)' + ); + }, + success: function(data) { + if (data == '-1') { + alert( + 'The selected migration profile could not be deleted because it was not found.\nPlease refresh this page to see an accurate list of the currently available migration profiles.' + ); + } + } + }); + + }); + + // deletes a profile from the main profile selection screen + $('.main-list-delete-profile-link').click(function() { + var name = $(this).prev().html(); + var answer = confirm('You are removing the "' + name + + '" migration profile. This cannot be undone. Do you wish to continue?' + ); + + if (!answer) { + return; + } + + $(this).parent().fadeOut(500); + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action: 'wpsdb_delete_migration_profile', + profile_id: $(this).attr('data-profile-id') + }, + error: function(jqXHR, textStatus, errorThrown) { + alert( + 'An error occurred when trying to delete the profile. Please see the Help tab for details on how to request support. (#107)' + ); + } + }); + + }); + + // warn the user when editing the connection info after a connection has + // been established + $('body').delegate('.temp-disabled', 'click', function() { + var answer = confirm( + 'If you change the connection details, you will lose any replaces and table selections you have made below. Do you wish to continue?' + ); + + if (!answer) { + return; + } else { + $('.ssl-notice').hide(); + $('.different-plugin-version-notice').hide(); + $('.migrate-db-button').show(); + $('.temp-disabled').removeAttr('readonly'); + $('.temp-disabled').removeClass('temp-disabled'); + $('.connect-button').show(); + $('.step-two').hide(); + $('.connection-status').show().html( + 'Please enter the connection information above to continue.'); + connection_established = false; + } + }); + + // ajax request for settings page when checking/unchecking setting radio + // buttons + $('.settings-tab input[type=checkbox]').change(function() { + var checked = $(this).is(':checked'); + var setting = $(this).attr('id'); + + $(this).parent().append(''); + var $label = $(this).parent(); + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action: 'wpsdb_save_setting', + checked: checked, + setting: setting + }, + error: function(jqXHR, textStatus, errorThrown) { + alert( + 'An error occurred when trying to save the settings. Please try again. If the problem persists, please see the Help tab for details on how to request support. (#108)' + ); + $('.ajax-spinner').remove(); + }, + success: function(data) { + $('.ajax-spinner').remove(); + $($label).append( + 'Saved'); + $('.ajax-success-msg').fadeOut(2000, function() { + $(this).remove(); + }); + } + }); + + }); + + // disable form submissions + $('.migrate-form').submit(function() { + return false; + }); + + // fire connection_box_changed when the connect button is pressed + $('.connect-button').click(function(event) { + event.preventDefault(); + $(this).blur(); + connection_box_changed(); + }); + + // send paste even to connection_box_changed() function + $('.pull-push-connection-info').bind('paste', function(e) { + var $this = this; + setTimeout(function() { + connection_box_changed(); + }, 0); + + }); + + $('body').delegate('.try-again', 'click', function() { + connection_box_changed(); + }); + + $('body').delegate('.try-http', 'click', function() { + var connection_info = $.trim($('.pull-push-connection-info').val()) + .split("\n"); + var new_url = connection_info[0].replace('https', 'http'); + var new_contents = new_url + "\n" + connection_info[1]; + $('.pull-push-connection-info').val(new_contents); + connection_box_changed(); + }); + + $('.create-new-profile').change(function() { + profile_name_edited = true; + }); + + // fired when the connection info box changes (e.g. gets pasted into) + function connection_box_changed(data) { + var $this = $('.pull-push-connection-info'); + + if (doing_ajax || $($this).hasClass('temp-disabled')) { + return; + } + + var data = $('.pull-push-connection-info').val(); + + var connection_info = $.trim(data).split("\n"); + var error = false; + var error_message = ''; + + if (connection_info == '') { + error = true; + error_message = + 'The connection information appears to be missing, please enter it to continue.'; + } + + if (connection_info.length != 2 && !error) { + error = true; + error_message = + 'The connection information appears to be incorrect, it should consist of two lines. The first being the remote server\'s URL and the second being the secret key.'; + } + + if (!error && !validate_url(connection_info[0])) { + error = true; + error_message = + 'The URL on the first line appears to be invalid, please check it and try again.'; + } + + if (!error && connection_info[1].length != 32) { + error = true; + error_message = + 'The secret key on the second line appears to be invalid. It should be a 32 character string that consists of letters, numbers and special characters only.'; + } + + if (!error && connection_info[0] == this_connection_info[0]) { + error = true; + error_message = + 'It appears you\'ve entered the URL for this website, you need to provide the URL of the remote website instead.'; + } + + if (!error && connection_info[1] == this_connection_info[1]) { + error = true; + error_message = + 'It appears you\'ve entered the secret key for this website, you need to provide the secret key for the remote website instead.'; + } + + if (error) { + $('.connection-status').html(error_message); + $('.connection-status').addClass( + 'notification-message error-notice migration-error'); + return; + } + + if (wpsdb_openssl_available == false) { + connection_info[0] = connection_info[0].replace('https://', + 'http://'); + var new_connection_info_contents = connection_info[0] + "\n" + + connection_info[1]; + $('.pull-push-connection-info').val(new_connection_info_contents); + } + + show_prefix_notice = false; + doing_ajax = true; + disable_export_type_controls(); + + if ($('.basic-access-auth-wrapper').is(':visible')) { + connection_info[0] = connection_info[0].replace(/\/\/(.*)@/, '//'); + connection_info[0] = connection_info[0].replace('//', '//' + + encodeURIComponent($.trim($('.auth-username').val())) + ':' + + encodeURIComponent($.trim($('.auth-password').val())) + '@'); + var new_connection_info_contents = connection_info[0] + "\n" + + connection_info[1]; + $('.pull-push-connection-info').val(new_connection_info_contents); + $('.basic-access-auth-wrapper').hide(); + } + + $('.step-two').hide(); + $('.ssl-notice').hide(); + $('.prefix-notice').hide(); + $('.connection-status').show(); + + $('.connection-status').html( + 'Establishing connection to remote server, please wait'); + $('.connection-status').removeClass( + 'notification-message error-notice migration-error'); + $('.connection-status').append(''); + + var intent = $('input[name=action]:checked').val(); + + profile_name_edited = false; + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'json', + cache: false, + data: { + action: 'wpsdb_verify_connection_to_remote_site', + url: connection_info[0], + key: connection_info[1], + intent: intent, + }, + error: function(jqXHR, textStatus, errorThrown) { + $('.connection-status').html( + 'A problem occurred when attempting to connect to the local server, please check the details and try again. (#100)' + ); + $('.connection-status').addClass( + 'notification-message error-notice migration-error'); + $('.ajax-spinner').remove(); + doing_ajax = false; + enable_export_type_controls(); + }, + success: function(data) { + $('.ajax-spinner').remove(); + doing_ajax = false; + enable_export_type_controls(); + + if (typeof data.wpsdb_error != 'undefined' && data.wpsdb_error == + 1) { + $('.connection-status').html(data.body); + $('.connection-status').addClass( + 'notification-message error-notice migration-error'); + + if (data.body.indexOf('401 Unauthorized') > -1) { + $('.basic-access-auth-wrapper').show(); + } + + return; + } + + var profile_name = get_domain_name(connection_info[0]); + $('.create-new-profile').val(profile_name); + + $('.pull-push-connection-info').addClass('temp-disabled'); + $('.pull-push-connection-info').attr('readonly', 'readonly'); + $('.connect-button').hide(); + + $('.connection-status').hide(); + $('.step-two').show(); + + maybe_show_ssl_warning(connection_info[0], connection_info[1], + data.scheme); + maybe_show_version_warning(data.plugin_version, connection_info[ + 0]); + maybe_show_prefix_notice(data.prefix); + + connection_established = true; + connection_data = data; + move_connection_info_box(); + + var table_select = document.createElement('select'); + $(table_select).attr({ + multiple: 'multiple', + name: 'select_tables[]', + id: 'select-tables', + class: 'multiselect' + }); + + $.each(connection_data.tables, function(index, value) { + $(table_select).append(''); + }); + + pull_select = table_select; + push_select_backup = $(table_select).clone(); + $(push_select_backup).attr({ + name: 'select_backup[]', + id: 'select-backup' + }); + + var post_type_select = document.createElement('select'); + $(post_type_select).attr({ + multiple: 'multiple', + name: 'select_post_types[]', + id: 'select-post-types', + class: 'multiselect' + }); + + $.each(connection_data.post_types, function(index, value) { + $(post_type_select).append(''); + }); + + pull_post_type_select = post_type_select; + + if ($('#pull').is(':checked')) { + $('#new-url').val(remove_protocol(wpsdb_this_url)); + $('#new-path').val(wpsdb_this_path); + if (wpsdb_is_multisite == true) { + $('#new-domain').val(wpsdb_this_domain); + } + $('#old-url').val(remove_protocol(data.url)); + $('#old-path').val(data.path); + $('#select-tables').remove(); + $('.select-tables-wrap').prepend(pull_select); + $('#select-post-types').remove(); + $('.select-post-types-wrap').prepend(pull_post_type_select); + $('.table-prefix').html(data.prefix); + $('.uploads-dir').html(wpsdb_this_uploads_dir); + } else { + $('#select-backup').remove(); + $('.backup-tables-wrap').prepend(push_select_backup); + $('#new-url').val(remove_protocol(data.url)); + $('#new-path').val(data.path); + } + + $.wpsdb.do_action('verify_connection_to_remote_site', + connection_data); + } + }); + } + }); })(jQuery); From 32f9785c4264cb6b81d5948efe306ed0033af305 Mon Sep 17 00:00:00 2001 From: Sean Lang Date: Sat, 21 Jun 2014 01:31:37 -0400 Subject: [PATCH 30/52] update js to 1.4b --- asset/js/common.js | 1 + asset/js/script.js | 736 +++++++++++++++++++++++++++++++++------------ 2 files changed, 539 insertions(+), 198 deletions(-) diff --git a/asset/js/common.js b/asset/js/common.js index 6576157..5b14e41 100644 --- a/asset/js/common.js +++ b/asset/js/common.js @@ -4,6 +4,7 @@ var call_stack = []; var non_fatal_errors = ''; var migration_error = false; var connection_data; +var next_step_in_migration; function wpsdb_call_next_hook() { if (!call_stack.length) { diff --git a/asset/js/script.js b/asset/js/script.js index b52c89b..c6ab2fa 100755 --- a/asset/js/script.js +++ b/asset/js/script.js @@ -1,6 +1,8 @@ // global functions var migration_complete; var migration_complete_events; +var migrate_table_recursive; +var execute_next_step; (function($) { var connection_established = false; @@ -8,6 +10,7 @@ var migration_complete_events; var doing_ajax = false; var doing_reset_api_key_ajax = false; var doing_save_profile = false; + var doing_plugin_compatibility_ajax = false; var profile_name_edited = false; var show_prefix_notice = false; var show_ssl_notice = false; @@ -24,6 +27,12 @@ var migration_complete_events; var elapsed_interval; var completed_msg; var tables_to_migrate = ''; + var migration_paused = false; + var previous_progress_title; + var previous_progress_text; + var timer_count; + var overall_percent; + var migration_cancelled = false; var admin_url = ajaxurl.replace('/admin-ajax.php', ''), spinner_url = admin_url + '/images/wpspin_light'; @@ -61,27 +70,27 @@ var migration_complete_events; } function setup_counter() { - var c = 0, - counter_display = $('.timer'), - label = 'Time Elapsed: '; - - function display_count() { - hours = parseInt(c / 3600) % 24; - minutes = parseInt(c / 60) % 60; - seconds = c % 60; - var display = label + pad(hours, 2, 0) + ':' + pad(minutes, 2, 0) + ':' + - pad(seconds, 2, 0); - counter_display.html(display); - } - - function count() { - c = c + 1; - display_count(); - } + timer_count = 0, + counter_display = $('.timer'), + label = wpsdb_i10n.time_elapsed + ' '; elapsed_interval = setInterval(count, 1000); } + function display_count() { + hours = Math.floor(timer_count / 3600) % 24; + minutes = Math.floor(timer_count / 60) % 60; + seconds = timer_count % 60; + var display = label + pad(hours, 2, 0) + ':' + pad(minutes, 2, 0) + ':' + + pad(seconds, 2, 0); + counter_display.html(display); + } + + function count() { + timer_count = timer_count + 1; + display_count(); + } + function get_intersect(arr1, arr2) { var r = [], o = {}, l = arr2.length, @@ -146,7 +155,7 @@ var migration_complete_events; function get_domain_name(url) { var temp_url = url; var domain = temp_url.replace(/\/\/(.*)@/, '//').replace('http://', '').replace( - 'https://', '').replace('www.', '').split(/[/?#]/)[0]; + 'https://', '').replace('www.', ''); return domain; } @@ -170,6 +179,70 @@ var migration_complete_events; } $(document).ready(function() { + $('#plugin-compatibility').change(function(e) { + var install = '1'; + if ($(this).is(':checked')) { + // replace with l10n string when available + var answer = confirm( + 'If confirmed we will install an additional WordPress "Must Use" plugin. This plugin will allow us to control which plugins are loaded during WP Sync DB specific operations. Do you wish to continue?' + ); + + if (!answer) { + $(this).prop('checked', false); + return; + } + } else { + install = '0'; + } + + $('.plugin-compatibility-wrap').toggle(); + + $(this).parent().append(''); + $('#plugin-compatibility').attr('disabled', 'disabled'); + $('.plugin-compatibility').addClass('disabled'); + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action: 'wpsdb_plugin_compatibility', + install: install, + }, + error: function(jqXHR, textStatus, errorThrown) { + // replace with l10n string when available + alert( + 'A problem occurred when trying to change the plugin compatibility setting.\r\n\r\nStatus: ' + + jqXHR.status + ' ' + jqXHR.statusText + + '\r\n\r\nResponse:\r\n' + jqXHR.responseText); + $('.ajax-spinner').remove(); + $('#plugin-compatibility').removeAttr('disabled'); + $('.plugin-compatibility').removeClass('disabled'); + }, + success: function(data) { + if ('' != $.trim(data)) { + alert(data); + } else { + $('.plugin-compatibility').append( + 'Saved'); + $('.ajax-success-msg').fadeOut(2000, function() { + $(this).remove(); + }); + } + $('.ajax-spinner').remove(); + $('#plugin-compatibility').removeAttr('disabled'); + $('.plugin-compatibility').removeClass('disabled'); + } + }); + + }); + + if ($('#plugin-compatibility').is(':checked')) { + $('.plugin-compatibility-wrap').show(); + } + if (navigator.userAgent.indexOf('MSIE') > 0 || navigator.userAgent.indexOf( 'Trident') > 0) { $('.ie-warning').show(); @@ -196,13 +269,12 @@ var migration_complete_events; data: { action: 'wpsdb_update_max_request_size', max_request_size: parseInt(ui.value), + nonce: wpsdb_nonces.update_max_request_size, }, error: function(jqXHR, textStatus, errorThrown) { $('.slider').slider('enable'); $('.slider-spinner').remove(); - alert( - 'A problem occurred when trying to change the maximum request size, please try again.' - ); + alert(wpsdb_i10n.max_request_size_problem); }, success: function(data) { $('.slider').slider('enable'); @@ -221,8 +293,6 @@ var migration_complete_events; var progress_content_original = $('.progress-content').clone(); $('.progress-content').remove(); - var this_tables = $.parseJSON(wpsdb_this_tables); - var this_prefixed_tables = $.parseJSON(wpsdb_this_prefixed_tables); var push_select = $('#select-tables').clone(); var pull_select = $('#select-tables').clone(); var push_post_type_select = $('#select-post-types').clone(); @@ -234,13 +304,14 @@ var migration_complete_events; var $container = $(this), $viewer = $('.video-viewer'); - $('a', this).click(function() { + $('a', this).click(function(e) { + e.preventDefault(); + $viewer.attr('src', '//www.youtube.com/embed/' + $container.data( 'video-id') + '?autoplay=1'); $viewer.show(); var offset = $viewer.offset(); $(window).scrollTop(offset.top - 50); - return false; }); }); @@ -283,8 +354,7 @@ var migration_complete_events; doing_ajax = true; disable_export_type_controls(); - $('.connection-status').html( - 'Establishing connection to remote server, please wait'); + $('.connection-status').html(wpsdb_i10n.establishing_remote_connection); $('.connection-status').removeClass( 'notification-message error-notice migration-error'); $('.connection-status').append(' tags which act as JS event buttons, will not jump page to top // and will deselect the button - $('.js-action-link').click(function(event) { + $('.js-action-link').click(function(e) { + e.preventDefault(); $(this).blur(); - return false; }); // clears the debug log @@ -470,11 +551,10 @@ var migration_complete_events; cache: false, data: { action: 'wpsdb_clear_log', + nonce: wpsdb_nonces.clear_log, }, error: function(jqXHR, textStatus, errorThrown) { - alert( - 'An error occurred when trying to clear the debug log. Please contact support. (#132)' - ); + alert(wpsdb_i10n.clear_log_problem); }, success: function(data) {} }); @@ -489,11 +569,10 @@ var migration_complete_events; cache: false, data: { action: 'wpsdb_get_log', + nonce: wpsdb_nonces.get_log, }, error: function(jqXHR, textStatus, errorThrown) { - alert( - 'An error occurred when trying to update the debug log. Please contact support. (#133)' - ); + alert(wpsdb_i10n.update_log_problem); }, success: function(data) { $('.debug-log-textarea').val(data); @@ -570,16 +649,16 @@ var migration_complete_events; $('#save-migration-profile').change(function() { if ($(this).is(':checked')) { $('.save-settings-button').show(); - $('.migrate-db .button-primary').val('Migrate DB & Save'); + $('.migrate-db .button-primary').val(wpsdb_i10n.migrate_db_save); } else { $('.save-settings-button').hide(); - $('.migrate-db .button-primary').val('Migrate DB'); + $('.migrate-db .button-primary').val(wpsdb_i10n.migrate_db); } }); if ($('#save-migration-profile').is(':checked')) { $('.save-settings-button').show(); - $('.migrate-db .button-primary').val('Migrate DB & Save'); + $('.migrate-db .button-primary').val(wpsdb_i10n.migrate_db_save); }; $('.checkbox-label input[type=checkbox]').each(function() { @@ -588,6 +667,14 @@ var migration_complete_events; } }); + $('#new-url').change(function() { + $('#new-url-missing-warning').hide(); + }); + + $('#new-path').change(function() { + $('#new-path-missing-warning').hide(); + }); + // AJAX migrate button $('.migrate-db-button').click(function(event) { $(this).blur(); @@ -596,16 +683,36 @@ var migration_complete_events; // check that they've selected some tables to migrate if ($('#migrate-selected').is(':checked') && $('#select-tables').val() == null) { - alert('Please select at least one table to migrate.'); + alert(wpsdb_i10n.please_select_one_table); return; } + new_url_missing = false; + new_file_path_missing = false; + if ($('#new-url').length && !$('#new-url').val()) { + $('#new-url-missing-warning').show(); + $('#new-url').focus(); + $('html,body').scrollTop(0); + new_url_missing = true; + } + + if ($('#new-path').length && !$('#new-path').val()) { + $('#new-path-missing-warning').show(); + if (false == new_url_missing) { + $('#new-path').focus(); + $('html,body').scrollTop(0); + } + new_file_path_missing = true; + } + + if (true == new_url_missing || true == new_file_path_missing) return; + // also save profile if ($('#save-migration-profile').is(':checked')) { if ($.trim($('.create-new-profile').val()) == '' && $( '#create_new').is(':checked')) { - alert('Please enter a name for your migration profile.'); + alert(wpsdb_i10n.enter_name_for_profile); $('.create-new-profile').focus(); return; } @@ -627,22 +734,24 @@ var migration_complete_events; data: { action: 'wpsdb_save_profile', profile: profile, + nonce: wpsdb_nonces.save_profile, }, error: function(jqXHR, textStatus, errorThrown) { - alert( - 'An error occurred when attempting to save the migration profile. Please see the Help tab for details on how to request support. (#118)' - ); + alert(wpsdb_i10n.save_profile_problem); }, success: function(data) { if (create_new_profile) { + var new_profile_key = parseInt(data, 10); + var new_profile_id = new_profile_key + 1; var new_li = '
  • '; $('#create_new').parents('li').before(new_li); - $('#profile-' + data).attr('checked', 'checked'); + $('#profile-' + new_profile_id).attr('checked', 'checked'); $('.create-new-profile').val(''); } } @@ -691,15 +800,15 @@ var migration_complete_events; $('#overlay').after($progress_content); - completed_msg = 'Exporting complete'; + completed_msg = wpsdb_i10n.exporting_complete; if (migration_intent == 'savefile') { - static_migration_label = 'Exporting, please wait...'; + static_migration_label = wpsdb_i10n.exporting_please_wait; } else { static_migration_label = get_default_profile_name(remote_site, - migration_intent, true) + ', please wait...'; + migration_intent, true) + ', ' + wpsdb_i10n.please_wait; completed_msg = get_default_profile_name(remote_site, - migration_intent, true) + ' complete'; + migration_intent, true) + ' ' + wpsdb_i10n.complete; } $('.progress-title').html(static_migration_label); @@ -725,14 +834,13 @@ var migration_complete_events; tables_to_migrate = $('#select-backup').val(); } } else { - table_rows = $.parseJSON(wpsdb_this_table_rows); + table_rows = wpsdb_this_table_rows; if (backup_option == 'backup_only_with_prefix') { - tables_to_migrate = $.parseJSON(wpsdb_this_prefixed_tables); + tables_to_migrate = wpsdb_this_prefixed_tables; } else if (backup_option == 'backup_selected') { selected_tables = $('#select-tables').val(); - local_tables = $.parseJSON(wpsdb_this_tables); tables_to_migrate = get_intersect(selected_tables, - local_tables); + wpsdb_this_tables); } else if (backup_option == 'backup_manual_select') { tables_to_migrate = $('#select-backup').val(); } @@ -745,15 +853,15 @@ var migration_complete_events; if (migration_intent == 'push' || migration_intent == 'savefile') { // default value, assuming we're not backing up - table_rows = $.parseJSON(wpsdb_this_table_rows); + table_rows = wpsdb_this_table_rows; } else { table_rows = connection_data.table_rows; } } else { if (migration_intent == 'push' || migration_intent == 'savefile') { - tables_to_migrate = this_prefixed_tables; - table_rows = $.parseJSON(wpsdb_this_table_rows); + tables_to_migrate = wpsdb_this_prefixed_tables; + table_rows = wpsdb_this_table_rows; } else { tables_to_migrate = connection_data.prefixed_tables; table_rows = connection_data.table_rows; @@ -761,7 +869,9 @@ var migration_complete_events; } } - function decide_tables_to_display_rows(tables_to_migrate, table_rows) { + function decide_tables_to_display_rows(tables_to_migrate, + table_rows) { + var total_size = 0; $.each(tables_to_migrate, function(index, value) { total_size += parseInt(table_rows[value]); @@ -849,12 +959,15 @@ var migration_complete_events; key: secret_key, form_data: form_data, stage: stage, + nonce: wpsdb_nonces.initiate_migration, }, error: function(jqXHR, textStatus, errorThrown) { $('.progress-title').html('Migration failed'); - $('.progress-text').html( - 'A problem occurred when attempting to connect to the local server, please check the details and try again. (#112)' - ); + $('.progress-text').html(wpsdb_i10n.connection_local_server_problem + + ' (#112)'); + $('.progress-text').append('

    Status: ' + jqXHR.status + + ' ' + jqXHR.statusText + '

    Response:
    ' + + jqXHR.responseText); $('.progress-text').addClass('migration-error'); console.log(jqXHR); console.log(textStatus); @@ -866,8 +979,9 @@ var migration_complete_events; success: function(data) { if (typeof data.wpsdb_error != 'undefined' && data.wpsdb_error == 1) { + migration_error = true; migration_complete_events(); - $('.progress-title').html('Migration failed'); + $('.progress-title').html(wpsdb_i10n.migration_failed); $('.progress-text').addClass('migration-error'); $('.progress-text').html(data.body); return; @@ -878,13 +992,13 @@ var migration_complete_events; var i = 0; var progress_size = 0; - var overall_percent = 0; + overall_percent = 0; var table_progress = 0; var temp_progress = 0; var last_progress = 0; var overall_table_progress = 0; - function migrate_table_recursive(current_row, primary_keys) { + migrate_table_recursive = function(current_row, primary_keys) { if (i >= tables_to_migrate.length) { if (stage == 'backup') { stage = 'migrate'; @@ -896,15 +1010,15 @@ var migration_complete_events; tables_to_migrate = $('#select-tables').val(); if (migration_intent == 'push' || migration_intent == 'savefile') { - table_rows = $.parseJSON(wpsdb_this_table_rows); + table_rows = wpsdb_this_table_rows; } else { table_rows = connection_data.table_rows; } } else { if (migration_intent == 'push' || migration_intent == 'savefile') { - tables_to_migrate = this_prefixed_tables; - table_rows = $.parseJSON(wpsdb_this_table_rows); + tables_to_migrate = wpsdb_this_prefixed_tables; + table_rows = wpsdb_this_table_rows; } else { tables_to_migrate = connection_data.prefixed_tables; table_rows = connection_data.table_rows; @@ -918,7 +1032,6 @@ var migration_complete_events; tables_to_migrate, table_rows); table_rows = table_details[0]; total_size = table_details[1]; - } else { hooks = $.wpsdb.apply_filters( 'wpsdb_before_migration_complete_hooks', hooks); @@ -926,17 +1039,22 @@ var migration_complete_events; hooks = $.wpsdb.apply_filters( 'wpsdb_after_migration_complete_hooks', hooks); hooks.push('migration_complete_events'); - wpsdb_call_next_hook(); + next_step_in_migration = { + fn: wpsdb_call_next_hook + }; + execute_next_step(); return; } } if (stage == 'backup') { - $('.progress-text').html(overall_percent + - '% - Backing up "' + tables_to_migrate[i] + '"'); + $('.progress-text').html(overall_percent + '% - ' + + wpsdb_i10n.backing_up + ' "' + tables_to_migrate[i] + + '"'); } else { - $('.progress-text').html(overall_percent + - '% - Migrating "' + tables_to_migrate[i] + '"'); + $('.progress-text').html(overall_percent + '% - ' + + wpsdb_i10n.migrating + ' "' + tables_to_migrate[i] + + '"'); } last_table = 0; @@ -963,6 +1081,7 @@ var migration_complete_events; last_table: last_table, primary_keys: primary_keys, gzip: gzip, + nonce: wpsdb_nonces.migrate_table, }; if (migration_intent != 'savefile') { @@ -976,6 +1095,8 @@ var migration_complete_events; request_data.domain_current_site = connection_data.domain; } + doing_ajax = true; + $.ajax({ url: ajaxurl, type: 'POST', @@ -985,13 +1106,14 @@ var migration_complete_events; data: request_data, error: function(jqXHR, textStatus, errorThrown) { $('.progress-title').html('Migration failed'); - $('.progress-text').html( - 'A problem occurred when processing the ' + - tables_to_migrate[i] + ' table. (#113)'); - $('.progress-text').append('

    Status: ' + - jqXHR.status + ' ' + jqXHR.statusText + - '

    Response:
    ' + jqXHR.responseText); + $('.progress-text').html(wpsdb_i10n.table_process_problem + + ' ' + tables_to_migrate[i]); + $('.progress-text').append('

    ' + + wpsdb_i10n.status + ': ' + jqXHR.status + ' ' + + jqXHR.statusText + '

    ' + wpsdb_i10n.response + + ':
    ' + jqXHR.responseText); $('.progress-text').addClass('migration-error'); + doing_ajax = false; console.log(jqXHR); console.log(textStatus); console.log(errorThrown); @@ -1000,17 +1122,15 @@ var migration_complete_events; return; }, success: function(data) { + doing_ajax = false; data = $.trim(data); row_information = wpsdb_parse_json(data); if (false == row_information || null == row_information) { $('.progress-title').html('Migration failed'); if ('' == data || null == data) { - $('.progress-text').html( - 'A problem occurred when processing the ' + - tables_to_migrate[i] + - ' table. We were expecting a response in JSON format but instead received an empty response.' - ); + $('.progress-text').html(wpsdb_i10n.table_process_problem_empty_response + + ' ' + tables_to_migrate[i]); } else { $('.progress-text').html(data); } @@ -1020,6 +1140,16 @@ var migration_complete_events; return; } + if (typeof row_information.wpsdb_error != 'undefined' && + row_information.wpsdb_error == 1) { + $('.progress-title').html('Migration failed'); + $('.progress-text').addClass('migration-error'); + $('.progress-text').html(row_information.body); + migration_error = true; + migration_complete_events(); + return; + } + if (row_information.current_row == '-1') { progress_size -= overall_table_progress; overall_table_progress = 0; @@ -1039,12 +1169,22 @@ var migration_complete_events; var percent = 100 * progress_size / total_size; $('.progress-bar').width(percent + '%'); overall_percent = Math.floor(percent); - migrate_table_recursive(row_information.current_row, - row_information.primary_keys); + next_step_in_migration = { + fn: migrate_table_recursive, + args: [row_information.current_row, row_information + .primary_keys + ] + }; + execute_next_step(); } }); } - migrate_table_recursive('-1', ''); + + next_step_in_migration = { + fn: migrate_table_recursive, + args: ['-1', ''] + }; + execute_next_step(); } }); // end ajax }); @@ -1061,17 +1201,22 @@ var migration_complete_events; } else { $('.progress-text').html(non_fatal_errors); $('.progress-text').addClass('migration-error'); - $('.progress-title').html('Migration completed with some errors'); + $('.progress-title').html(wpsdb_i10n.completed_with_some_errors); } $('.progress-bar-wrapper').hide(); } + $('.migration-controls').hide(); + // reset migration variables so consecutive migrations work correctly hooks = []; call_stack = []; migration_error = false; currently_migrating = false; migration_completed = true; + migration_paused = false; + migration_cancelled = false; + doing_ajax = false; non_fatal_errors = ''; $('.progress-label').remove(); @@ -1079,9 +1224,10 @@ var migration_complete_events; $('.close-progress-content').show(); $('#overlay').css('cursor', 'pointer'); clearInterval(elapsed_interval); - } + }; migration_complete = function() { + $('.migration-controls').fadeOut(); if (migration_intent == 'savefile') { currently_migrating = false; var migrate_complete_text = 'Migration complete'; @@ -1093,9 +1239,8 @@ var migration_complete_events; } window.location = url; } else { - migrate_complete_text = - 'Migration complete, your backup is located at: ' + dump_url + '.'; + migrate_complete_text = wpsdb_i10n.completed_dump_located_at + + ' ' + dump_url + '.'; } if (migration_error == false) { @@ -1120,11 +1265,11 @@ var migration_complete_events; prefix: connection_data.prefix, temp_prefix: connection_data.temp_prefix, tables: tables_to_migrate.join(','), + nonce: wpsdb_nonces.finalize_migration, }, error: function(jqXHR, textStatus, errorThrown) { - $('.progress-title').html('Migration failed'); - $('.progress-text').html( - 'A problem occurred when finalizing the backup. (#132)'); + $('.progress-title').html(wpsdb_i10n.migration_failed); + $('.progress-text').html(wpsdb_i10n.finalize_tables_problem); $('.progress-text').addClass('migration-error'); alert(jqXHR + ' : ' + textStatus + ' : ' + errorThrown); migration_error = true; @@ -1133,18 +1278,21 @@ var migration_complete_events; }, success: function(data) { if ($.trim(data) != '') { - $('.progress-title').html('Migration failed'); + $('.progress-title').html(wpsdb_i10n.migration_failed); $('.progress-text').html(data); $('.progress-text').addClass('migration-error'); migration_error = true; migration_complete_events(); return; } - wpsdb_call_next_hook(); + next_step_in_migration = { + fn: wpsdb_call_next_hook + }; + execute_next_step(); } }); } - } + }; // close progress pop up once migration is completed $('body').delegate('.close-progress-content-button', 'click', function( @@ -1182,13 +1330,13 @@ var migration_complete_events; // check that they've selected some tables to migrate if ($('#migrate-selected').is(':checked') && $('#select-tables').val() == null) { - alert('Please select at least one table to migrate.'); + alert(wpsdb_i10n.please_select_one_table); return; } if ($.trim($('.create-new-profile').val()) == '' && $('#create_new') .is(':checked')) { - alert('Please enter a name for your migration profile.'); + alert(wpsdb_i10n.enter_name_for_profile); $('.create-new-profile').focus(); return; } @@ -1215,15 +1363,15 @@ var migration_complete_events; data: { action: 'wpsdb_save_profile', profile: profile, + nonce: wpsdb_nonces.save_profile, }, error: function(jqXHR, textStatus, errorThrown) { - alert( - 'An error occurred when attempting to save the migration profile. Please see the Help tab for details on how to request support. (#104)' - ); + alert(wpsdb_i10n.save_profile_problem); $('.save-settings-button').removeAttr('disabled'); $('.save-profile-ajax-spinner').remove(); $('.save-settings-button').after( - 'Saved'); + '' + wpsdb_i10n.saved + + ''); $('.ajax-success-msg').fadeOut(2000, function() { $(this).remove(); }); @@ -1233,7 +1381,8 @@ var migration_complete_events; $('.save-settings-button').removeAttr('disabled'); $('.save-profile-ajax-spinner').remove(); $('.save-settings-button').after( - 'Saved'); + '' + wpsdb_i10n.saved + + ''); $('.ajax-success-msg').fadeOut(2000, function() { $(this).remove(); }); @@ -1241,19 +1390,20 @@ var migration_complete_events; $('.create-new-profile').val(''); if (create_new_profile) { + var new_profile_key = parseInt(data, 10); + var new_profile_id = new_profile_key + 1; var new_li = '
  • '; $('#create_new').parents('li').before(new_li); - $('#profile-' + data).attr('checked', 'checked'); + $('#profile-' + new_profile_id).attr('checked', 'checked'); } - } }); - }); // progress label updating @@ -1286,9 +1436,8 @@ var migration_complete_events; } }); - // save file (export) / import / push / pull special conditions + // save file (export) / push / pull special conditions function move_connection_info_box() { - $('.import-button').hide(); $('.connection-status').hide(); $('.prefix-notice').hide(); $('.ssl-notice').hide(); @@ -1421,7 +1570,6 @@ var migration_complete_events; $('.backup-tables-wrap').prepend(pull_select_backup); last_replace_switch = 'pull'; } - } // hide second section if pull or push is selected with no connection established @@ -1432,20 +1580,28 @@ var migration_complete_events; } // show / hide GUID helper description - $('.general-helper').click(function() { - var $icon = $(this), - $bubble = $(this).next(); + $('.general-helper').click(function(e) { + var icon = $(this), + bubble = $(this).next(); // Close any that are already open - $('.helper-message').not($bubble).hide(); + $('.helper-message').not(bubble).hide(); - var position = $icon.position(); - $bubble.css({ - 'left': (position.left + $icon.width() + 8) + 'px', - 'top': (position.top + $icon.height() / 2 - 18) + 'px' - }); + var position = icon.position(); + if (bubble.hasClass('bottom')) { + bubble.css({ + 'left': (position.left - bubble.width() / 2) + 'px', + 'top': (position.top + icon.height() + 9) + 'px' + }); + } else { + bubble.css({ + 'left': (position.left + icon.width() + 9) + 'px', + 'top': (position.top + icon.height() / 2 - 18) + 'px' + }); + } - $bubble.toggle(); + bubble.toggle(); + e.stopPropagation(); }); $('body').click(function() { @@ -1473,8 +1629,8 @@ var migration_complete_events; }); // repeatable fields - $('body').delegate('.replace-add-row', 'click', function() { - $(this).parents('tr').after($('.original-repeatable-field').clone() + $('body').delegate('.add-row', 'click', function() { + $(this).parents('tr').before($('.original-repeatable-field').clone() .removeClass('original-repeatable-field')); }); @@ -1487,11 +1643,33 @@ var migration_complete_events; }); $('.add-replace').click(function() { - $('.replace-fields').append($('.original-repeatable-field').clone() + $('.replace-fields').prepend($('.original-repeatable-field').clone() .removeClass('original-repeatable-field')); $('.no-replaces-message').hide(); }); + $('body').delegate('#find-and-replace-sort tbody tr.replace-row', + 'hover', function(event) { + if (event.type === 'mouseenter') { + $('.replace-remove-row', this).show(); + } else { + $('.replace-remove-row', this).hide(); + } + }); + + $('#find-and-replace-sort tbody').sortable({ + items: '> tr:not(.pin)', + handle: 'td:first', + start: function() { + $('.sort-handle').css('cursor', '-webkit-grabbing'); + $('.sort-handle').css('cursor', '-moz-grabbing'); + }, + stop: function() { + $('.sort-handle').css('cursor', '-webkit-grab'); + $('.sort-handle').css('cursor', '-moz-grab'); + } + }); + // delete saved profiles $('body').delegate('.save-migration-profile-wrap li', 'hover', function( event) { @@ -1502,29 +1680,36 @@ var migration_complete_events; } }); - /*function validate_url(url) { + function validate_url(url) { return /^([a-z]([a-z]|\d|\+|-|\.)*):(\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?((\[(|(v[\da-f]{1,}\.(([a-z]|\d|-|\.|_|~)|[!\$&'\(\)\*\+,;=]|:)+))\])|((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=])*)(:\d*)?)(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*|(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)){0})(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i .test(url); - }*/ + } // check for hash in url (settings || migrate) switch tabs accordingly if (window.location.hash) { var hash = window.location.hash.substring(1); - switch_to_plugin_tab(hash); + switch_to_plugin_tab(hash, false); + } + + if (get_query_var('install-plugin') != '') { + hash = 'addons'; + switch_to_plugin_tab(hash, true); } - function switch_to_plugin_tab(hash) { + function switch_to_plugin_tab(hash, skip_addons_check) { $('.nav-tab').removeClass('nav-tab-active'); $('.nav-tab.' + hash).addClass('nav-tab-active'); $('.content-tab').hide(); $('.' + hash + '-tab').show(); + + if (hash == 'help') { + refresh_debug_log(); + } } // regenerates the saved secret key $('.reset-api-key').click(function() { - var answer = confirm( - 'Any sites setup to use the current API key will no longer be able to connect. You will need to update those sites with the newly generated API key. Do you wish to continue?' - ); + var answer = confirm(wpsdb_i10n.reset_api_key); if (!answer || doing_reset_api_key_ajax) { return; @@ -1541,11 +1726,10 @@ var migration_complete_events; cache: false, data: { action: 'wpsdb_reset_api_key', + nonce: wpsdb_nonces.reset_api_key, }, error: function(jqXHR, textStatus, errorThrown) { - alert( - 'An error occurred when trying to generate the API key. Please see the Help tab for details on how to request support. (#105)' - ); + alert(wpsdb_i10n.reset_api_key_problem); $('.reset-api-key-ajax-spinner').remove(); doing_reset_api_key_ajax = false; }, @@ -1558,8 +1742,6 @@ var migration_complete_events; }); - var this_connection_info = $.parseJSON(wpsdb_connection_info); - // show / hide table select box when specific settings change $('input.multiselect-toggle').change(function() { $(this).parents('.expandable-content').children('.select-wrap').toggle(); @@ -1586,14 +1768,59 @@ var migration_complete_events; $('.backup-tables-wrap').show(); } + $('.plugin-compatibility-save').click(function() { + if (doing_plugin_compatibility_ajax) { + return; + } + $(this).addClass('disabled'); + select_element = $('#selected-plugins'); + $(select_element).attr('disabled', 'disabled'); + + doing_plugin_compatibility_ajax = true; + $(this).after('' + ); + + $.ajax({ + url: ajaxurl, + type: 'POST', + dataType: 'text', + cache: false, + data: { + action: 'wpsdb_blacklist_plugins', + blacklist_plugins: $(select_element).val(), + }, + error: function(jqXHR, textStatus, errorThrown) { + // replace with l10n string when available + alert( + 'A problem occurred when trying to add plugins to backlist.\r\n\r\nStatus: ' + + jqXHR.status + ' ' + jqXHR.statusText + + '\r\n\r\nResponse:\r\n' + jqXHR.responseText); + $(select_element).removeAttr('disabled'); + $('.plugin-compatibility-save').removeClass('disabled'); + doing_plugin_compatibility_ajax = false; + $('.plugin-compatibility-spinner').remove(); + $('.plugin-compatibility-success-msg').show().fadeOut(2000); + }, + success: function(data) { + if ('' != $.trim(data)) { + alert(data); + } + $(select_element).removeAttr('disabled'); + $('.plugin-compatibility-save').removeClass('disabled'); + doing_plugin_compatibility_ajax = false; + $('.plugin-compatibility-spinner').remove(); + $('.plugin-compatibility-success-msg').show().fadeOut(2000); + } + }); + }); + // delete a profile from the migrate form area $('body').delegate('.delete-profile', 'click', function() { var name = $(this).next().clone(); $('input', name).remove(); var name = $.trim($(name).html()); - var answer = confirm('You are removing the "' + name + - '" migration profile. This cannot be undone. Do you wish to continue?' - ); + var answer = confirm(wpsdb_i10n.remove_profile + ' "' + name + '"'); if (!answer) { return; @@ -1608,18 +1835,15 @@ var migration_complete_events; cache: false, data: { action: 'wpsdb_delete_migration_profile', - profile_id: $(this).attr('data-profile-id') + profile_id: $(this).attr('data-profile-id'), + nonce: wpsdb_nonces.delete_migration_profile, }, error: function(jqXHR, textStatus, errorThrown) { - alert( - 'An error occurred when trying to delete the profile. Please see the Help tab for details on how to request support. (#106)' - ); + alert(wpsdb_i10n.remove_profile_problem); }, success: function(data) { if (data == '-1') { - alert( - 'The selected migration profile could not be deleted because it was not found.\nPlease refresh this page to see an accurate list of the currently available migration profiles.' - ); + alert(wpsdb_i10n.remove_profile_not_found); } } }); @@ -1629,9 +1853,7 @@ var migration_complete_events; // deletes a profile from the main profile selection screen $('.main-list-delete-profile-link').click(function() { var name = $(this).prev().html(); - var answer = confirm('You are removing the "' + name + - '" migration profile. This cannot be undone. Do you wish to continue?' - ); + var answer = confirm(wpsdb_i10n.remove_profile + ' "' + name + '"'); if (!answer) { return; @@ -1646,12 +1868,11 @@ var migration_complete_events; cache: false, data: { action: 'wpsdb_delete_migration_profile', - profile_id: $(this).attr('data-profile-id') + profile_id: $(this).attr('data-profile-id'), + nonce: wpsdb_nonces.delete_migration_profile, }, error: function(jqXHR, textStatus, errorThrown) { - alert( - 'An error occurred when trying to delete the profile. Please see the Help tab for details on how to request support. (#107)' - ); + alert(wpsdb_i10n.remove_profile_problem); } }); @@ -1660,9 +1881,7 @@ var migration_complete_events; // warn the user when editing the connection info after a connection has // been established $('body').delegate('.temp-disabled', 'click', function() { - var answer = confirm( - 'If you change the connection details, you will lose any replaces and table selections you have made below. Do you wish to continue?' - ); + var answer = confirm(wpsdb_i10n.change_connection_info); if (!answer) { return; @@ -1674,8 +1893,7 @@ var migration_complete_events; $('.temp-disabled').removeClass('temp-disabled'); $('.connect-button').show(); $('.step-two').hide(); - $('.connection-status').show().html( - 'Please enter the connection information above to continue.'); + $('.connection-status').show().html(wpsdb_i10n.enter_connection_info); connection_established = false; } }); @@ -1683,6 +1901,7 @@ var migration_complete_events; // ajax request for settings page when checking/unchecking setting radio // buttons $('.settings-tab input[type=checkbox]').change(function() { + if ('plugin-compatibility' == $(this).attr('id')) return; var checked = $(this).is(':checked'); var setting = $(this).attr('id'); @@ -1698,18 +1917,17 @@ var migration_complete_events; data: { action: 'wpsdb_save_setting', checked: checked, - setting: setting + setting: setting, + nonce: wpsdb_nonces.save_setting, }, error: function(jqXHR, textStatus, errorThrown) { - alert( - 'An error occurred when trying to save the settings. Please try again. If the problem persists, please see the Help tab for details on how to request support. (#108)' - ); + alert(wpsdb_i10n.save_settings_problem); $('.ajax-spinner').remove(); }, success: function(data) { $('.ajax-spinner').remove(); - $($label).append( - 'Saved'); + $($label).append('' + + wpsdb_i10n.saved + ''); $('.ajax-success-msg').fadeOut(2000, function() { $(this).remove(); }); @@ -1719,8 +1937,8 @@ var migration_complete_events; }); // disable form submissions - $('.migrate-form').submit(function() { - return false; + $('.migrate-form').submit(function(e) { + e.preventDefault(); }); // fire connection_box_changed when the connect button is pressed @@ -1756,6 +1974,13 @@ var migration_complete_events; profile_name_edited = true; }); + $('body').delegate('.temporarily-disable-ssl', 'click', function() { + if (window.location.hash) { + var hash = window.location.hash.substring(1); + } + $(this).attr('href', $(this).attr('href') + '&hash=' + hash); + }); + // fired when the connection info box changes (e.g. gets pasted into) function connection_box_changed(data) { var $this = $('.pull-push-connection-info'); @@ -1772,38 +1997,32 @@ var migration_complete_events; if (connection_info == '') { error = true; - error_message = - 'The connection information appears to be missing, please enter it to continue.'; + error_message = wpsdb_i10n.connection_info_missing; } if (connection_info.length != 2 && !error) { error = true; - error_message = - 'The connection information appears to be incorrect, it should consist of two lines. The first being the remote server\'s URL and the second being the secret key.'; + error_message = wpsdb_i10n.connection_info_incorrect; } if (!error && !validate_url(connection_info[0])) { error = true; - error_message = - 'The URL on the first line appears to be invalid, please check it and try again.'; + error_message = wpsdb_i10n.connection_info_url_invalid; } if (!error && connection_info[1].length != 32) { error = true; - error_message = - 'The secret key on the second line appears to be invalid. It should be a 32 character string that consists of letters, numbers and special characters only.'; + error_message = wpsdb_i10n.connection_info_key_invalid; } - if (!error && connection_info[0] == this_connection_info[0]) { + if (!error && connection_info[0] == wpsdb_connection_info[0]) { error = true; - error_message = - 'It appears you\'ve entered the URL for this website, you need to provide the URL of the remote website instead.'; + error_message = wpsdb_i10n.connection_info_local_url; } - if (!error && connection_info[1] == this_connection_info[1]) { + if (!error && connection_info[1] == wpsdb_connection_info[1]) { error = true; - error_message = - 'It appears you\'ve entered the secret key for this website, you need to provide the secret key for the remote website instead.'; + error_message = wpsdb_i10n.connection_info_local_key; } if (error) { @@ -1841,8 +2060,7 @@ var migration_complete_events; $('.prefix-notice').hide(); $('.connection-status').show(); - $('.connection-status').html( - 'Establishing connection to remote server, please wait'); + $('.connection-status').html(wpsdb_i10n.establishing_remote_connection); $('.connection-status').removeClass( 'notification-message error-notice migration-error'); $('.connection-status').append(' -

    - Update Required — - get_wpsdb_basename(); - $addon_name = $this->get_plugin_name(); - $required = $this->version_required; - $installed = $this->get_installed_version( $wpsdb_basename ); - $update = wp_nonce_url( network_admin_url( 'update.php?action=upgrade-plugin&plugin=' . urlencode( $wpsdb_basename ) ), 'upgrade-plugin_' . $wpsdb_basename ); - echo sprintf( 'The version of %s you have installed, requires version %s of WP Migrate DB. You currently have %s installed. Update Now', $addon_name, $required, $installed, $update ); - ?> -

    +
    + Update Required — + get_plugin_name(); + $required = $this->version_required; + $installed = $GLOBALS['wpsdb_meta']['wp-sync-db']['version']; + $wpsdb_basename = sprintf( '%s/%s.php', $GLOBALS['wpsdb_meta']['wp-sync-db']['folder'], 'wp-sync-db' ); + $update = wp_nonce_url( network_admin_url( 'update.php?action=upgrade-plugin&plugin=' . urlencode( $wpsdb_basename ) ), 'upgrade-plugin_' . $wpsdb_basename ); + printf( __( 'The version of %1$s you have installed, requires version %2$s of WP Sync DB. You currently have %3$s installed. Update Now', 'wp-sync-db' ), $addon_name, $required, $installed, $update ); + ?>
    settings = get_option( 'wpsdb_settings' ); @@ -23,20 +26,26 @@ function __construct( $plugin_file_path ) { $this->addons = array( 'wp-sync-db-media-files/wp-sync-db-media-files.php' => array( 'name' => 'Media Files', - 'required_version' => '1.0.1', + 'required_version' => '1.1.4b1', + ), + 'wp-sync-db-cli/wp-sync-db-cli.php' => array( + 'name' => 'CLI', + 'required_version' => '1.0b1', ) ); + $this->invalid_content_verification_error = __( 'Invalid content verification signature, please verify the connection information on the remote site and try again.', 'wp-sync-db' ); + $this->transient_timeout = 60 * 60 * 12; $this->transient_retry_timeout = 60 * 60 * 2; $this->plugin_file_path = $plugin_file_path; $this->plugin_dir_path = plugin_dir_path( $plugin_file_path ); - $this->plugin_slug = basename( $this->plugin_dir_path ); + $this->plugin_folder_name = basename( $this->plugin_dir_path ); $this->plugin_basename = plugin_basename( $plugin_file_path ); $this->template_dir = $this->plugin_dir_path . 'template' . DS; - $this->plugin_title = ucwords( str_ireplace( '-', ' ', $this->plugin_slug ) ); - $this->plugin_title = str_ireplace( array( 'db', 'wp' ), array( 'DB', 'WP' ), $this->plugin_title ); + $this->plugin_title = ucwords( str_ireplace( '-', ' ', basename( $plugin_file_path ) ) ); + $this->plugin_title = str_ireplace( array( 'db', 'wp', '.php' ), array( 'DB', 'WP', '' ), $this->plugin_title ); if ( is_multisite() ) { $this->plugin_base = 'settings.php?page=wp-sync-db'; @@ -49,28 +58,10 @@ function __construct( $plugin_file_path ) { $this->temp_prefix = apply_filters( 'wpsdb_temporary_prefix', $this->temp_prefix ); } - function printer( $debug ) { - echo '
    ' . print_r( $debug, true ) . '
    '; - } - function template( $template ) { include $this->template_dir . $template . '.php'; } - function get_installed_version( $plugin = false ) { - if ( !is_admin() ) return false; - - $plugin_basename = ( false !== $plugin ? $plugin : $this->plugin_basename ); - - $plugins = get_plugins(); - - if ( !isset( $plugins[$plugin_basename]['Version'] ) ) { - return false; - } - - return $plugins[$plugin_basename]['Version']; - } - function open_ssl_enabled() { if ( defined( 'OPENSSL_VERSION_TEXT' ) ) { return true; @@ -82,7 +73,7 @@ function open_ssl_enabled() { function set_time_limit() { if ( !function_exists( 'ini_get' ) || !ini_get( 'safe_mode' ) ) { - set_time_limit( 0 ); + @set_time_limit( 0 ); } } @@ -117,7 +108,7 @@ function remote_post( $url, $data, $scope, $args = array(), $expecting_serial = $args['body'] = $this->array_to_multipart( $data ); } $args['headers']['Content-Type'] = 'multipart/form-data; boundary=' . $this->multipart_boundary; - $args['headers']['Referer'] = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ); + $args['headers']['Referer'] = network_admin_url( 'admin-ajax.php' ); $this->attempting_to_connect_to = $url; @@ -132,17 +123,23 @@ function remote_post( $url, $data, $scope, $args = array(), $expecting_serial = return $this->retry_remote_post( $url, $data, $scope, $args, $expecting_serial ); } else if( isset( $response->errors['http_request_failed'][0] ) && strstr( $response->errors['http_request_failed'][0], 'timed out' ) ) { - $this->error = 'The connection to the remote server has timed out, no changes have been committed. (#134 - scope: ' . $scope . ')'; + $this->error = sprintf( __( 'The connection to the remote server has timed out, no changes have been committed. (#134 - scope: %s)', 'wp-sync-db' ), $scope ); } else if ( isset( $response->errors['http_request_failed'][0] ) && ( strstr( $response->errors['http_request_failed'][0], 'Could not resolve host' ) || strstr( $response->errors['http_request_failed'][0], 'couldn\'t connect to host' ) ) ) { - $this->error = 'We could not find: ' . $_POST['url'] . '. Are you sure this is the correct URL?'; + $this->error = sprintf( __( 'We could not find: %s. Are you sure this is the correct URL?', 'wp-sync-db' ), $_POST['url'] ); $url_bits = parse_url( $_POST['url'] ); if( strstr( $_POST['url'], 'dev.' ) || strstr( $_POST['url'], '.dev' ) || ! strstr( $url_bits['host'], '.' ) ) { - $this->error .= '
    It appears that you might be trying to ' . $_POST['intent'] . ( $_POST['intent'] == 'pull' ? ' from' : ' to' ) . ' a local environment. This will not work if this website happens to be located on a remote server, it would be impossible for this server to contact your local environment.'; + $this->error .= '
    '; + if( $_POST['intent'] == 'pull' ) { + $this->error .= __( 'It appears that you might be trying to pull from a local environment. This will not work if this website happens to be located on a remote server, it would be impossible for this server to contact your local environment.', 'wp-sync-db' ); + } + else { + $this->error .= __( 'It appears that you might be trying to push to a local environment. This will not work if this website happens to be located on a remote server, it would be impossible for this server to contact your local environment.', 'wp-sync-db' ); + } } } else { - $this->error = 'The connection failed, an unexpected error occurred, please contact support. (#121 - scope: ' . $scope . ')'; + $this->error = sprintf( __( 'The connection failed, an unexpected error occurred, please contact support. (#121 - scope: %s)', 'wp-sync-db' ), $scope ); } $this->log_error( $this->error, $response ); return false; @@ -152,12 +149,12 @@ function remote_post( $url, $data, $scope, $args = array(), $expecting_serial = return $this->retry_remote_post( $url, $data, $scope, $args, $expecting_serial ); } else if( $response['response']['code'] == '401' ) { - $this->error = 'The remote site is protected with Basic Authentication. Please enter the username and password above to continue. (401 Unauthorized)'; + $this->error = __( 'The remote site is protected with Basic Authentication. Please enter the username and password above to continue. (401 Unauthorized)', 'wp-sync-db' ); $this->log_error( $this->error, $response ); return false; } else { - $this->error = 'Unable to connect to the remote server, please check the connection details - ' . $response['response']['code'] . ' ' . $response['response']['message'] . ' (#129 - scope: ' . $scope . ')'; + $this->error = sprintf( __( 'Unable to connect to the remote server, please check the connection details - %1$s %2$s (#129 - scope: %3$s)', 'wp-sync-db' ), $response['response']['code'], $response['response']['message'], $scope ); $this->log_error( $this->error, $response ); return false; } @@ -166,7 +163,7 @@ function remote_post( $url, $data, $scope, $args = array(), $expecting_serial = if( strpos( $url, 'https://' ) === 0 && $scope == 'ajax_verify_connection_to_remote_site' ) { return $this->retry_remote_post( $url, $data, $scope, $args, $expecting_serial ); } - $this->error = 'There was a problem with the AJAX request, we were expecting a serialized response, instead we received:
    ' . htmlentities( $response['body'] ); + $this->error = __( 'There was a problem with the AJAX request, we were expecting a serialized response, instead we received:
    ', 'wp-sync-db' ) . htmlentities( $response['body'] ); $this->log_error( $this->error, $response ); return false; } @@ -174,10 +171,16 @@ function remote_post( $url, $data, $scope, $args = array(), $expecting_serial = if( strpos( $url, 'https://' ) === 0 && $scope == 'ajax_verify_connection_to_remote_site' ) { return $this->retry_remote_post( $url, $data, $scope, $args, $expecting_serial ); } - $this->error = 'WP Migrate DB does not seem to be installed or active on the remote site. (#131 - scope: ' . $scope . ')'; + $this->error = sprintf( __( 'WP Sync DB does not seem to be installed or active on the remote site. (#131 - scope: %s)', 'wp-sync-db' ), $scope ); $this->log_error( $this->error, $response ); return false; } + elseif ( $expecting_serial && is_serialized( $response['body'] ) == true && $scope == 'ajax_verify_connection_to_remote_site' ) { + $unserialized_response = unserialize( $response['body'] ); + if ( isset( $unserialized_response['error'] ) && '1' == $unserialized_response['error'] && strpos( $url, 'https://' ) === 0 ) { + return $this->retry_remote_post( $url, $data, $scope, $args, $expecting_serial ); + } + } return $response['body']; } @@ -270,6 +273,9 @@ function display_errors() { } function filter_post_elements( $post_array, $accepted_elements ) { + if ( isset( $post_array['form_data'] ) ) { + $post_array['form_data'] = stripslashes( $post_array['form_data'] ); + } $accepted_elements[] = 'sig'; return array_intersect_key( $post_array, array_flip( $accepted_elements ) ); } @@ -286,6 +292,9 @@ function verify_signature( $data, $key ) { if( empty( $data['sig'] ) ) { return false; } + if ( isset( $data['nonce'] ) ) { + unset( $data['nonce'] ); + } $temp = $data; $computed_signature = $this->create_signature( $temp, $key ); return $computed_signature === $data['sig']; @@ -314,6 +323,10 @@ function get_plugin_name( $plugin = false ) { return $plugins[$plugin_basename]['Name']; } + function get_class_props() { + return get_object_vars( $this ); + } + // Get only the table beginning with our DB prefix or temporary prefix, also skip views function get_tables( $scope = 'regular' ) { global $wpdb; @@ -334,7 +347,10 @@ function plugins_dir() { } function is_addon_outdated( $addon_basename ) { - $installed_version = $this->get_installed_version( $addon_basename ); + $addon_slug = current( explode( '/', $addon_basename ) ); + // If pre-1.1.2 version of Media Files addon, then it is outdated + if ( ! isset( $GLOBALS['wpsdb_meta'][$addon_slug]['version'] ) ) return true; + $installed_version = $GLOBALS['wpsdb_meta'][$addon_slug]['version']; $required_version = $this->addons[$addon_basename]['required_version']; return version_compare( $installed_version, $required_version, '<' ); } @@ -343,4 +359,33 @@ function get_plugin_file_path() { return $this->plugin_file_path; } + function set_cli_migration() { + $this->doing_cli_migration = true; + } + + function end_ajax( $return = false ) { + if( defined( 'DOING_WPSDB_TESTS' ) || $this->doing_cli_migration ) { + return ( false === $return ) ? NULL : $return; + } + + echo ( false === $return ) ? '' : $return; + exit; + } + + function check_ajax_referer( $action ) { + if ( defined( 'DOING_WPSDB_TESTS' ) || $this->doing_cli_migration ) return; + $result = check_ajax_referer( $action, 'nonce', false ); + if ( false === $result ) { + $return = array( 'wpsdb_error' => 1, 'body' => sprintf( __( 'Invalid nonce for: %s', 'wp-sync-db' ), $action ) ); + $this->end_ajax( json_encode( $return ) ); + } + + $cap = ( is_multisite() ) ? 'manage_network_options' : 'export'; + $cap = apply_filters( 'wpsdb_ajax_cap', $cap ); + if ( !current_user_can( $cap ) ) { + $return = array( 'wpsdb_error' => 1, 'body' => sprintf( __( 'Access denied for: %s', 'wp-sync-db' ), $action ) ); + $this->end_ajax( json_encode( $return ) ); + } + } + } diff --git a/class/wpsdb.php b/class/wpsdb.php index da08fed..7de84d2 100755 --- a/class/wpsdb.php +++ b/class/wpsdb.php @@ -22,6 +22,9 @@ class WPSDB extends WPSDB_Base { function __construct( $plugin_file_path ) { parent::__construct( $plugin_file_path ); + $this->plugin_slug = 'wp-sync-db'; + $this->plugin_version = $GLOBALS['wpsdb_meta']['wp-sync-db']['version']; + $this->max_insert_string_len = 50000; // 50000 is the default as defined by phphmyadmin $default_settings = array( @@ -30,6 +33,7 @@ function __construct( $plugin_file_path ) { 'allow_push' => false, 'profiles' => array(), 'verify_ssl' => false, + 'blacklist_plugins' => array(), ); if( empty( $this->settings['max_request'] ) ) { @@ -76,6 +80,9 @@ function __construct( $plugin_file_path ) { add_action( 'wp_ajax_wpsdb_get_log', array( $this, 'ajax_get_log' ) ); add_action( 'wp_ajax_wpsdb_fire_migration_complete', array( $this, 'fire_migration_complete' ) ); add_action( 'wp_ajax_wpsdb_update_max_request_size', array( $this, 'ajax_update_max_request_size' ) ); + add_action( 'wp_ajax_wpsdb_plugin_compatibility', array( $this, 'ajax_plugin_compatibility' ) ); + add_action( 'wp_ajax_wpsdb_blacklist_plugins', array( $this, 'ajax_blacklist_plugins' ) ); + add_action( 'wp_ajax_wpsdb_cancel_migration', array( $this, 'ajax_cancel_migration' ) ); // external AJAX handlers add_action( 'wp_ajax_nopriv_wpsdb_verify_connection_to_remote_site', array( $this, 'respond_to_verify_connection_to_remote_site' ) ); @@ -85,6 +92,10 @@ function __construct( $plugin_file_path ) { add_action( 'wp_ajax_nopriv_wpsdb_fire_migration_complete', array( $this, 'fire_migration_complete' ) ); add_action( 'wp_ajax_nopriv_wpsdb_backup_remote_table', array( $this, 'respond_to_backup_remote_table' ) ); add_action( 'wp_ajax_nopriv_wpsdb_remote_finalize_migration', array( $this, 'respond_to_remote_finalize_migration' ) ); + add_action( 'wp_ajax_nopriv_wpsdb_process_push_migration_cancellation', array( $this, 'respond_to_process_push_migration_cancellation' ) ); + + // Clear update transients when the user clicks the "Check Again" button from the update screen + add_action( 'current_screen', array( $this, 'check_again_clear_transients' ) ); $absolute_path = rtrim( ABSPATH, '\\/' ); $site_url = rtrim( site_url( '', 'http' ), '\\/' ); @@ -114,10 +125,11 @@ function __construct( $plugin_file_path ) { 'create_backup', 'remove_backup', 'keep_active_plugins', - 'post_type_migrate_option', 'select_post_types', 'backup_option', 'select_backup', + 'exclude_transients', + 'exclude_post_types' ); $this->default_profile = array( @@ -129,9 +141,9 @@ function __construct( $plugin_file_path ) { 'default_profile' => true, 'name' => '', 'select_tables' => array(), - 'post_type_migrate_option' => 'migrate_all_post_types', 'select_post_types' => array(), - 'backup_option' => 'backup_only_with_prefix' + 'backup_option' => 'backup_only_with_prefix', + 'exclude_transients' => '1', ); $this->checkbox_options = array( @@ -140,7 +152,8 @@ function __construct( $plugin_file_path ) { 'replace_guids' => '0', 'exclude_spam' => '0', 'keep_active_plugins' => '0', - 'create_backup' => '0' + 'create_backup' => '0', + 'exclude_post_types' =>'0' ); if ( is_multisite() ) { @@ -165,6 +178,34 @@ function __construct( $plugin_file_path ) { } } + function ajax_blacklist_plugins() { + $this->settings['blacklist_plugins'] = $_POST['blacklist_plugins']; + update_option( 'wpsdb_settings', $this->settings ); + exit; + } + + function ajax_plugin_compatibility() { + $mu_dir = ( defined( 'WPMU_PLUGIN_DIR' ) && defined( 'WPMU_PLUGIN_URL' ) ) ? WPMU_PLUGIN_DIR : trailingslashit( WP_CONTENT_DIR ) . 'mu-plugins'; + $source = trailingslashit( $this->plugin_dir_path ) . 'compatibility/wp-sync-db-compatibility.php'; + $dest = trailingslashit( $mu_dir ) . 'wp-sync-db-compatibility.php'; + if ( '1' === trim( $_POST['install'] ) ) { // install MU plugin + if ( !wp_mkdir_p( $mu_dir ) ) { + _e( sprintf( 'The following directory could not be created: %s', $mu_dir ), 'wp-sync-db' ); + exit; + } + if ( !copy( $source, $dest ) ) { + _e( sprintf( 'Could not copy the compatibility plugin from %1$s to %2$s', $source, $destination ), 'wp-sync-db' ); + exit; + } + } else { // uninstall MU plugin + if ( file_exists( $dest ) && !unlink( $dest ) ) { + _e( sprintf( 'Could not remove the compatibility plugin from %s', $dest ), 'wp-sync-db' ); + exit; + } + } + exit; + } + function check_again_clear_transients( $current_screen ) { if( ! isset( $current_screen->id ) || strpos( $current_screen->id, 'update-core' ) === false || ! isset( $_GET['force-check'] ) ) return; delete_site_transient( 'wpsdb_upgrade_data' ); @@ -235,6 +276,7 @@ function get_upload_info( $type = 'path' ) { } function ajax_update_max_request_size() { + $this->check_ajax_referer( 'update-max-request-size' ); $this->settings['max_request'] = (int) $_POST['max_request_size'] * 1024; update_option( 'wpsdb_settings', $this->settings ); $result = $this->end_ajax(); @@ -272,12 +314,14 @@ function plugin_action_links( $links ) { } function ajax_clear_log() { + $this->check_ajax_referer( 'clear-log' ); delete_option( 'wpsdb_error_log' ); $result = $this->end_ajax(); return $result; } function ajax_get_log() { + $this->check_ajax_referer( 'get-log' ); ob_start(); $this->output_diagnostic_info(); $this->output_log_file(); @@ -295,102 +339,107 @@ function output_log_file() { function output_diagnostic_info() { global $table_prefix; + global $wpdb; - _e( 'site_url()', 'wp-app-store' ); echo ': '; + echo 'site_url(): '; echo site_url(); echo "\r\n"; - _e( 'home_url()', 'wp-app-store' ); echo ': '; + echo 'home_url(): '; echo home_url(); echo "\r\n"; - _e( 'Table Prefix', 'wp-app-store' ); echo ': '; + echo 'Table Prefix: '; echo $table_prefix; echo "\r\n"; - _e( 'WordPress', 'wp-app-store' ); echo ': '; + echo 'WordPress: '; if ( is_multisite() ) echo 'WPMU'; else echo 'WP'; echo bloginfo('version'); echo "\r\n"; - _e( 'Web Server', 'wp-app-store' ); echo ': '; + echo 'Web Server: '; echo $_SERVER['SERVER_SOFTWARE']; echo "\r\n"; - _e( 'PHP', 'wp-app-store' ); echo ': '; + echo 'PHP: '; if ( function_exists( 'phpversion' ) ) echo esc_html( phpversion() ); echo "\r\n"; - _e( 'MySQL', 'wp-app-store' ); echo ': '; - if ( function_exists( 'mysql_get_server_info' ) ) echo esc_html( mysql_get_server_info() ); + echo 'MySQL: '; + echo esc_html( empty( $wpdb->use_mysqli ) ? mysql_get_server_info() : mysqli_get_server_info( $wpdb->dbh ) ); + echo "\r\n"; + + _e( 'ext/mysqli', 'wp-app-store' ); echo ': '; + echo empty( $wpdb->use_mysqli ) ? 'no' : 'yes'; echo "\r\n"; _e( 'WP Memory Limit', 'wp-app-store' ); echo ': '; echo WP_MEMORY_LIMIT; echo "\r\n"; - _e( 'WPSDB Bottleneck', 'wp-app-store' ); echo ': '; + echo 'WPSDB Bottleneck: '; echo size_format( $this->get_bottleneck() ); echo "\r\n"; if ( function_exists( 'ini_get' ) && $suhosin_limit = ini_get( 'suhosin.post.max_value_length' ) ) { - _e( 'Suhosin Post Max Value Length', 'wp-app-store' ); echo ': '; + echo 'Suhosin Post Max Value Length: '; echo is_numeric( $suhosin_limit ) ? size_format( $suhosin_limit ) : $suhosin_limit; echo "\r\n"; } if ( function_exists( 'ini_get' ) && $suhosin_limit = ini_get( 'suhosin.request.max_value_length' ) ) { - _e( 'Suhosin Request Max Value Length', 'wp-app-store' ); echo ': '; + echo 'Suhosin Request Max Value Length: '; echo is_numeric( $suhosin_limit ) ? size_format( $suhosin_limit ) : $suhosin_limit; echo "\r\n"; } - _e( 'Debug Mode', 'wp-app-store' ); echo ': '; + echo 'Debug Mode: '; if ( defined('WP_DEBUG') && WP_DEBUG ) { echo 'Yes'; } else { echo 'No'; } echo "\r\n"; - _e( 'WP Max Upload Size', 'wp-app-store' ); echo ': '; + echo 'WP Max Upload Size: '; echo size_format( wp_max_upload_size() ); echo "\r\n"; - _e( 'PHP Post Max Size', 'wp-app-store' ); echo ': '; + echo 'PHP Post Max Size: '; echo size_format( $this->get_post_max_size() ); echo "\r\n"; - _e( 'PHP Time Limit', 'wp-app-store' ); echo ': '; + echo 'PHP Time Limit: '; if ( function_exists( 'ini_get' ) ) echo ini_get('max_execution_time'); echo "\r\n"; - _e( 'PHP Error Log', 'wp-app-store' ); echo ': '; + echo 'PHP Error Log: '; if ( function_exists( 'ini_get' ) ) echo ini_get('error_log'); echo "\r\n"; - _e( 'fsockopen', 'wp-app-store' ); echo ': '; + echo 'fsockopen: '; if ( function_exists( 'fsockopen' ) ) { - _e('Enabled', 'wp-app-store' ); + echo 'Enabled'; } else { - _e( 'Disabled', 'wp-app-store' ); + echo 'Disabled'; } echo "\r\n"; - _e( 'OpenSSL', 'wp-app-store' ); echo ': '; + echo 'OpenSSL: '; if ( $this->open_ssl_enabled() ) { echo OPENSSL_VERSION_TEXT; } else { - _e( 'Disabled', 'wp-app-store' ); + echo 'Disabled'; } echo "\r\n"; - _e( 'cURL', 'wp-app-store' ); echo ': '; + echo 'cURL: '; if ( function_exists( 'curl_init' ) ) { - _e('Enabled', 'wp-app-store' ); + echo 'Enabled'; } else { - _e( 'Disabled', 'wp-app-store' ); + echo 'Disabled'; } echo "\r\n"; echo "\r\n"; - _e( 'Active Plugins', 'wp-app-store' ); echo ":\r\n"; + echo "Active Plugins:\r\n"; $active_plugins = (array) get_option( 'active_plugins', array() ); @@ -402,7 +451,7 @@ function output_diagnostic_info() { foreach ( $active_plugins as $plugin ) { $plugin_data = @get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ); if ( empty( $plugin_data['Name'] ) ) continue; - echo $plugin_data['Name'] . ' (v' . $plugin_data['Version'] . ') ' . __( 'by', 'wp-app-store' ) . ' ' . $plugin_data['AuthorName'] . "\r\n"; + printf( "%s (v%s) by %s\r\n", $plugin_data['Name'], $plugin_data['Version'], $plugin_data['AuthorName'] ); } echo "\r\n"; @@ -416,7 +465,9 @@ function remove_wp_plugin_dir( $name ) { function fire_migration_complete() { $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'url' ) ); if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { - $result = $this->end_ajax( $this->invalid_content_verification_error . ' (#138)' ); + $error_msg = $this->invalid_content_verification_error . ' (#138)'; + $this->log_error( $error_msg, $filtered_post ); + $result = $this->end_ajax( $error_msg ); return $result; } @@ -440,6 +491,7 @@ function get_alter_queries() { // After table migration, delete old tables and rename new tables removing the temporarily prefix function ajax_finalize_migration() { + $this->check_ajax_referer( 'finalize-migration' ); global $wpdb; $return = ''; if ( $_POST['intent'] == 'pull' ) { @@ -448,6 +500,9 @@ function ajax_finalize_migration() { else { do_action( 'wpsdb_migration_complete', 'push', $_POST['url'] ); $data = $_POST; + if ( isset( $data['nonce'] ) ) { + unset( $data['nonce'] ); + } $data['action'] = 'wpsdb_remote_finalize_migration'; $data['intent'] = 'pull'; $data['prefix'] = $wpdb->prefix; @@ -469,7 +524,9 @@ function ajax_finalize_migration() { function respond_to_remote_finalize_migration() { $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent', 'url', 'key', 'form_data', 'prefix', 'type', 'location', 'tables', 'temp_prefix' ) ); if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { - $result = $this->end_ajax( $this->invalid_content_verification_error . ' (#123)' ); + $error_msg = $this->invalid_content_verification_error . ' (#123)'; + $this->log_error( $error_msg, $filtered_post ); + $result = $this->end_ajax( $error_msg ); return $result; } $return = $this->finalize_migration(); @@ -559,12 +616,12 @@ function ajax_process_chunk() { $tmp_file_path = wp_tempnam( $tmp_file_name ); if ( !isset( $_FILES['chunk']['tmp_name'] ) || !move_uploaded_file( $_FILES['chunk']['tmp_name'], $tmp_file_path ) ) { - $result = $this->end_ajax( 'Could not upload the SQL to the server. (#135)' ); + $result = $this->end_ajax( __( 'Could not upload the SQL to the server. (#135)', 'wp-sync-db' ) ); return $result; } if ( false === ( $chunk = file_get_contents( $tmp_file_path ) ) ) { - $result = $this->end_ajax( 'Could not read the SQL we\'ve uploaded to the server. (#136)' ); + $result = $this->end_ajax( __( 'Could not read the SQL file we uploaded to the server. (#136)', 'wp-sync-db' ) ); return $result; } @@ -573,12 +630,14 @@ function ajax_process_chunk() { $filtered_post['chunk'] = $chunk; if ( !$this->verify_signature( $filtered_post, $this->settings['key'] ) ) { - $result = $this->end_ajax( $this->invalid_content_verification_error . ' (#130)' ); + $error_msg = $this->invalid_content_verification_error . ' (#130)'; + $this->log_error( $error_msg, $filtered_post ); + $result = $this->end_ajax( $error_msg ); return $result; } if ( $this->settings['allow_push'] != true ) { - $result = $this->end_ajax( 'The connection succeeded but the remote site is configured to reject push connections. You can change this in the "settings" tab on the remote site. (#133)' ); + $result = $this->end_ajax( __( 'The connection succeeded but the remote site is configured to reject push connections. You can change this in the "settings" tab on the remote site. (#133)', 'wp-sync-db' ) ); return $result; } @@ -617,6 +676,7 @@ function process_chunk( $chunk ) { } function ajax_migrate_table() { + $this->check_ajax_referer( 'migrate-table' ); global $wpdb; $this->form_data = $this->parse_migration_form_data( $_POST['form_data'] ); @@ -627,6 +687,9 @@ function ajax_migrate_table() { // if performing a push we need to backup the REMOTE machine's DB if ( $_POST['intent'] == 'push' ) { $data = $_POST; + if ( isset( $data['nonce'] ) ) { + unset( $data['nonce'] ); + } $data['action'] = 'wpsdb_backup_remote_table'; $data['intent'] = 'pull'; $ajax_url = trailingslashit( $_POST['url'] ) . 'wp-admin/admin-ajax.php'; @@ -676,6 +739,9 @@ function ajax_migrate_table() { } else { $data = $_POST; + if ( isset( $data['nonce'] ) ) { + unset( $data['nonce'] ); + } $data['action'] = 'wpsdb_process_pull_request'; $data['pull_limit'] = $this->get_sensible_pull_limit(); if( is_multisite() ) { @@ -732,7 +798,9 @@ function respond_to_backup_remote_table() { $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent', 'url', 'key', 'table', 'form_data', 'stage', 'bottleneck', 'prefix', 'current_row', 'dump_filename', 'last_table', 'gzip', 'primary_keys', 'path_current_site', 'domain_current_site' ) ); $filtered_post['primary_keys'] = stripslashes( $filtered_post['primary_keys'] ); if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { - $result = $this->end_ajax( $this->invalid_content_verification_error . ' (#137)' ); + $error_msg = $this->invalid_content_verification_error . ' (#137)'; + $this->log_error( $error_msg, $filtered_post ); + $result = $this->end_ajax( $error_msg ); return $result; } @@ -779,12 +847,14 @@ function respond_to_process_pull_request() { } if ( ! $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { - $result = $this->end_ajax( $this->invalid_content_verification_error . ' (#124)' ); + $error_msg = $this->invalid_content_verification_error . ' (#124)'; + $this->log_error( $error_msg, $filtered_post ); + $result = $this->end_ajax( $error_msg ); return $result; } if ( $this->settings['allow_pull'] != true ) { - $result = $this->end_ajax( 'The connection succeeded but the remote site is configured to reject pull connections. You can change this in the "settings" tab on the remote site. (#132)' ); + $result = $this->end_ajax( __( 'The connection succeeded but the remote site is configured to reject pull connections. You can change this in the "settings" tab on the remote site. (#132)', 'wp-sync-db' ) ); return $result; } @@ -800,6 +870,7 @@ function respond_to_process_pull_request() { // Occurs right before the first table is migrated / backed up during the migration process // Does a quick check to make sure the verification string is valid and also opens / creates files for writing to (if required) function ajax_initiate_migration() { + $this->check_ajax_referer( 'initiate-migration' ); $this->form_data = $this->parse_migration_form_data( $_POST['form_data'] ); if ( $_POST['intent'] == 'savefile' ) { @@ -849,7 +920,21 @@ function ajax_initiate_migration() { return $result; } - $return = json_decode( stripslashes( $response ), ARRAY_A ); + $return = @unserialize( trim( $response ) ); + + if ( false === $return ) { + $error_msg = __( 'Failed attempting to unserialize the response from the remote server. Please contact support.', 'wp-sync-db' ); + $return = array( 'wpsdb_error' => 1, 'body' => $error_msg ); + $this->log_error( $error_msg, $response ); + $result = $this->end_ajax( json_encode( $return ) ); + return $result; + } + + if ( isset( $return['error'] ) && $return['error'] == 1 ) { + $return = array( 'wpsdb_error' => 1, 'body' => $return['message'] ); + $result = $this->end_ajax( json_encode( $return ) ); + return $result; + } if( $_POST['intent'] == 'pull' ) { // sets up our table to store 'ALTER' queries @@ -881,17 +966,25 @@ function respond_to_remote_initiate_migration() { $return = array(); $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent', 'form_data' ) ); if ( $this->verify_signature( $filtered_post, $this->settings['key'] ) ) { - if ( isset( $this->settings['allow_' . $_POST['intent']] ) && $this->settings['allow_' . $_POST['intent']] == true ) { + if ( isset( $this->settings['allow_' . $_POST['intent']] ) && ( true === $this->settings['allow_' . $_POST['intent']] || 1 === $this->settings['allow_' . $_POST['intent']] ) ) { $return['error'] = 0; } else { $return['error'] = 1; - $return['message'] = 'The connection succeeded but the remote site is configured to reject ' . $_POST['intent'] . ' connections. You can change this in the "settings" tab on the remote site. (#110)'; + if( $_POST['intent'] == 'pull' ) { + $intent = __( 'pull', 'wp-sync-db' ); + } + else { + $intent = __( 'push', 'wp-sync-db' ); + } + $return['message'] = sprintf( __( 'The connection succeeded but the remote site is configured to reject %s connections. You can change this in the "settings" tab on the remote site. (#110)', 'wp-sync-db'), $intent ); } } else { $return['error'] = 1; - $return['message'] = $this->invalid_content_verification_error . ' (#111)'; + $error_msg = $this->invalid_content_verification_error . ' (#111)'; + $this->log_error( $error_msg, $filtered_post ); + $return['message'] = $error_msg; } $this->form_data = $this->parse_migration_form_data( $_POST['form_data'] ); @@ -911,11 +1004,12 @@ function respond_to_remote_initiate_migration() { } } - $result = $this->end_ajax( json_encode( $return ) ); + $result = $this->end_ajax( serialize( $return ) ); return $result; } function ajax_save_profile() { + $this->check_ajax_referer( 'save-profile' ); $profile = $this->parse_migration_form_data( $_POST['profile'] ); $profile = wp_parse_args( $profile, $this->checkbox_options ); if ( isset( $profile['save_migration_profile_option'] ) && $profile['save_migration_profile_option'] == 'new' ) { @@ -929,11 +1023,14 @@ function ajax_save_profile() { $this->settings['profiles'][$key]['name'] = $name; } update_option( 'wpsdb_settings', $this->settings ); - $result = $this->end_ajax( count( $this->settings['profiles'] ) - 1 ); + end( $this->settings['profiles'] ); + $key = key( $this->settings['profiles'] ); + $result = $this->end_ajax( $key ); return $result; } function ajax_save_setting() { + $this->check_ajax_referer( 'save-setting' ); $this->settings[$_POST['setting']] = ( $_POST['checked'] == 'false' ? false : true ); update_option( 'wpsdb_settings', $this->settings ); $result = $this->end_ajax(); @@ -941,7 +1038,9 @@ function ajax_save_setting() { } function ajax_delete_migration_profile() { - $key = $_POST['profile_id']; + $this->check_ajax_referer( 'delete-migration-profile' ); + $key = absint( $_POST['profile_id'] ); + --$key; $return = ''; if ( isset( $this->settings['profiles'][$key] ) ) { unset( $this->settings['profiles'][$key] ); @@ -955,6 +1054,7 @@ function ajax_delete_migration_profile() { } function ajax_reset_api_key() { + $this->check_ajax_referer( 'reset-api-key' ); $this->settings['key'] = $this->generate_key(); update_option( 'wpsdb_settings', $this->settings ); $result = $this->end_ajax( sprintf( "%s\n%s", site_url( '', 'https' ), $this->settings['key'] ) ); @@ -964,6 +1064,7 @@ function ajax_reset_api_key() { // AJAX endpoint for when the user pastes into the connection info box (or when they click "connect") // Responsible for contacting the remote website and retrieving info and testing the verification string function ajax_verify_connection_to_remote_site() { + $this->check_ajax_referer( 'verify-connection-to-remote-site' ); $data = array( 'action' => 'wpsdb_verify_connection_to_remote_site', 'intent' => $_POST['intent'] @@ -986,12 +1087,30 @@ function ajax_verify_connection_to_remote_site() { $response = unserialize( trim( $response ) ); + if ( false === $response ) { + $error_msg = __( 'Failed attempting to unserialize the response from the remote server. Please contact support.', 'wp-sync-db' ); + $return = array( 'wpsdb_error' => 1, 'body' => $error_msg ); + $this->log_error( $error_msg ); + $result = $this->end_ajax( json_encode( $return ) ); + return $result; + } + if ( isset( $response['error'] ) && $response['error'] == 1 ) { $return = array( 'wpsdb_error' => 1, 'body' => $response['message'] ); + $this->log_error( $response['message'], $response ); $result = $this->end_ajax( json_encode( $return ) ); return $result; } + if ( isset( $_POST['convert_post_type_selection'] ) && '1' == $_POST['convert_post_type_selection'] ) { + $profile = (int) $_POST['profile']; + unset( $this->settings['profiles'][$profile]['post_type_migrate_option'] ); + $this->settings['profiles'][$profile]['exclude_post_types'] = '1'; + $this->settings['profiles'][$profile]['select_post_types'] = array_values( array_diff( $response['post_types'], $this->settings['profiles'][$profile]['select_post_types'] ) ); + $response['select_post_types'] = $this->settings['profiles'][$profile]['select_post_types']; + update_option( 'wpsdb_settings', $this->settings ); + } + $response['scheme'] = $url_bits['scheme']; $return = json_encode( $response ); @@ -1008,14 +1127,21 @@ function respond_to_verify_connection_to_remote_site() { $filtered_post = $this->filter_post_elements( $_POST, array( 'action', 'intent' ) ); if ( !$this->verify_signature( $filtered_post, $this->settings['key'] ) ) { $return['error'] = 1; - $return['message'] = $this->invalid_content_verification_error . ' (#120) Try again?'; + $return['message'] = $this->invalid_content_verification_error . ' (#120) ' . __( 'Try again?', 'wp-sync-db' ) . ''; + $this->log_error( $this->invalid_content_verification_error . ' (#120)', $filtered_post ); $result = $this->end_ajax( serialize( $return ) ); return $result; } if ( !isset( $this->settings['allow_' . $_POST['intent']] ) || $this->settings['allow_' . $_POST['intent']] != true ) { $return['error'] = 1; - $return['message'] = 'The connection succeeded but the remote site is configured to reject ' . $_POST['intent'] . ' connections. You can change this in the "settings" tab on the remote site. (#122) Try again?'; + if( $_POST['intent'] == 'pull' ) { + $intent = __( 'pull', 'wp-sync-db' ); + } + else { + $intent = __( 'push', 'wp-sync-db' ); + } + $return['message'] = sprintf( __( 'The connection succeeded but the remote site is configured to reject %s connections. You can change this in the "settings" tab on the remote site. (#122) Try again?', 'wp-sync-db' ), $intent ); $result = $this->end_ajax( serialize( $return ) ); return $result; } @@ -1030,7 +1156,7 @@ function respond_to_verify_connection_to_remote_site() { $return['prefix'] = $wpdb->prefix; $return['bottleneck'] = $this->get_bottleneck(); $return['error'] = 0; - $return['plugin_version'] = $this->get_installed_version(); + $return['plugin_version'] = $this->plugin_version; $return['domain'] = $this->get_domain_current_site(); $return['path_current_site'] = $this->get_path_current_site(); $return['uploads_dir'] = $this->get_short_uploads_dir(); @@ -1089,6 +1215,7 @@ function get_post_types() { // Retrieves the specified profile, if -1, returns the default profile function get_profile( $profile_id ) { + --$profile_id; if ( $profile_id == '-1' || ! isset( $this->settings['profiles'][$profile_id] ) ) { return $this->default_profile; } @@ -1192,7 +1319,7 @@ function options_page() {

    Migrate DB

    - + @@ -1202,62 +1329,48 @@ function options_page() { foreach( $this->addons as $addon_basename => $addon ) { if( false == $this->is_addon_outdated( $addon_basename ) || false == is_plugin_active( $addon_basename ) ) continue; $update_url = wp_nonce_url( network_admin_url( 'update.php?action=upgrade-plugin&plugin=' . urlencode( $addon_basename ) ), 'upgrade-plugin_' . $addon_basename ); + $addon_slug = current( explode( '/', $addon_basename ) ); + if ( isset( $GLOBALS['wpsdb_meta'][$addon_slug]['version'] ) ) { + $version = ' (' . $GLOBALS['wpsdb_meta'][$addon_slug]['version'] . ')'; + } + else { + $version = ''; + } ?> -
    -

    - Update Required — - Update Now', $addon['name'], $this->get_installed_version( $addon_basename ), $update_url ); ?> -

    +
    + Update Required — + Update Now', 'wp-sync-db' ), $addon['name'], $version, $update_url ); ?>
    -
    -

    - PHP Safe Mode Enabled — - We do not officially support running this plugin in - safe mode because set_time_limit() - has no effect. Therefore we can't extend the run time of the - script and ensure it doesn't time out before the migration completes. - We haven't disabled the plugin however, so you're free to cross your - fingers and hope for the best. However, if you have trouble, - we can't help you until you turn off safe mode. - - Your current PHP run time limit is set to seconds. - -

    + if ( function_exists( 'ini_get' ) && ini_get( 'safe_mode' ) && !$hide_warning ) { ?> +
    + PHP Safe Mode Enabled — We do not officially support running this plugin in safe mode because set_time_limit() has no effect. Therefore we can't extend the run time of the script and ensure it doesn't time out before the migration completes. We haven't disabled the plugin however, so you're free to cross your fingers and hope for the best. However, if you have trouble, we can't help you until you turn off safe mode.", 'wp-sync-db' ); + if ( function_exists( 'ini_get' ) ) { + printf( __( 'Your current PHP run time limit is set to %s seconds.', 'wp-sync-db' ), ini_get( 'max_execution_time' ) ); + } ?>
    - -
    - get_post_types(); ?> -
    - -
    Post Types
    -
    - -