Merge pull request #888 from mailpoet/mp2tomp3migration
MP2 to MP3 migration [MAILPOET-946]
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -19,3 +19,4 @@ assets/js/*.js
|
||||
.vagrant
|
||||
lang
|
||||
.mp_svn
|
||||
/nbproject/
|
@@ -22,3 +22,5 @@
|
||||
@require 'progress_bar'
|
||||
|
||||
@require 'subscribers'
|
||||
|
||||
@require 'mp2migrator'
|
||||
|
33
assets/css/src/mp2migrator.styl
Normal file
33
assets/css/src/mp2migrator.styl
Normal file
@@ -0,0 +1,33 @@
|
||||
#logger
|
||||
width: 100%
|
||||
height: 300px
|
||||
background-color: transparent
|
||||
border: 0
|
||||
border-top: 1px #aba9a9 solid
|
||||
padding: 2px
|
||||
overflow: scroll
|
||||
resize: both
|
||||
font-size: 0.85em
|
||||
margin-top: 20px
|
||||
|
||||
#progressbar
|
||||
width: 50%
|
||||
background-color: #d8d8d8
|
||||
border-radius: 5px
|
||||
|
||||
progressbar_color = #fecf23
|
||||
progressbar_gradient_to_color = #fd9215
|
||||
|
||||
.ui-progressbar .ui-progressbar-value
|
||||
height: 100%
|
||||
background-color: progressbar_color
|
||||
background-image: linear-gradient(to bottom, progressbar_color, progressbar_gradient_to_color)
|
||||
border-radius: 3px
|
||||
box-shadow: 0 1px 0 rgba(255,255,255,0.5) inset
|
||||
border 0
|
||||
|
||||
.mailpoet_progress_label
|
||||
font-size: 15px
|
||||
|
||||
.error_msg
|
||||
color: #f00
|
187
assets/js/src/mp2migrator.js
Normal file
187
assets/js/src/mp2migrator.js
Normal file
@@ -0,0 +1,187 @@
|
||||
define('mp2migrator', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
|
||||
'use strict';
|
||||
MailPoet.MP2Migrator = {
|
||||
|
||||
fatal_error: '',
|
||||
is_logging: false,
|
||||
|
||||
startLogger: function () {
|
||||
MailPoet.MP2Migrator.is_logging = true;
|
||||
clearTimeout(MailPoet.MP2Migrator.displayLogs_timeout);
|
||||
clearTimeout(MailPoet.MP2Migrator.updateProgressbar_timeout);
|
||||
clearTimeout(MailPoet.MP2Migrator.update_wordpress_info_timeout);
|
||||
setTimeout(MailPoet.MP2Migrator.updateDisplay, 1000)
|
||||
},
|
||||
|
||||
stopLogger: function () {
|
||||
MailPoet.MP2Migrator.is_logging = false;
|
||||
},
|
||||
|
||||
updateDisplay: function () {
|
||||
MailPoet.MP2Migrator.displayLogs();
|
||||
MailPoet.MP2Migrator.updateProgressbar();
|
||||
},
|
||||
|
||||
displayLogs: function () {
|
||||
jQuery.ajax({
|
||||
url: mailpoet_mp2_migrator.log_file_url,
|
||||
cache: false
|
||||
}).done(function (result) {
|
||||
jQuery("#logger").html('');
|
||||
result.split("\n").forEach(function (row) {
|
||||
if(row.substr(0, 7) === '[ERROR]' || row.substr(0, 9) === '[WARNING]' || row === MailPoet.I18n.t('import_stopped_by_user')) {
|
||||
row = '<span class="error_msg">' + row + '</span>'; // Mark the errors in red
|
||||
}
|
||||
// Test if the import is complete
|
||||
else if(row === MailPoet.I18n.t('import_complete')) {
|
||||
jQuery('#import-actions').hide();
|
||||
jQuery('#upgrade-completed').show();
|
||||
}
|
||||
jQuery("#logger").append(row + "<br />\n");
|
||||
|
||||
});
|
||||
jQuery("#logger").append('<span class="error_msg">' + MailPoet.MP2Migrator.fatal_error + '</span>' + "<br />\n");
|
||||
}).always(function () {
|
||||
if(MailPoet.MP2Migrator.is_logging) {
|
||||
MailPoet.MP2Migrator.displayLogs_timeout = setTimeout(MailPoet.MP2Migrator.displayLogs, 1000);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updateProgressbar: function () {
|
||||
jQuery.ajax({
|
||||
url: mailpoet_mp2_migrator.progress_url,
|
||||
cache: false,
|
||||
dataType: 'json'
|
||||
}).always(function (result) {
|
||||
// Move the progress bar
|
||||
var progress = 0;
|
||||
if((result.total !== undefined) && (Number(result.total) !== 0)) {
|
||||
progress = Math.round(Number(result.current) / Number(result.total) * 100);
|
||||
}
|
||||
jQuery('#progressbar').progressbar('option', 'value', progress);
|
||||
jQuery('#progresslabel').html(progress + '%');
|
||||
if(Number(result.current !== 0)) {
|
||||
jQuery('#skip-import').hide();
|
||||
}
|
||||
if(MailPoet.MP2Migrator.is_logging) {
|
||||
MailPoet.MP2Migrator.updateProgressbar_timeout = setTimeout(MailPoet.MP2Migrator.updateProgressbar, 1000);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
startImport: function () {
|
||||
MailPoet.MP2Migrator.fatal_error = '';
|
||||
// Start displaying the logs
|
||||
MailPoet.MP2Migrator.startLogger();
|
||||
|
||||
// Disable the import button
|
||||
MailPoet.MP2Migrator.import_button_label = jQuery('#import').val();
|
||||
jQuery('#import').val(MailPoet.I18n.t('importing')).attr('disabled', 'disabled');
|
||||
// Hide the Skip button
|
||||
jQuery('#skip-import').hide();
|
||||
// Show the stop button
|
||||
jQuery('#stop-import').show();
|
||||
|
||||
// Run the import
|
||||
MailPoet.Ajax.post({
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'MP2Migrator',
|
||||
action: 'import',
|
||||
data: {
|
||||
}
|
||||
}).always(function () {
|
||||
MailPoet.MP2Migrator.stopLogger();
|
||||
MailPoet.MP2Migrator.updateDisplay(); // Get the latest information after the import was stopped
|
||||
MailPoet.MP2Migrator.reactivateImportButton();
|
||||
}).done(function (response) {
|
||||
if(response) {
|
||||
MailPoet.MP2Migrator.fatal_error = response.data;
|
||||
}
|
||||
}).fail(function (response) {
|
||||
if(response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function (error) {
|
||||
return error.message;
|
||||
}),
|
||||
{scroll: true}
|
||||
);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
},
|
||||
|
||||
reactivateImportButton: function () {
|
||||
jQuery('#import').val(MailPoet.MP2Migrator.import_button_label).removeAttr('disabled');
|
||||
jQuery('#stop-import').hide();
|
||||
},
|
||||
|
||||
stopImport: function () {
|
||||
jQuery('#stop-import').attr('disabled', 'disabled');
|
||||
// Stop the import
|
||||
MailPoet.Ajax.post({
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'MP2Migrator',
|
||||
action: 'stopImport',
|
||||
data: {
|
||||
}
|
||||
}).always(function () {
|
||||
jQuery('#stop-import').removeAttr('disabled'); // Enable the button
|
||||
MailPoet.MP2Migrator.reactivateImportButton();
|
||||
MailPoet.MP2Migrator.updateDisplay(); // Get the latest information after the import was stopped
|
||||
});
|
||||
MailPoet.MP2Migrator.stopLogger();
|
||||
return false;
|
||||
},
|
||||
|
||||
skipImport: function () {
|
||||
MailPoet.Ajax.post({
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'MP2Migrator',
|
||||
action: 'skipImport',
|
||||
data: {
|
||||
}
|
||||
}).done(function () {
|
||||
MailPoet.MP2Migrator.gotoWelcomePage();
|
||||
});
|
||||
return false;
|
||||
},
|
||||
|
||||
gotoWelcomePage: function () {
|
||||
window.location.href = 'admin.php?page=mailpoet-welcome';
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Actions to run when the DOM is ready
|
||||
*/
|
||||
jQuery(function () {
|
||||
jQuery('#progressbar').progressbar({value: 0});
|
||||
|
||||
// Import button
|
||||
jQuery('#import').click(function() {
|
||||
MailPoet.MP2Migrator.startImport();
|
||||
});
|
||||
|
||||
// Stop import button
|
||||
jQuery('#stop-import').click(function() {
|
||||
MailPoet.MP2Migrator.stopImport();
|
||||
});
|
||||
|
||||
// Skip import link
|
||||
jQuery('#skip-import').click(function() {
|
||||
MailPoet.MP2Migrator.skipImport();
|
||||
});
|
||||
|
||||
// Go to welcome page
|
||||
jQuery('#goto-welcome').click(function() {
|
||||
MailPoet.MP2Migrator.gotoWelcomePage();
|
||||
});
|
||||
|
||||
// Update the display
|
||||
MailPoet.MP2Migrator.updateDisplay();
|
||||
});
|
||||
|
||||
});
|
64
lib/API/JSON/v1/MP2Migrator.php
Normal file
64
lib/API/JSON/v1/MP2Migrator.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
namespace MailPoet\API\JSON\v1;
|
||||
use MailPoet\API\JSON\Endpoint as APIEndpoint;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class MP2Migrator extends APIEndpoint {
|
||||
|
||||
public function __construct() {
|
||||
$this->MP2Migrator = new \MailPoet\Config\MP2Migrator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Import end point
|
||||
*
|
||||
* @param object $data
|
||||
* @return object
|
||||
*/
|
||||
public function import($data) {
|
||||
try {
|
||||
$process = $this->MP2Migrator->import($data);
|
||||
return $this->successResponse($process);
|
||||
} catch(\Exception $e) {
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop import end point
|
||||
*
|
||||
* @param object $data
|
||||
* @return object
|
||||
*/
|
||||
public function stopImport($data) {
|
||||
try {
|
||||
$process = $this->MP2Migrator->stopImport();
|
||||
return $this->successResponse($process);
|
||||
} catch(\Exception $e) {
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip import end point
|
||||
*
|
||||
* @param object $data
|
||||
* @return object
|
||||
*/
|
||||
public function skipImport($data) {
|
||||
try {
|
||||
$process = $this->MP2Migrator->skipImport();
|
||||
return $this->successResponse($process);
|
||||
} catch(\Exception $e) {
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -34,12 +34,23 @@ class Changelog {
|
||||
$version = Setting::getValue('version', null);
|
||||
$redirect_url = null;
|
||||
|
||||
if($version === null) {
|
||||
// new install
|
||||
$redirect_url = admin_url('admin.php?page=mailpoet-welcome');
|
||||
} else if($version !== Env::$version) {
|
||||
// update
|
||||
$redirect_url = admin_url('admin.php?page=mailpoet-update');
|
||||
$mp2_migrator = new MP2Migrator();
|
||||
if(!in_array($_GET['page'], array('mailpoet-migration', 'mailpoet-settings')) && $mp2_migrator->isMigrationStartedAndNotCompleted()) {
|
||||
// Force the redirection if the migration has started but is not completed
|
||||
$redirect_url = admin_url('admin.php?page=mailpoet-migration');
|
||||
} else {
|
||||
if($version === null) {
|
||||
// new install
|
||||
if($mp2_migrator->isMigrationNeeded()) {
|
||||
// Migration from MP2
|
||||
$redirect_url = admin_url('admin.php?page=mailpoet-migration');
|
||||
} else {
|
||||
$redirect_url = admin_url('admin.php?page=mailpoet-welcome');
|
||||
}
|
||||
} else if($version !== Env::$version) {
|
||||
// update
|
||||
$redirect_url = admin_url('admin.php?page=mailpoet-update');
|
||||
}
|
||||
}
|
||||
|
||||
if($redirect_url !== null) {
|
||||
|
@@ -77,6 +77,7 @@ class Database {
|
||||
$statistics_opens = Env::$db_prefix . 'statistics_opens';
|
||||
$statistics_unsubscribes = Env::$db_prefix . 'statistics_unsubscribes';
|
||||
$statistics_forms = Env::$db_prefix . 'statistics_forms';
|
||||
$mapping_to_external_entities = Env::$db_prefix . 'mapping_to_external_entities';
|
||||
|
||||
define('MP_SETTINGS_TABLE', $settings);
|
||||
define('MP_SEGMENTS_TABLE', $segments);
|
||||
@@ -98,6 +99,7 @@ class Database {
|
||||
define('MP_STATISTICS_OPENS_TABLE', $statistics_opens);
|
||||
define('MP_STATISTICS_UNSUBSCRIBES_TABLE', $statistics_unsubscribes);
|
||||
define('MP_STATISTICS_FORMS_TABLE', $statistics_forms);
|
||||
define('MP_MAPPING_TO_EXTERNAL_ENTITIES_TABLE', $mapping_to_external_entities);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
742
lib/Config/MP2Migrator.php
Normal file
742
lib/Config/MP2Migrator.php
Normal file
@@ -0,0 +1,742 @@
|
||||
<?php
|
||||
|
||||
namespace MailPoet\Config;
|
||||
|
||||
use MailPoet\Util\ProgressBar;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Models\CustomField;
|
||||
use MailPoet\Models\SubscriberSegment;
|
||||
use MailPoet\Models\SubscriberCustomField;
|
||||
use MailPoet\Models\MappingToExternalEntities;
|
||||
use MailPoet\Config\Activator;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class MP2Migrator {
|
||||
|
||||
const IMPORT_TIMEOUT_IN_SECONDS = 7200; // Timeout = 2 hours
|
||||
const CHUNK_SIZE = 10; // To import the data by batch
|
||||
|
||||
private $log_file;
|
||||
public $log_file_url;
|
||||
public $progressbar;
|
||||
private $segments_mapping = array(); // Mapping between old and new segment IDs
|
||||
private $wp_users_segment;
|
||||
|
||||
public function __construct() {
|
||||
$this->defineMP2Tables();
|
||||
$log_filename = 'mp2migration.log';
|
||||
$this->log_file = Env::$temp_path . '/' . $log_filename;
|
||||
$this->log_file_url = Env::$temp_url . '/' . $log_filename;
|
||||
$this->progressbar = new ProgressBar('mp2migration');
|
||||
}
|
||||
|
||||
private function defineMP2Tables() {
|
||||
global $wpdb;
|
||||
|
||||
if(!defined('MP2_CAMPAIGN_TABLE')) {
|
||||
define('MP2_CAMPAIGN_TABLE', $wpdb->prefix . 'wysija_campaign');
|
||||
}
|
||||
if(!defined('MP2_CUSTOM_FIELD_TABLE')) {
|
||||
define('MP2_CUSTOM_FIELD_TABLE', $wpdb->prefix . 'wysija_custom_field');
|
||||
}
|
||||
if(!defined('MP2_EMAIL_TABLE')) {
|
||||
define('MP2_EMAIL_TABLE', $wpdb->prefix . 'wysija_email');
|
||||
}
|
||||
if(!defined('MP2_FORM_TABLE')) {
|
||||
define('MP2_FORM_TABLE', $wpdb->prefix . 'wysija_form');
|
||||
}
|
||||
if(!defined('MP2_LIST_TABLE')) {
|
||||
define('MP2_LIST_TABLE', $wpdb->prefix . 'wysija_list');
|
||||
}
|
||||
if(!defined('MP2_USER_TABLE')) {
|
||||
define('MP2_USER_TABLE', $wpdb->prefix . 'wysija_user');
|
||||
}
|
||||
if(!defined('MP2_USER_LIST_TABLE')) {
|
||||
define('MP2_USER_LIST_TABLE', $wpdb->prefix . 'wysija_user_list');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the migration is already started but is not completed
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isMigrationStartedAndNotCompleted() {
|
||||
return Setting::getValue('mailpoet_migration_started', false) && !Setting::getValue('mailpoet_migration_complete', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the migration is needed
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isMigrationNeeded() {
|
||||
if(Setting::getValue('mailpoet_migration_complete')) {
|
||||
return false;
|
||||
} else {
|
||||
return $this->tableExists(MP2_CAMPAIGN_TABLE); // Check if the MailPoet 2 tables exist
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the "Skip import" choice
|
||||
*
|
||||
*/
|
||||
public function skipImport() {
|
||||
Setting::setValue('mailpoet_migration_complete', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a table exists
|
||||
*
|
||||
* @param string $table Table name
|
||||
* @return boolean
|
||||
*/
|
||||
private function tableExists($table) {
|
||||
global $wpdb;
|
||||
|
||||
try {
|
||||
$sql = "SHOW TABLES LIKE '{$table}'";
|
||||
$result = $wpdb->query($sql);
|
||||
return !empty($result);
|
||||
} catch (Exception $e) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the migration page
|
||||
*
|
||||
*/
|
||||
public function init() {
|
||||
if(!Setting::getValue('mailpoet_migration_started', false)) {
|
||||
$this->emptyLog();
|
||||
$this->progressbar->setTotalCount(0);
|
||||
}
|
||||
$this->enqueueScripts();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the JavaScript for the admin area.
|
||||
*
|
||||
*/
|
||||
private function enqueueScripts() {
|
||||
wp_enqueue_script('jquery-ui-progressbar');
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a message in the log file
|
||||
*
|
||||
* @param string $message
|
||||
*/
|
||||
private function log($message) {
|
||||
file_put_contents($this->log_file, "$message\n", FILE_APPEND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import the data from MailPoet 2
|
||||
*
|
||||
* @return string Result
|
||||
*/
|
||||
public function import() {
|
||||
set_time_limit(self::IMPORT_TIMEOUT_IN_SECONDS);
|
||||
ob_start();
|
||||
$datetime = new \MailPoet\WP\DateTime();
|
||||
$this->log(sprintf('=== ' . __('START IMPORT', 'mailpoet') . ' %s ===', $datetime->formatTime(time(), \MailPoet\WP\DateTime::DEFAULT_DATE_TIME_FORMAT)));
|
||||
Setting::setValue('import_stopped', false); // Reset the stop import action
|
||||
|
||||
if(!Setting::getValue('mailpoet_migration_started', false)) {
|
||||
$this->eraseMP3Data();
|
||||
Setting::setValue('mailpoet_migration_started', true);
|
||||
$this->displayDataToMigrate();
|
||||
}
|
||||
|
||||
$this->importSegments();
|
||||
$this->importCustomFields();
|
||||
$this->importSubscribers();
|
||||
|
||||
if(!$this->importStopped()) {
|
||||
Setting::setValue('mailpoet_migration_complete', true);
|
||||
$this->log(__('IMPORT COMPLETE', 'mailpoet'));
|
||||
}
|
||||
|
||||
$this->log(sprintf('=== ' . __('END IMPORT', 'mailpoet') . ' %s ===', $datetime->formatTime(time(), \MailPoet\WP\DateTime::DEFAULT_DATE_TIME_FORMAT)));
|
||||
$result = ob_get_contents();
|
||||
ob_clean();
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty the log file
|
||||
*
|
||||
*/
|
||||
private function emptyLog() {
|
||||
file_put_contents($this->log_file, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Erase all the MailPoet 3 data
|
||||
*
|
||||
*/
|
||||
private function eraseMP3Data() {
|
||||
Activator::deactivate();
|
||||
Activator::activate();
|
||||
|
||||
$this->deleteSegments();
|
||||
$this->resetMigrationCounters();
|
||||
$this->log(__("MailPoet data erased", 'mailpoet'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the migration counters
|
||||
*
|
||||
*/
|
||||
private function resetMigrationCounters() {
|
||||
Setting::setValue('last_imported_user_id', 0);
|
||||
Setting::setValue('last_imported_list_id', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the existing segments except the wp_users segment
|
||||
*
|
||||
*/
|
||||
private function deleteSegments() {
|
||||
global $wpdb;
|
||||
|
||||
$table = MP_SEGMENTS_TABLE;
|
||||
$wpdb->query("DELETE FROM {$table} WHERE type != '" . Segment::TYPE_WP_USERS . "'");
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the import
|
||||
*
|
||||
*/
|
||||
public function stopImport() {
|
||||
Setting::setValue('import_stopped', true);
|
||||
$this->log(__('IMPORT STOPPED BY USER', 'mailpoet'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the import must stop
|
||||
*
|
||||
* @return boolean Import must stop or not
|
||||
*/
|
||||
private function importStopped() {
|
||||
return Setting::getValue('import_stopped', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the number of data to migrate
|
||||
*
|
||||
*/
|
||||
private function displayDataToMigrate() {
|
||||
$data = $this->getDataToMigrateAndResetProgressBar();
|
||||
$this->log($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data to migrate
|
||||
*
|
||||
* @return string Data to migrate
|
||||
*/
|
||||
private function getDataToMigrateAndResetProgressBar() {
|
||||
$result = '';
|
||||
$total_count = 0;
|
||||
|
||||
$this->progressbar->setTotalCount(0);
|
||||
|
||||
$result .= __('MailPoet 2 data found:', 'mailpoet') . "\n";
|
||||
|
||||
// User Lists
|
||||
$users_lists_count = \ORM::for_table(MP2_LIST_TABLE)->count();
|
||||
$total_count += $users_lists_count;
|
||||
$result .= sprintf(_n('%d subscribers list', '%d subscribers lists', $users_lists_count, 'mailpoet'), $users_lists_count) . "\n";
|
||||
|
||||
// Users
|
||||
$users_count = \ORM::for_table(MP2_USER_TABLE)->count();
|
||||
$total_count += $users_count;
|
||||
$result .= sprintf(_n('%d subscriber', '%d subscribers', $users_count, 'mailpoet'), $users_count) . "\n";
|
||||
|
||||
// TODO to reactivate during the next phases
|
||||
/*
|
||||
// Emails
|
||||
$emails_count = \ORM::for_table(MP2_EMAIL_TABLE)->count();
|
||||
$total_count += $emails_count;
|
||||
$result .= sprintf(_n('%d newsletter', '%d newsletters', $emails_count, 'mailpoet'), $emails_count) . "\n";
|
||||
|
||||
// Forms
|
||||
$forms_count = \ORM::for_table(MP2_FORM_TABLE)->count();
|
||||
$total_count += $forms_count;
|
||||
$result .= sprintf(_n('%d form', '%d forms', $forms_count, 'mailpoet'), $forms_count) . "\n";
|
||||
*/
|
||||
|
||||
$this->progressbar->setTotalCount($total_count);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import the subscribers segments
|
||||
*
|
||||
*/
|
||||
private function importSegments() {
|
||||
$imported_segments_count = 0;
|
||||
if($this->importStopped()) {
|
||||
$this->segments_mapping = $this->getImportedMapping('segments');
|
||||
return;
|
||||
}
|
||||
$this->log(__("Importing segments...", 'mailpoet'));
|
||||
do {
|
||||
if($this->importStopped()) {
|
||||
break;
|
||||
}
|
||||
$lists = $this->getLists(self::CHUNK_SIZE);
|
||||
$lists_count = count($lists);
|
||||
|
||||
if(is_array($lists)) {
|
||||
foreach($lists as $list) {
|
||||
$segment = $this->importSegment($list);
|
||||
if(!empty($segment)) {
|
||||
$imported_segments_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->progressbar->incrementCurrentCount($lists_count);
|
||||
} while(($lists != null) && ($lists_count > 0));
|
||||
|
||||
$this->segments_mapping = $this->getImportedMapping('segments');
|
||||
|
||||
$this->log(sprintf(_n("%d segment imported", "%d segments imported", $imported_segments_count, 'mailpoet'), $imported_segments_count));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Mailpoet 2 users lists
|
||||
*
|
||||
* @global object $wpdb
|
||||
* @param int $limit Number of users max
|
||||
* @return array Users Lists
|
||||
*/
|
||||
private function getLists($limit) {
|
||||
global $wpdb;
|
||||
$lists = array();
|
||||
|
||||
$last_id = Setting::getValue('last_imported_list_id', 0);
|
||||
$table = MP2_LIST_TABLE;
|
||||
$sql = "
|
||||
SELECT l.list_id, l.name, l.description, l.is_enabled, l.created_at
|
||||
FROM `$table` l
|
||||
WHERE l.list_id > '$last_id'
|
||||
ORDER BY l.list_id
|
||||
LIMIT $limit
|
||||
";
|
||||
$lists = $wpdb->get_results($sql, ARRAY_A);
|
||||
|
||||
return $lists;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a segment
|
||||
*
|
||||
* @param array $list_data List data
|
||||
* @return Segment
|
||||
*/
|
||||
private function importSegment($list_data) {
|
||||
$datetime = new \MailPoet\WP\DateTime();
|
||||
if($list_data['is_enabled']) {
|
||||
$segment = Segment::createOrUpdate(array(
|
||||
'name' => $list_data['name'],
|
||||
'type' => 'default',
|
||||
'description' => !empty($list_data['description']) ? $list_data['description'] : '',
|
||||
'created_at' => $datetime->formatTime($list_data['created_at'], \MailPoet\WP\DateTime::DEFAULT_DATE_TIME_FORMAT),
|
||||
));
|
||||
} else {
|
||||
$segment = Segment::getWPSegment();
|
||||
}
|
||||
if(!empty($segment)) {
|
||||
// Map the segment with its old ID
|
||||
$mapping = new MappingToExternalEntities();
|
||||
$mapping->create(array(
|
||||
'old_id' => $list_data['list_id'],
|
||||
'type' => 'segments',
|
||||
'new_id' => $segment->id,
|
||||
'created_at' => $datetime->formatTime(time(), \MailPoet\WP\DateTime::DEFAULT_DATE_TIME_FORMAT),
|
||||
));
|
||||
}
|
||||
Setting::setValue('last_imported_list_id', $list_data['list_id']);
|
||||
return $segment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import the custom fields
|
||||
*
|
||||
*/
|
||||
private function importCustomFields() {
|
||||
$imported_custom_fields_count = 0;
|
||||
if($this->importStopped()) {
|
||||
return;
|
||||
}
|
||||
$this->log(__("Importing custom fields...", 'mailpoet'));
|
||||
$custom_fields = $this->getCustomFields();
|
||||
|
||||
foreach($custom_fields as $custom_field) {
|
||||
$result = $this->importCustomField($custom_field);
|
||||
if(!empty($result)) {
|
||||
$imported_custom_fields_count++;
|
||||
}
|
||||
}
|
||||
|
||||
$this->log(sprintf(_n("%d custom field imported", "%d custom fields imported", $imported_custom_fields_count, 'mailpoet'), $imported_custom_fields_count));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Mailpoet 2 custom fields
|
||||
*
|
||||
* @global object $wpdb
|
||||
* @return array Custom fields
|
||||
*/
|
||||
private function getCustomFields() {
|
||||
global $wpdb;
|
||||
$custom_fields = array();
|
||||
|
||||
$table = MP2_CUSTOM_FIELD_TABLE;
|
||||
$sql = "
|
||||
SELECT cf.id, cf.name, cf.type, cf.required, cf.settings
|
||||
FROM `$table` cf
|
||||
";
|
||||
$custom_fields = $wpdb->get_results($sql, ARRAY_A);
|
||||
|
||||
return $custom_fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a custom field
|
||||
*
|
||||
* @param array $custom_field MP2 custom field
|
||||
* @return CustomField
|
||||
*/
|
||||
private function importCustomField($custom_field) {
|
||||
$data = array(
|
||||
'id' => $custom_field['id'],
|
||||
'name' => $custom_field['name'],
|
||||
'type' => $this->mapCustomFieldType($custom_field['type']),
|
||||
'params' => $this->mapCustomFieldParams($custom_field),
|
||||
);
|
||||
$custom_field = new CustomField();
|
||||
$custom_field->createOrUpdate($data);
|
||||
return $custom_field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the MailPoet 2 custom field type with the MailPoet custom field type
|
||||
*
|
||||
* @param string $mp2_type MP2 custom field type
|
||||
* @return string MP3 custom field type
|
||||
*/
|
||||
private function mapCustomFieldType($mp2_type) {
|
||||
$type = '';
|
||||
switch($mp2_type) {
|
||||
case 'input':
|
||||
$type = 'text';
|
||||
break;
|
||||
default:
|
||||
$type = $mp2_type;
|
||||
}
|
||||
return $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the MailPoet 2 custom field settings with the MailPoet custom field params
|
||||
*
|
||||
* @param array $custom_field MP2 custom field
|
||||
* @return string serialized MP3 custom field params
|
||||
*/
|
||||
private function mapCustomFieldParams($custom_field) {
|
||||
$params = unserialize($custom_field['settings']);
|
||||
$params['label'] = $custom_field['name'];
|
||||
if(isset($params['validate'])) {
|
||||
$params['validate'] = $this->mapCustomFieldValidateValue($params['validate']);
|
||||
}
|
||||
if(isset($params['date_order'])) { // Convert the date_order field
|
||||
$params['date_format'] = strtoupper($params['date_order']);
|
||||
unset($params['date_order']);
|
||||
}
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the validate value
|
||||
*
|
||||
* @param string $mp2_value MP2 value
|
||||
* @return string MP3 value
|
||||
*/
|
||||
private function mapCustomFieldValidateValue($mp2_value) {
|
||||
$value = '';
|
||||
switch($mp2_value) {
|
||||
case 'onlyLetterSp':
|
||||
case 'onlyLetterNumber':
|
||||
$value = 'alphanum';
|
||||
break;
|
||||
case 'onlyNumberSp':
|
||||
$value = 'number';
|
||||
break;
|
||||
case 'phone':
|
||||
$value = 'phone';
|
||||
break;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import the subscribers
|
||||
*
|
||||
*/
|
||||
private function importSubscribers() {
|
||||
$imported_subscribers_count = 0;
|
||||
if($this->importStopped()) {
|
||||
return;
|
||||
}
|
||||
$this->log(__("Importing subscribers...", 'mailpoet'));
|
||||
$this->wp_users_segment = Segment::getWPSegment();
|
||||
do {
|
||||
if($this->importStopped()) {
|
||||
break;
|
||||
}
|
||||
$users = $this->getUsers(self::CHUNK_SIZE);
|
||||
$users_count = count($users);
|
||||
|
||||
if(is_array($users)) {
|
||||
foreach($users as $user) {
|
||||
$subscriber = $this->importSubscriber($user);
|
||||
if(!empty($subscriber)) {
|
||||
$imported_subscribers_count++;
|
||||
$this->importSubscriberSegments($subscriber, $user['user_id']);
|
||||
$this->importSubscriberCustomFields($subscriber, $user);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->progressbar->incrementCurrentCount($users_count);
|
||||
} while(($users != null) && ($users_count > 0));
|
||||
|
||||
$this->log(sprintf(_n("%d subscriber imported", "%d subscribers imported", $imported_subscribers_count, 'mailpoet'), $imported_subscribers_count));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Mailpoet 2 users
|
||||
*
|
||||
* @global object $wpdb
|
||||
* @param int $limit Number of users max
|
||||
* @return array Users
|
||||
*/
|
||||
private function getUsers($limit) {
|
||||
global $wpdb;
|
||||
$users = array();
|
||||
|
||||
$last_id = Setting::getValue('last_imported_user_id', 0);
|
||||
$table = MP2_USER_TABLE;
|
||||
$sql = "
|
||||
SELECT u.*
|
||||
FROM `$table` u
|
||||
WHERE u.user_id > '$last_id'
|
||||
ORDER BY u.user_id
|
||||
LIMIT $limit
|
||||
";
|
||||
$users = $wpdb->get_results($sql, ARRAY_A);
|
||||
|
||||
return $users;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a subscriber
|
||||
*
|
||||
* @param array $user_data User data
|
||||
* @return Subscriber
|
||||
*/
|
||||
private function importSubscriber($user_data) {
|
||||
$datetime = new \MailPoet\WP\DateTime();
|
||||
$subscriber = Subscriber::createOrUpdate(array(
|
||||
'wp_user_id' => !empty($user_data['wpuser_id']) ? $user_data['wpuser_id'] : null,
|
||||
'email' => $user_data['email'],
|
||||
'first_name' => $user_data['firstname'],
|
||||
'last_name' => $user_data['lastname'],
|
||||
'status' => $this->mapUserStatus($user_data['status']),
|
||||
'created_at' => $datetime->formatTime($user_data['created_at'], \MailPoet\WP\DateTime::DEFAULT_DATE_TIME_FORMAT),
|
||||
'subscribed_ip' => !empty($user_data['ip']) ? $user_data['ip'] : null,
|
||||
'confirmed_ip' => !empty($user_data['confirmed_ip']) ? $user_data['confirmed_ip'] : null,
|
||||
'confirmed_at' => !empty($user_data['confirmed_at']) ? $datetime->formatTime($user_data['confirmed_at'], \MailPoet\WP\DateTime::DEFAULT_DATE_TIME_FORMAT) : null,
|
||||
));
|
||||
Setting::setValue('last_imported_user_id', $user_data['user_id']);
|
||||
if(!empty($subscriber)) {
|
||||
// Map the subscriber with its old ID
|
||||
$mapping = new MappingToExternalEntities();
|
||||
$mapping->create(array(
|
||||
'old_id' => $user_data['user_id'],
|
||||
'type' => 'subscribers',
|
||||
'new_id' => $subscriber->id,
|
||||
'created_at' => $datetime->formatTime(time(), \MailPoet\WP\DateTime::DEFAULT_DATE_TIME_FORMAT),
|
||||
));
|
||||
}
|
||||
return $subscriber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the MailPoet 2 user status with MailPoet 3
|
||||
*
|
||||
* @param int $mp2_user_status MP2 user status
|
||||
* @return string MP3 user status
|
||||
*/
|
||||
private function mapUserStatus($mp2_user_status) {
|
||||
switch($mp2_user_status) {
|
||||
case 1:
|
||||
$status = 'subscribed';
|
||||
break;
|
||||
case -1:
|
||||
$status = 'unsubscribed';
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
$status = 'unconfirmed';
|
||||
}
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import the segments for a subscriber
|
||||
*
|
||||
* @param Subscriber $subscriber MP3 subscriber
|
||||
* @param int $user_id MP2 user ID
|
||||
*/
|
||||
private function importSubscriberSegments($subscriber, $user_id) {
|
||||
$user_lists = $this->getUserLists($user_id);
|
||||
foreach($user_lists as $user_list) {
|
||||
$this->importSubscriberSegment($subscriber->id, $user_list);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the lists for a user
|
||||
*
|
||||
* @global object $wpdb
|
||||
* @param int $user_id User ID
|
||||
* @return array Users Lists
|
||||
*/
|
||||
private function getUserLists($user_id) {
|
||||
global $wpdb;
|
||||
$user_lists = array();
|
||||
|
||||
$table = MP2_USER_LIST_TABLE;
|
||||
$sql = "
|
||||
SELECT ul.list_id, ul.sub_date, ul.unsub_date
|
||||
FROM `$table` ul
|
||||
WHERE ul.user_id = '$user_id'
|
||||
";
|
||||
$user_lists = $wpdb->get_results($sql, ARRAY_A);
|
||||
|
||||
return $user_lists;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a subscriber segment
|
||||
*
|
||||
* @param int $subscriber_id
|
||||
* @param array $user_list
|
||||
* @return SubscriberSegment
|
||||
*/
|
||||
private function importSubscriberSegment($subscriber_id, $user_list) {
|
||||
$subscriber_segment = null;
|
||||
$datetime = new \MailPoet\WP\DateTime();
|
||||
if(isset($this->segments_mapping[$user_list['list_id']])) {
|
||||
$segment_id = $this->segments_mapping[$user_list['list_id']];
|
||||
$status = (($segment_id == $this->wp_users_segment->id) || empty($user_list['unsub_date'])) ? 'subscribed' : 'unsubscribed'; // the users belonging to the wp_users segment are always subscribed
|
||||
$data = array(
|
||||
'subscriber_id' => $subscriber_id,
|
||||
'segment_id' => $segment_id,
|
||||
'status' => $status,
|
||||
'created_at' => $datetime->formatTime($user_list['sub_date'], \MailPoet\WP\DateTime::DEFAULT_DATE_TIME_FORMAT),
|
||||
'updated_at' => !empty($user_list['unsub_date']) ? $datetime->formatTime($user_list['unsub_date'], \MailPoet\WP\DateTime::DEFAULT_DATE_TIME_FORMAT) : null,
|
||||
);
|
||||
$subscriber_segment = new SubscriberSegment();
|
||||
$subscriber_segment->createOrUpdate($data);
|
||||
}
|
||||
return $subscriber_segment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import the custom fields values for a subscriber
|
||||
*
|
||||
* @param Subscriber $subscriber MP3 subscriber
|
||||
* @param array $user MP2 user
|
||||
*/
|
||||
private function importSubscriberCustomFields($subscriber, $user) {
|
||||
$imported_custom_fields = $this->getImportedCustomFields();
|
||||
foreach($imported_custom_fields as $custom_field) {
|
||||
$custom_field_column = 'cf_' . $custom_field['id'];
|
||||
if(isset($custom_field_column)) {
|
||||
$this->importSubscriberCustomField($subscriber->id, $custom_field, $user[$custom_field_column]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the imported custom fields
|
||||
*
|
||||
* @global object $wpdb
|
||||
* @return array Imported custom fields
|
||||
*
|
||||
*/
|
||||
private function getImportedCustomFields() {
|
||||
global $wpdb;
|
||||
$table = MP_CUSTOM_FIELDS_TABLE;
|
||||
$sql = "
|
||||
SELECT cf.id, cf.name, cf.type
|
||||
FROM `$table` cf
|
||||
";
|
||||
$custom_fields = $wpdb->get_results($sql, ARRAY_A);
|
||||
return $custom_fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a subscriber custom field
|
||||
*
|
||||
* @param int $subscriber_id Subscriber ID
|
||||
* @param int $custom_field Custom field
|
||||
* @param string $custom_field_value Custom field value
|
||||
* @return SubscriberCustomField
|
||||
*/
|
||||
private function importSubscriberCustomField($subscriber_id, $custom_field, $custom_field_value) {
|
||||
if($custom_field['type'] == 'date') {
|
||||
$datetime = new \MailPoet\WP\DateTime();
|
||||
$value = $datetime->formatTime($custom_field_value, \MailPoet\WP\DateTime::DEFAULT_DATE_TIME_FORMAT); // Convert the date field
|
||||
} else {
|
||||
$value = $custom_field_value;
|
||||
}
|
||||
$data = array(
|
||||
'subscriber_id' => $subscriber_id,
|
||||
'custom_field_id' => $custom_field['id'],
|
||||
'value' => isset($value) ? $value : '',
|
||||
);
|
||||
$subscriber_custom_field = new SubscriberCustomField();
|
||||
$subscriber_custom_field->createOrUpdate($data);
|
||||
return $subscriber_custom_field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mapping between the MP2 and the imported MP3 IDs
|
||||
*
|
||||
* @param string $model Model (segment,...)
|
||||
* @return array Mapping
|
||||
*/
|
||||
public function getImportedMapping($model) {
|
||||
$mappings = array();
|
||||
$mapping_relations = MappingToExternalEntities::where('type', $model)->findArray();
|
||||
foreach($mapping_relations as $relation) {
|
||||
$mappings[$relation['old_id']] = $relation['new_id'];
|
||||
}
|
||||
return $mappings;
|
||||
}
|
||||
|
||||
}
|
@@ -215,6 +215,18 @@ class Menu {
|
||||
)
|
||||
);
|
||||
|
||||
add_submenu_page(
|
||||
true,
|
||||
$this->setPageTitle(__('Migration', 'mailpoet')),
|
||||
'',
|
||||
Env::$required_permission,
|
||||
'mailpoet-migration',
|
||||
array(
|
||||
$this,
|
||||
'migration'
|
||||
)
|
||||
);
|
||||
|
||||
add_submenu_page(
|
||||
true,
|
||||
$this->setPageTitle(__('Update', 'mailpoet')),
|
||||
@@ -279,6 +291,16 @@ class Menu {
|
||||
$this->displayPage('welcome.html', $data);
|
||||
}
|
||||
|
||||
function migration() {
|
||||
$mp2_migrator = new MP2Migrator();
|
||||
$mp2_migrator->init();
|
||||
$data = array(
|
||||
'log_file_url' => $mp2_migrator->log_file_url,
|
||||
'progress_url' => $mp2_migrator->progressbar->url,
|
||||
);
|
||||
$this->displayPage('mp2migration.html', $data);
|
||||
}
|
||||
|
||||
function update() {
|
||||
global $wp;
|
||||
$current_url = home_url(add_query_arg($wp->query_string, $wp->request));
|
||||
|
@@ -33,7 +33,8 @@ class Migrator {
|
||||
'statistics_clicks',
|
||||
'statistics_opens',
|
||||
'statistics_unsubscribes',
|
||||
'statistics_forms'
|
||||
'statistics_forms',
|
||||
'mapping_to_external_entities'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -79,7 +80,7 @@ class Migrator {
|
||||
function settings() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'name varchar(20) NOT NULL,',
|
||||
'name varchar(50) NOT NULL,',
|
||||
'value longtext,',
|
||||
'created_at TIMESTAMP NULL,',
|
||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
@@ -363,6 +364,18 @@ class Migrator {
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
function mappingToExternalEntities() {
|
||||
$attributes = array(
|
||||
'old_id mediumint(9) NOT NULL,',
|
||||
'type varchar(50) NOT NULL,',
|
||||
'new_id mediumint(9) NOT NULL,',
|
||||
'created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,',
|
||||
'PRIMARY KEY (old_id, type),',
|
||||
'KEY new_id (new_id)'
|
||||
);
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
private function sqlify($model, $attributes) {
|
||||
$table = $this->prefix . Helpers::camelCaseToUnderscore($model);
|
||||
|
||||
|
15
lib/Models/MappingToExternalEntities.php
Normal file
15
lib/Models/MappingToExternalEntities.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
namespace MailPoet\Models;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class MappingToExternalEntities extends Model {
|
||||
public static $_table = MP_MAPPING_TO_EXTERNAL_ENTITIES_TABLE;
|
||||
|
||||
static function create($data = array()) {
|
||||
$relation = parent::create();
|
||||
$relation->hydrate($data);
|
||||
return $relation->save();
|
||||
}
|
||||
|
||||
}
|
@@ -136,4 +136,5 @@ class Helpers {
|
||||
static function splitObject($object = array()) {
|
||||
return explode(self::DIVIDER, $object);
|
||||
}
|
||||
|
||||
}
|
98
lib/Util/ProgressBar.php
Normal file
98
lib/Util/ProgressBar.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace MailPoet\Util;
|
||||
|
||||
use MailPoet\Config\Env;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
if(!class_exists('ProgressBar', false)) {
|
||||
|
||||
/**
|
||||
* The Progress Bar class
|
||||
*
|
||||
*/
|
||||
class ProgressBar {
|
||||
|
||||
private $total_count = 0;
|
||||
private $current_count = 0;
|
||||
private $filename;
|
||||
public $url;
|
||||
|
||||
/**
|
||||
* Initialize the class and set its properties.
|
||||
*
|
||||
*/
|
||||
public function __construct($progress_bar_id) {
|
||||
$filename = $progress_bar_id . '-progress.json';
|
||||
$this->filename = Env::$temp_path . '/' . $filename;
|
||||
$this->url = Env::$temp_url . '/' . $filename;
|
||||
$counters = $this->readProgress();
|
||||
if(isset($counters->total)) {
|
||||
$this->total_count = $counters->total;
|
||||
}
|
||||
if(isset($counters->current)) {
|
||||
$this->current_count = $counters->current;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the progress file URL
|
||||
*
|
||||
* @return string Progress file URL
|
||||
*/
|
||||
public function getUrl() {
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the progress counters
|
||||
*
|
||||
* @return array|false Array of counters
|
||||
*/
|
||||
private function readProgress() {
|
||||
if(file_exists($this->filename)) {
|
||||
$json_content = file_get_contents($this->filename);
|
||||
return json_decode($json_content);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the total count
|
||||
*
|
||||
* @param int $count Count
|
||||
*/
|
||||
public function setTotalCount($count) {
|
||||
if($count != $this->total_count) {
|
||||
$this->total_count = $count;
|
||||
$this->current_count = 0;
|
||||
$this->saveProgress();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the current count
|
||||
*
|
||||
* @param int $count Count
|
||||
*/
|
||||
public function incrementCurrentCount($count) {
|
||||
$this->current_count += $count;
|
||||
$this->saveProgress();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the progress counters
|
||||
*
|
||||
*/
|
||||
private function saveProgress() {
|
||||
file_put_contents($this->filename, json_encode(array(
|
||||
'total' => $this->total_count,
|
||||
'current' => $this->current_count,
|
||||
)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -93,4 +93,22 @@ abstract class MailPoetTest extends \Codeception\TestCase\Test {
|
||||
protected $runTestInSeparateProcess = false;
|
||||
protected $preserveGlobalState = false;
|
||||
protected $inIsolation = false;
|
||||
|
||||
/**
|
||||
* Call protected/private method of a class.
|
||||
*
|
||||
* @param object &$object Instantiated object that we will run method on.
|
||||
* @param string $methodName Method name to call
|
||||
* @param array $parameters Array of parameters to pass into method.
|
||||
*
|
||||
* @return mixed Method return.
|
||||
*/
|
||||
public function invokeMethod(&$object, $methodName, array $parameters = array()) {
|
||||
$reflection = new \ReflectionClass(get_class($object));
|
||||
$method = $reflection->getMethod($methodName);
|
||||
$method->setAccessible(true);
|
||||
|
||||
return $method->invokeArgs($object, $parameters);
|
||||
}
|
||||
|
||||
}
|
431
tests/_data/createMP2Tables.sql
Normal file
431
tests/_data/createMP2Tables.sql
Normal file
@@ -0,0 +1,431 @@
|
||||
-- phpMyAdmin SQL Dump
|
||||
-- version 4.4.10
|
||||
-- http://www.phpmyadmin.net
|
||||
--
|
||||
-- Client : localhost:3306
|
||||
-- Généré le : Mer 26 Avril 2017 à 17:52
|
||||
-- Version du serveur : 5.5.42
|
||||
-- Version de PHP : 7.0.0
|
||||
|
||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
||||
SET time_zone = "+00:00";
|
||||
|
||||
--
|
||||
-- Base de données : `mailpoet`
|
||||
--
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Structure de la table `wp_wysija_campaign`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `wp_wysija_campaign`;
|
||||
CREATE TABLE `wp_wysija_campaign` (
|
||||
`campaign_id` int(10) unsigned NOT NULL,
|
||||
`name` varchar(250) DEFAULT NULL,
|
||||
`description` text
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Structure de la table `wp_wysija_campaign_list`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `wp_wysija_campaign_list`;
|
||||
CREATE TABLE `wp_wysija_campaign_list` (
|
||||
`list_id` int(10) unsigned NOT NULL,
|
||||
`campaign_id` int(10) unsigned NOT NULL,
|
||||
`filter` text
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Structure de la table `wp_wysija_custom_field`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `wp_wysija_custom_field`;
|
||||
CREATE TABLE `wp_wysija_custom_field` (
|
||||
`id` mediumint(9) NOT NULL,
|
||||
`name` tinytext NOT NULL,
|
||||
`type` tinytext NOT NULL,
|
||||
`required` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`settings` text
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Structure de la table `wp_wysija_email`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `wp_wysija_email`;
|
||||
CREATE TABLE `wp_wysija_email` (
|
||||
`email_id` int(10) unsigned NOT NULL,
|
||||
`campaign_id` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`subject` varchar(250) NOT NULL DEFAULT '',
|
||||
`body` longtext,
|
||||
`created_at` int(10) unsigned DEFAULT NULL,
|
||||
`modified_at` int(10) unsigned DEFAULT NULL,
|
||||
`sent_at` int(10) unsigned DEFAULT NULL,
|
||||
`from_email` varchar(250) DEFAULT NULL,
|
||||
`from_name` varchar(250) DEFAULT NULL,
|
||||
`replyto_email` varchar(250) DEFAULT NULL,
|
||||
`replyto_name` varchar(250) DEFAULT NULL,
|
||||
`attachments` text,
|
||||
`status` tinyint(4) NOT NULL DEFAULT '0',
|
||||
`type` tinyint(4) NOT NULL DEFAULT '1',
|
||||
`number_sent` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`number_opened` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`number_clicked` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`number_unsub` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`number_bounce` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`number_forward` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`params` text,
|
||||
`wj_data` longtext,
|
||||
`wj_styles` longtext
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Structure de la table `wp_wysija_email_user_stat`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `wp_wysija_email_user_stat`;
|
||||
CREATE TABLE `wp_wysija_email_user_stat` (
|
||||
`user_id` int(10) unsigned NOT NULL,
|
||||
`email_id` int(10) unsigned NOT NULL,
|
||||
`sent_at` int(10) unsigned NOT NULL,
|
||||
`opened_at` int(10) unsigned DEFAULT NULL,
|
||||
`status` tinyint(4) NOT NULL DEFAULT '0'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Structure de la table `wp_wysija_email_user_url`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `wp_wysija_email_user_url`;
|
||||
CREATE TABLE `wp_wysija_email_user_url` (
|
||||
`email_id` int(10) unsigned NOT NULL,
|
||||
`user_id` int(10) unsigned NOT NULL,
|
||||
`url_id` int(10) unsigned NOT NULL,
|
||||
`clicked_at` int(10) unsigned DEFAULT NULL,
|
||||
`number_clicked` int(10) unsigned NOT NULL DEFAULT '0'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Structure de la table `wp_wysija_form`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `wp_wysija_form`;
|
||||
CREATE TABLE `wp_wysija_form` (
|
||||
`form_id` int(10) unsigned NOT NULL,
|
||||
`name` tinytext CHARACTER SET utf8 COLLATE utf8_bin,
|
||||
`data` longtext CHARACTER SET utf8 COLLATE utf8_bin,
|
||||
`styles` longtext CHARACTER SET utf8 COLLATE utf8_bin,
|
||||
`subscribed` int(10) unsigned NOT NULL DEFAULT '0'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Structure de la table `wp_wysija_list`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `wp_wysija_list`;
|
||||
CREATE TABLE `wp_wysija_list` (
|
||||
`list_id` int(10) unsigned NOT NULL,
|
||||
`name` varchar(250) DEFAULT NULL,
|
||||
`namekey` varchar(255) DEFAULT NULL,
|
||||
`description` text,
|
||||
`unsub_mail_id` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`welcome_mail_id` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`is_enabled` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`is_public` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`created_at` int(10) unsigned DEFAULT NULL,
|
||||
`ordering` int(10) unsigned NOT NULL DEFAULT '0'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Structure de la table `wp_wysija_queue`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `wp_wysija_queue`;
|
||||
CREATE TABLE `wp_wysija_queue` (
|
||||
`user_id` int(10) unsigned NOT NULL,
|
||||
`email_id` int(10) unsigned NOT NULL,
|
||||
`send_at` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`priority` tinyint(4) NOT NULL DEFAULT '0',
|
||||
`number_try` tinyint(3) unsigned NOT NULL DEFAULT '0'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Structure de la table `wp_wysija_url`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `wp_wysija_url`;
|
||||
CREATE TABLE `wp_wysija_url` (
|
||||
`url_id` int(10) unsigned NOT NULL,
|
||||
`name` varchar(250) DEFAULT NULL,
|
||||
`url` text
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Structure de la table `wp_wysija_url_mail`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `wp_wysija_url_mail`;
|
||||
CREATE TABLE `wp_wysija_url_mail` (
|
||||
`email_id` int(11) NOT NULL,
|
||||
`url_id` int(10) unsigned NOT NULL,
|
||||
`unique_clicked` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`total_clicked` int(10) unsigned NOT NULL DEFAULT '0'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Structure de la table `wp_wysija_user`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `wp_wysija_user`;
|
||||
CREATE TABLE `wp_wysija_user` (
|
||||
`user_id` int(10) unsigned NOT NULL,
|
||||
`wpuser_id` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`email` varchar(255) NOT NULL,
|
||||
`firstname` varchar(255) NOT NULL DEFAULT '',
|
||||
`lastname` varchar(255) NOT NULL DEFAULT '',
|
||||
`ip` varchar(100) NOT NULL,
|
||||
`confirmed_ip` varchar(100) NOT NULL DEFAULT '0',
|
||||
`confirmed_at` int(10) unsigned DEFAULT NULL,
|
||||
`last_opened` int(10) unsigned DEFAULT NULL,
|
||||
`last_clicked` int(10) unsigned DEFAULT NULL,
|
||||
`keyuser` varchar(255) NOT NULL DEFAULT '',
|
||||
`created_at` int(10) unsigned DEFAULT NULL,
|
||||
`status` tinyint(4) NOT NULL DEFAULT '0',
|
||||
`domain` varchar(255) DEFAULT '',
|
||||
`cf_1` varchar(100) DEFAULT NULL,
|
||||
`cf_3` varchar(255) DEFAULT NULL,
|
||||
`cf_4` varchar(255) DEFAULT NULL,
|
||||
`cf_5` tinyint(1) DEFAULT NULL,
|
||||
`cf_6` varchar(255) DEFAULT NULL,
|
||||
`cf_7` int(20) DEFAULT NULL,
|
||||
`cf_8` varchar(100) DEFAULT NULL,
|
||||
`cf_9` varchar(100) DEFAULT NULL,
|
||||
`cf_10` varchar(100) DEFAULT NULL,
|
||||
`cf_11` varchar(100) DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Structure de la table `wp_wysija_user_field`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `wp_wysija_user_field`;
|
||||
CREATE TABLE `wp_wysija_user_field` (
|
||||
`field_id` int(10) unsigned NOT NULL,
|
||||
`name` varchar(250) DEFAULT NULL,
|
||||
`column_name` varchar(250) NOT NULL DEFAULT '',
|
||||
`type` tinyint(3) unsigned DEFAULT '0',
|
||||
`values` text,
|
||||
`default` varchar(250) NOT NULL DEFAULT '',
|
||||
`is_required` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`error_message` varchar(250) NOT NULL DEFAULT ''
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Structure de la table `wp_wysija_user_history`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `wp_wysija_user_history`;
|
||||
CREATE TABLE `wp_wysija_user_history` (
|
||||
`history_id` int(10) unsigned NOT NULL,
|
||||
`user_id` int(10) unsigned NOT NULL,
|
||||
`email_id` int(10) unsigned DEFAULT '0',
|
||||
`type` varchar(250) NOT NULL DEFAULT '',
|
||||
`details` text,
|
||||
`executed_at` int(10) unsigned DEFAULT NULL,
|
||||
`executed_by` int(10) unsigned DEFAULT NULL,
|
||||
`source` text
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Structure de la table `wp_wysija_user_list`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `wp_wysija_user_list`;
|
||||
CREATE TABLE `wp_wysija_user_list` (
|
||||
`list_id` int(10) unsigned NOT NULL,
|
||||
`user_id` int(10) unsigned NOT NULL,
|
||||
`sub_date` int(10) unsigned DEFAULT '0',
|
||||
`unsub_date` int(10) unsigned DEFAULT '0'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Index pour les tables exportées
|
||||
--
|
||||
|
||||
--
|
||||
-- Index pour la table `wp_wysija_campaign`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_campaign`
|
||||
ADD PRIMARY KEY (`campaign_id`);
|
||||
|
||||
--
|
||||
-- Index pour la table `wp_wysija_campaign_list`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_campaign_list`
|
||||
ADD PRIMARY KEY (`list_id`,`campaign_id`);
|
||||
|
||||
--
|
||||
-- Index pour la table `wp_wysija_custom_field`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_custom_field`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- Index pour la table `wp_wysija_email`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_email`
|
||||
ADD PRIMARY KEY (`email_id`);
|
||||
|
||||
--
|
||||
-- Index pour la table `wp_wysija_email_user_stat`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_email_user_stat`
|
||||
ADD PRIMARY KEY (`user_id`,`email_id`);
|
||||
|
||||
--
|
||||
-- Index pour la table `wp_wysija_email_user_url`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_email_user_url`
|
||||
ADD PRIMARY KEY (`user_id`,`email_id`,`url_id`);
|
||||
|
||||
--
|
||||
-- Index pour la table `wp_wysija_form`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_form`
|
||||
ADD PRIMARY KEY (`form_id`);
|
||||
|
||||
--
|
||||
-- Index pour la table `wp_wysija_list`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_list`
|
||||
ADD PRIMARY KEY (`list_id`);
|
||||
|
||||
--
|
||||
-- Index pour la table `wp_wysija_queue`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_queue`
|
||||
ADD PRIMARY KEY (`user_id`,`email_id`),
|
||||
ADD KEY `SENT_AT_INDEX` (`send_at`);
|
||||
|
||||
--
|
||||
-- Index pour la table `wp_wysija_url`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_url`
|
||||
ADD PRIMARY KEY (`url_id`);
|
||||
|
||||
--
|
||||
-- Index pour la table `wp_wysija_url_mail`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_url_mail`
|
||||
ADD PRIMARY KEY (`email_id`,`url_id`);
|
||||
|
||||
--
|
||||
-- Index pour la table `wp_wysija_user`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_user`
|
||||
ADD PRIMARY KEY (`user_id`),
|
||||
ADD UNIQUE KEY `EMAIL_UNIQUE` (`email`);
|
||||
|
||||
--
|
||||
-- Index pour la table `wp_wysija_user_field`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_user_field`
|
||||
ADD PRIMARY KEY (`field_id`);
|
||||
|
||||
--
|
||||
-- Index pour la table `wp_wysija_user_history`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_user_history`
|
||||
ADD PRIMARY KEY (`history_id`);
|
||||
|
||||
--
|
||||
-- Index pour la table `wp_wysija_user_list`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_user_list`
|
||||
ADD PRIMARY KEY (`list_id`,`user_id`);
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT pour les tables exportées
|
||||
--
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT pour la table `wp_wysija_campaign`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_campaign`
|
||||
MODIFY `campaign_id` int(10) unsigned NOT NULL AUTO_INCREMENT;
|
||||
--
|
||||
-- AUTO_INCREMENT pour la table `wp_wysija_custom_field`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_custom_field`
|
||||
MODIFY `id` mediumint(9) NOT NULL AUTO_INCREMENT;
|
||||
--
|
||||
-- AUTO_INCREMENT pour la table `wp_wysija_email`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_email`
|
||||
MODIFY `email_id` int(10) unsigned NOT NULL AUTO_INCREMENT;
|
||||
--
|
||||
-- AUTO_INCREMENT pour la table `wp_wysija_form`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_form`
|
||||
MODIFY `form_id` int(10) unsigned NOT NULL AUTO_INCREMENT;
|
||||
--
|
||||
-- AUTO_INCREMENT pour la table `wp_wysija_list`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_list`
|
||||
MODIFY `list_id` int(10) unsigned NOT NULL AUTO_INCREMENT;
|
||||
--
|
||||
-- AUTO_INCREMENT pour la table `wp_wysija_url`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_url`
|
||||
MODIFY `url_id` int(10) unsigned NOT NULL AUTO_INCREMENT;
|
||||
--
|
||||
-- AUTO_INCREMENT pour la table `wp_wysija_url_mail`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_url_mail`
|
||||
MODIFY `email_id` int(11) NOT NULL AUTO_INCREMENT;
|
||||
--
|
||||
-- AUTO_INCREMENT pour la table `wp_wysija_user`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_user`
|
||||
MODIFY `user_id` int(10) unsigned NOT NULL AUTO_INCREMENT;
|
||||
--
|
||||
-- AUTO_INCREMENT pour la table `wp_wysija_user_field`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_user_field`
|
||||
MODIFY `field_id` int(10) unsigned NOT NULL AUTO_INCREMENT;
|
||||
--
|
||||
-- AUTO_INCREMENT pour la table `wp_wysija_user_history`
|
||||
--
|
||||
ALTER TABLE `wp_wysija_user_history`
|
||||
MODIFY `history_id` int(10) unsigned NOT NULL AUTO_INCREMENT;
|
15
tests/_data/dropMP2Tables.sql
Normal file
15
tests/_data/dropMP2Tables.sql
Normal file
@@ -0,0 +1,15 @@
|
||||
DROP TABLE IF EXISTS `wp_wysija_campaign`;
|
||||
DROP TABLE IF EXISTS `wp_wysija_campaign_list`;
|
||||
DROP TABLE IF EXISTS `wp_wysija_custom_field`;
|
||||
DROP TABLE IF EXISTS `wp_wysija_email`;
|
||||
DROP TABLE IF EXISTS `wp_wysija_email_user_stat`;
|
||||
DROP TABLE IF EXISTS `wp_wysija_email_user_url`;
|
||||
DROP TABLE IF EXISTS `wp_wysija_form`;
|
||||
DROP TABLE IF EXISTS `wp_wysija_list`;
|
||||
DROP TABLE IF EXISTS `wp_wysija_queue`;
|
||||
DROP TABLE IF EXISTS `wp_wysija_url`;
|
||||
DROP TABLE IF EXISTS `wp_wysija_url_mail`;
|
||||
DROP TABLE IF EXISTS `wp_wysija_user`;
|
||||
DROP TABLE IF EXISTS `wp_wysija_user_field`;
|
||||
DROP TABLE IF EXISTS `wp_wysija_user_history`;
|
||||
DROP TABLE IF EXISTS `wp_wysija_user_list`;
|
170
tests/_data/populateMP2Tables.sql
Normal file
170
tests/_data/populateMP2Tables.sql
Normal file
File diff suppressed because one or more lines are too long
22
tests/_support/Helper/Database.php
Normal file
22
tests/_support/Helper/Database.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
namespace Helper;
|
||||
use MailPoet\Config\Env;
|
||||
|
||||
// here you can define custom actions
|
||||
// all public methods declared in helper class will be available in $I
|
||||
|
||||
class Database extends \Codeception\Module
|
||||
{
|
||||
/**
|
||||
* Load a SQL file
|
||||
*
|
||||
* @param string $filename Filename without extension
|
||||
*/
|
||||
static public function loadSQL($filename) {
|
||||
$db = \ORM::getDb();
|
||||
$full_filename = Env::$path . '/tests/_data/' . $filename . '.sql';
|
||||
$sql = file_get_contents($full_filename);
|
||||
$db->exec($sql);
|
||||
}
|
||||
|
||||
}
|
352
tests/unit/Config/MP2MigratorTest.php
Normal file
352
tests/unit/Config/MP2MigratorTest.php
Normal file
@@ -0,0 +1,352 @@
|
||||
<?php
|
||||
use MailPoet\Config\MP2Migrator;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Models\CustomField;
|
||||
use MailPoet\Models\MappingToExternalEntities;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Models\SubscriberCustomField;
|
||||
use MailPoet\Models\SubscriberSegment;
|
||||
use Helper\Database;
|
||||
|
||||
class MP2MigratorTest extends MailPoetTest {
|
||||
|
||||
public function _before() {
|
||||
$this->MP2Migrator = new MP2Migrator();
|
||||
}
|
||||
|
||||
public function _after() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the isMigrationNeeded function
|
||||
*
|
||||
*/
|
||||
public function testIsMigrationNeeded() {
|
||||
Database::loadSQL('dropMP2Tables');
|
||||
$result = $this->MP2Migrator->isMigrationNeeded();
|
||||
expect($result)->false();
|
||||
|
||||
Database::loadSQL('createMP2Tables');
|
||||
$result = $this->MP2Migrator->isMigrationNeeded();
|
||||
expect($result)->true();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the init function
|
||||
*
|
||||
*/
|
||||
public function testInit() {
|
||||
// Nothing to test
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the eraseMP3Data function
|
||||
*
|
||||
*/
|
||||
public function testEraseMP3Data() {
|
||||
global $wpdb;
|
||||
|
||||
$this->invokeMethod($this->MP2Migrator, 'eraseMP3Data');
|
||||
|
||||
// Check if the subscribers number is equal to the WordPress users number
|
||||
$WPUsersCount = \ORM::for_table($wpdb->prefix . 'users')->count();
|
||||
expect(Subscriber::count())->equals($WPUsersCount);
|
||||
|
||||
// Check if the custom fields number is 0
|
||||
expect(CustomField::count())->equals(0);
|
||||
|
||||
// Check if the subscribers custom fields number is 0
|
||||
expect(SubscriberCustomField::count())->equals(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the resetMigrationCounters function
|
||||
*
|
||||
*/
|
||||
public function testResetMigrationCounters() {
|
||||
$this->invokeMethod($this->MP2Migrator, 'resetMigrationCounters');
|
||||
|
||||
// Check if the last imported user ID is 0
|
||||
$lastImportedUserID = Setting::getValue('last_imported_user_id', 0);
|
||||
expect($lastImportedUserID)->equals(0);
|
||||
|
||||
// Check if the last imported list ID is 0
|
||||
$lastImportedListID = Setting::getValue('last_imported_list_id', 0);
|
||||
expect($lastImportedListID)->equals(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the stopImport function
|
||||
*
|
||||
*/
|
||||
public function testStopImport() {
|
||||
delete_option('mailpoet_stopImport');
|
||||
$this->MP2Migrator->stopImport();
|
||||
$stopImport = !empty(Setting::getValue('import_stopped', false));
|
||||
expect($stopImport)->true();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the MP2 tables and erase the MP3 data
|
||||
*
|
||||
*/
|
||||
private function initImport() {
|
||||
Database::loadSQL('createMP2Tables');
|
||||
$this->invokeMethod($this->MP2Migrator, 'eraseMP3Data');
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the MP2 tables with some samples data
|
||||
*
|
||||
*/
|
||||
private function loadMP2Fixtures() {
|
||||
Database::loadSQL('populateMP2Tables');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the importSegments function
|
||||
*
|
||||
* @global object $wpdb
|
||||
*/
|
||||
public function testImportSegments() {
|
||||
global $wpdb;
|
||||
|
||||
// Check the segments number
|
||||
$this->initImport();
|
||||
$this->loadMP2Fixtures();
|
||||
$this->invokeMethod($this->MP2Migrator, 'importSegments');
|
||||
expect(Segment::count())->equals(3);
|
||||
|
||||
// Check a segment data
|
||||
$this->initImport();
|
||||
$id = 999;
|
||||
$name = 'Test list';
|
||||
$description = 'Description of the test list';
|
||||
$timestamp = 1486319877;
|
||||
$wpdb->insert($wpdb->prefix . 'wysija_list', array(
|
||||
'list_id' => $id,
|
||||
'name' => $name,
|
||||
'description' => $description,
|
||||
'is_enabled' => 1,
|
||||
'is_public' => 1,
|
||||
'created_at' => $timestamp,
|
||||
));
|
||||
$this->invokeMethod($this->MP2Migrator, 'importSegments');
|
||||
$importedSegmentsMapping = $this->MP2Migrator->getImportedMapping('segments');
|
||||
$table = MP_SEGMENTS_TABLE;
|
||||
$segment = $wpdb->get_row("SELECT * FROM $table WHERE id=" . $importedSegmentsMapping[$id]);
|
||||
expect($segment->name)->equals($name);
|
||||
expect($segment->description)->equals($description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the importCustomFields function
|
||||
*
|
||||
* @global object $wpdb
|
||||
*/
|
||||
public function testImportCustomFields() {
|
||||
global $wpdb;
|
||||
|
||||
// Check the custom fields number
|
||||
$this->initImport();
|
||||
$this->loadMP2Fixtures();
|
||||
$this->invokeMethod($this->MP2Migrator, 'importCustomFields');
|
||||
expect(CustomField::count())->equals(10);
|
||||
|
||||
// Check a custom field data
|
||||
$this->initImport();
|
||||
$id = 999;
|
||||
$name = 'Test field';
|
||||
$type = 'input';
|
||||
$required = 1;
|
||||
$settings = array(
|
||||
'required' => '1',
|
||||
'validate' => 'onlyLetterSp',
|
||||
);
|
||||
$wpdb->insert($wpdb->prefix . 'wysija_custom_field', array(
|
||||
'id' => $id,
|
||||
'name' => $name,
|
||||
'type' => $type,
|
||||
'required' => $required,
|
||||
'settings' => serialize($settings),
|
||||
));
|
||||
$this->invokeMethod($this->MP2Migrator, 'importCustomFields');
|
||||
$table = MP_CUSTOM_FIELDS_TABLE;
|
||||
$custom_field = $wpdb->get_row("SELECT * FROM $table WHERE id=$id");
|
||||
expect($custom_field->id)->equals($id);
|
||||
expect($custom_field->name)->equals($name);
|
||||
expect($custom_field->type)->equals('text');
|
||||
$custom_field_params = unserialize($custom_field->params);
|
||||
expect($custom_field_params['required'])->equals($settings['required']);
|
||||
expect($custom_field_params['validate'])->equals('alphanum');
|
||||
expect($custom_field_params['label'])->equals($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the importSubscribers function
|
||||
*
|
||||
* @global object $wpdb
|
||||
*/
|
||||
public function testImportSubscribers() {
|
||||
global $wpdb;
|
||||
|
||||
// Check a subscriber data
|
||||
$this->initImport();
|
||||
$id = 999;
|
||||
$wp_id = 1;
|
||||
$email = 'test@test.com';
|
||||
$firstname = 'Test firstname';
|
||||
$lastname = 'Test lastname';
|
||||
$ip = '127.0.0.1';
|
||||
$confirmed_ip = $ip;
|
||||
$wpdb->insert($wpdb->prefix . 'wysija_user', array(
|
||||
'user_id' => $id,
|
||||
'wpuser_id' => $wp_id,
|
||||
'email' => $email,
|
||||
'firstname' => $firstname,
|
||||
'lastname' => $lastname,
|
||||
'ip' => $ip,
|
||||
'confirmed_ip' => $confirmed_ip,
|
||||
'status' => '1',
|
||||
));
|
||||
$this->invokeMethod($this->MP2Migrator, 'importSubscribers');
|
||||
$table = MP_SUBSCRIBERS_TABLE;
|
||||
$subscriber = $wpdb->get_row("SELECT * FROM $table WHERE email='$email'");
|
||||
expect($subscriber->email)->equals($email);
|
||||
expect($subscriber->first_name)->equals($firstname);
|
||||
expect($subscriber->last_name)->equals($lastname);
|
||||
expect($subscriber->subscribed_ip)->equals($ip);
|
||||
expect($subscriber->confirmed_ip)->equals($confirmed_ip);
|
||||
expect($subscriber->status)->equals('subscribed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the importSubscriberSegments function
|
||||
*
|
||||
* @global object $wpdb
|
||||
*/
|
||||
public function testImportSubscriberSegments() {
|
||||
global $wpdb;
|
||||
|
||||
// Check a subscriber segment data
|
||||
|
||||
// Insert a list
|
||||
$this->initImport();
|
||||
$list_id = 998;
|
||||
$list_name = 'Test list';
|
||||
$description = 'Description of the test list';
|
||||
$timestamp = 1486319877;
|
||||
$wpdb->insert($wpdb->prefix . 'wysija_list', array(
|
||||
'list_id' => $list_id,
|
||||
'name' => $list_name,
|
||||
'description' => $description,
|
||||
'is_enabled' => 1,
|
||||
'is_public' => 1,
|
||||
'created_at' => $timestamp,
|
||||
));
|
||||
|
||||
// Insert a user
|
||||
$user_id = 999;
|
||||
$wp_id = 1;
|
||||
$email = 'test@test.com';
|
||||
$wpdb->insert($wpdb->prefix . 'wysija_user', array(
|
||||
'user_id' => $user_id,
|
||||
'wpuser_id' => $wp_id,
|
||||
'email' => $email,
|
||||
));
|
||||
|
||||
// Insert a user list
|
||||
$wpdb->insert($wpdb->prefix . 'wysija_user_list', array(
|
||||
'list_id' => $list_id,
|
||||
'user_id' => $user_id,
|
||||
'sub_date' => $timestamp,
|
||||
));
|
||||
|
||||
$this->invokeMethod($this->MP2Migrator, 'importSegments');
|
||||
$this->invokeMethod($this->MP2Migrator, 'importSubscribers');
|
||||
$importedSegmentsMapping = $this->MP2Migrator->getImportedMapping('segments');
|
||||
$importedSubscribersMapping = $this->MP2Migrator->getImportedMapping('subscribers');
|
||||
$table = MP_SUBSCRIBER_SEGMENT_TABLE;
|
||||
$segment_id = $importedSegmentsMapping[$list_id];
|
||||
$subscriber_id = $importedSubscribersMapping[$user_id];
|
||||
$subscriber_segment = $wpdb->get_row("SELECT * FROM $table WHERE subscriber_id='$subscriber_id' AND segment_id='$segment_id'");
|
||||
expect($subscriber_segment)->notNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the importSubscriberCustomFields function
|
||||
*
|
||||
* @global object $wpdb
|
||||
*/
|
||||
public function testImportSubscriberCustomFields() {
|
||||
global $wpdb;
|
||||
|
||||
// Check the subscriber custom fields number
|
||||
$this->initImport();
|
||||
$this->loadMP2Fixtures();
|
||||
$this->invokeMethod($this->MP2Migrator, 'importCustomFields');
|
||||
$this->invokeMethod($this->MP2Migrator, 'importSubscribers');
|
||||
expect(SubscriberCustomField::count())->equals(40);
|
||||
|
||||
// Check a subscriber custom field data
|
||||
|
||||
$this->initImport();
|
||||
// Insert a custom field
|
||||
$cf_id = 1;
|
||||
$cf_name = 'Custom field key';
|
||||
$cf_type = 'input';
|
||||
$cf_required = 1;
|
||||
$cf_settings = array(
|
||||
'required' => '1',
|
||||
'validate' => 'onlyLetterSp',
|
||||
);
|
||||
$wpdb->insert($wpdb->prefix . 'wysija_custom_field', array(
|
||||
'id' => $cf_id,
|
||||
'name' => $cf_name,
|
||||
'type' => $cf_type,
|
||||
'required' => $cf_required,
|
||||
'settings' => serialize($cf_settings),
|
||||
));
|
||||
|
||||
// Insert a user
|
||||
$user_id = 999;
|
||||
$wp_id = 1;
|
||||
$email = 'test@test.com';
|
||||
$custom_field_value = 'Test custom field value';
|
||||
$wpdb->insert($wpdb->prefix . 'wysija_user', array(
|
||||
'user_id' => $user_id,
|
||||
'wpuser_id' => $wp_id,
|
||||
'email' => $email,
|
||||
'cf_' . $cf_id => $custom_field_value,
|
||||
));
|
||||
|
||||
$this->invokeMethod($this->MP2Migrator, 'importCustomFields');
|
||||
$this->invokeMethod($this->MP2Migrator, 'importSubscribers');
|
||||
$importedSubscribersMapping = $this->MP2Migrator->getImportedMapping('subscribers');
|
||||
$table = MP_SUBSCRIBER_CUSTOM_FIELD_TABLE;
|
||||
$subscriber_id = $importedSubscribersMapping[$user_id];
|
||||
$subscriber_custom_field = $wpdb->get_row("SELECT * FROM $table WHERE subscriber_id='$subscriber_id' AND custom_field_id='$cf_id'");
|
||||
expect($subscriber_custom_field->value)->equals($custom_field_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the getImportedMapping function
|
||||
*
|
||||
*/
|
||||
public function testGetImportedMapping() {
|
||||
$this->initImport();
|
||||
$mapping = new MappingToExternalEntities();
|
||||
$old_id = 999;
|
||||
$new_id = 500;
|
||||
$type = 'testMapping';
|
||||
$mapping->create(array(
|
||||
'old_id' => $old_id,
|
||||
'type' => $type,
|
||||
'new_id' => $new_id,
|
||||
));
|
||||
$result = $this->invokeMethod($this->MP2Migrator, 'getImportedMapping', array('testMapping'));
|
||||
expect($result[$old_id])->equals($new_id);
|
||||
}
|
||||
|
||||
}
|
67
views/mp2migration.html
Normal file
67
views/mp2migration.html
Normal file
@@ -0,0 +1,67 @@
|
||||
<% extends 'layout.html' %>
|
||||
|
||||
<% block content %>
|
||||
|
||||
<div class="wrap about-wrap">
|
||||
<h1><%= __('Welcome to MailPoet version 3!') %> <%= settings.version %></h1>
|
||||
|
||||
<p class="about-text"><strong><%= __('This new version is quite an upgrade.') %></strong> <%= __('Since this new version is completely new, we first need to update your database before we begin.') %></p>
|
||||
|
||||
<h3><%= __('What will be kept in MailPoet 3') %></h3>
|
||||
<ul>
|
||||
<li><strong><%= __('Subscribers and lists') %> <img draggable="false" class="emoji" alt="✔" src="https://s.w.org/images/core/emoji/2.2.1/svg/2714.svg"></strong></li>
|
||||
<li><%= __('Settings') %> (<%= __('soon') %>!)</li>
|
||||
<li><%= __('Forms') %> (<%= __('soon') %>!)</li>
|
||||
<li><%= __('Archive of sent newsletters') %> (<%= __('soon') %>!)</li>
|
||||
</ul>
|
||||
|
||||
<div style="position: absolute; top: .2em; right: 0;"></div>
|
||||
<hr />
|
||||
|
||||
<div>
|
||||
<br />
|
||||
<div id="import-actions">
|
||||
<input type="submit" name="import" id="import" class="button button-primary" value="<%= __('Start upgrade') %>" />
|
||||
<input type="submit" name="stop-import" id="stop-import" class="button button-secondary" value="<%= __('Pause') %>" style="display: none"/>
|
||||
<small> <a id="skip-import" href="#"><%= __("No thanks, I'll skip and start from scratch.") %></a></small>
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
|
||||
<div id="progressbar" class="mailpoet_progress mailpoet_progress_complete">
|
||||
<span id="progresslabel" class="mailpoet_progress_label">0%</span>
|
||||
</div>
|
||||
|
||||
<div id="upgrade-completed" style="display: none">
|
||||
<h3><%= __('Upgrade completed!') %></h3>
|
||||
<input type="button" name="goto-welcome" id="goto-welcome" class="button button-primary" value="<%= __('Go to MailPoet') %>" />
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<small><strong><%= __('Log...') %></strong></small>
|
||||
<div id="logger"></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<% endblock %>
|
||||
|
||||
<% block after_javascript %>
|
||||
<%= javascript(
|
||||
'mp2migrator.js'
|
||||
)%>
|
||||
<script type="text/javascript">
|
||||
var mailpoet_mp2_migrator = {
|
||||
log_file_url: '<%= log_file_url %>',
|
||||
progress_url: '<%= progress_url %>'
|
||||
};
|
||||
</script>
|
||||
<% endblock %>
|
||||
|
||||
<% block translations %>
|
||||
<%= localize({
|
||||
'import_complete' : __('IMPORT COMPLETE'),
|
||||
'importing' : __('Importing…'),
|
||||
'import_stopped_by_user' : __('IMPORT STOPPED BY USER'),
|
||||
}) %>
|
||||
<% endblock %>
|
@@ -238,6 +238,20 @@ config.push(_.extend({}, baseConfig, {
|
||||
}
|
||||
}));
|
||||
|
||||
// mp2migrator
|
||||
config.push(_.extend({}, baseConfig, {
|
||||
name: 'mp2migrator',
|
||||
entry: {
|
||||
mp2migrator: [
|
||||
'mp2migrator.js'
|
||||
]
|
||||
},
|
||||
externals: {
|
||||
'jquery': 'jQuery',
|
||||
'mailpoet': 'MailPoet'
|
||||
}
|
||||
}));
|
||||
|
||||
// Test
|
||||
config.push(_.extend({}, baseConfig, {
|
||||
name: 'test',
|
||||
|
Reference in New Issue
Block a user