Merge pull request #941 from mailpoet/mp2tomp3migration

Mp2tomp3migration phase 2
This commit is contained in:
Tautvidas Sipavičius
2017-06-26 18:47:58 +03:00
committed by GitHub
4 changed files with 385 additions and 16 deletions

View File

@@ -61,7 +61,7 @@ define('mp2migrator', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
} }
jQuery('#progressbar').progressbar('option', 'value', progress); jQuery('#progressbar').progressbar('option', 'value', progress);
jQuery('#progresslabel').html(progress + '%'); jQuery('#progresslabel').html(progress + '%');
if(Number(result.current !== 0)) { if(Number(result.current) !== 0) {
jQuery('#skip-import').hide(); jQuery('#skip-import').hide();
} }
if(MailPoet.MP2Migrator.is_logging) { if(MailPoet.MP2Migrator.is_logging) {

View File

@@ -3,6 +3,7 @@
namespace MailPoet\Config; namespace MailPoet\Config;
use MailPoet\Util\ProgressBar; use MailPoet\Util\ProgressBar;
use MailPoet\Models\Form;
use MailPoet\Models\Setting; use MailPoet\Models\Setting;
use MailPoet\Models\Segment; use MailPoet\Models\Segment;
use MailPoet\Models\Subscriber; use MailPoet\Models\Subscriber;
@@ -159,6 +160,7 @@ class MP2Migrator {
$this->importSegments(); $this->importSegments();
$this->importCustomFields(); $this->importCustomFields();
$this->importSubscribers(); $this->importSubscribers();
$this->importForms();
if(!$this->importStopped()) { if(!$this->importStopped()) {
Setting::setValue('mailpoet_migration_complete', true); Setting::setValue('mailpoet_migration_complete', true);
@@ -199,6 +201,7 @@ class MP2Migrator {
private function resetMigrationCounters() { private function resetMigrationCounters() {
Setting::setValue('last_imported_user_id', 0); Setting::setValue('last_imported_user_id', 0);
Setting::setValue('last_imported_list_id', 0); Setting::setValue('last_imported_list_id', 0);
Setting::setValue('last_imported_form_id', 0);
} }
/** /**
@@ -262,17 +265,17 @@ class MP2Migrator {
$total_count += $users_count; $total_count += $users_count;
$result .= sprintf(_n('%d subscriber', '%d subscribers', $users_count, 'mailpoet'), $users_count) . "\n"; $result .= sprintf(_n('%d subscriber', '%d subscribers', $users_count, 'mailpoet'), $users_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";
// TODO to reactivate during the next phases // TODO to reactivate during the next phases
/* /*
// Emails // Emails
$emails_count = \ORM::for_table(MP2_EMAIL_TABLE)->count(); $emails_count = \ORM::for_table(MP2_EMAIL_TABLE)->count();
$total_count += $emails_count; $total_count += $emails_count;
$result .= sprintf(_n('%d newsletter', '%d newsletters', $emails_count, 'mailpoet'), $emails_count) . "\n"; $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); $this->progressbar->setTotalCount($total_count);
@@ -424,7 +427,7 @@ class MP2Migrator {
'id' => $custom_field['id'], 'id' => $custom_field['id'],
'name' => $custom_field['name'], 'name' => $custom_field['name'],
'type' => $this->mapCustomFieldType($custom_field['type']), 'type' => $this->mapCustomFieldType($custom_field['type']),
'params' => $this->mapCustomFieldParams($custom_field), 'params' => $this->mapCustomFieldParams($custom_field['name'], unserialize($custom_field['settings'])),
); );
$custom_field = new CustomField(); $custom_field = new CustomField();
$custom_field->createOrUpdate($data); $custom_field->createOrUpdate($data);
@@ -443,6 +446,9 @@ class MP2Migrator {
case 'input': case 'input':
$type = 'text'; $type = 'text';
break; break;
case 'list':
$type = 'segment';
break;
default: default:
$type = $mp2_type; $type = $mp2_type;
} }
@@ -452,17 +458,42 @@ class MP2Migrator {
/** /**
* Map the MailPoet 2 custom field settings with the MailPoet custom field params * Map the MailPoet 2 custom field settings with the MailPoet custom field params
* *
* @param array $custom_field MP2 custom field * @param string $name Parameter name
* @param array $params MP2 parameters
* @return string serialized MP3 custom field params * @return string serialized MP3 custom field params
*/ */
private function mapCustomFieldParams($custom_field) { private function mapCustomFieldParams($name, $params) {
$params = unserialize($custom_field['settings']); if(!isset($params['label'])) {
$params['label'] = $custom_field['name']; $params['label'] = $name;
}
if(isset($params['required'])) {
$params['required'] = (bool)$params['required'];
}
if(isset($params['validate'])) { if(isset($params['validate'])) {
$params['validate'] = $this->mapCustomFieldValidateValue($params['validate']); $params['validate'] = $this->mapCustomFieldValidateValue($params['validate']);
} }
if(isset($params['date_order'])) { // Convert the date_order field if(isset($params['date_order'])) { // Convert the date_order field
$params['date_format'] = strtoupper($params['date_order']); switch($params['date_type']) {
case 'year_month':
if(preg_match('/y$/i', $params['date_order'])) {
$params['date_format'] = 'MM/YYYY';
} else {
$params['date_format'] = 'YYYY/MM';
}
break;
case 'month';
$params['date_format'] = 'MM';
break;
case 'year';
$params['date_format'] = 'YYYY';
break;
default:
$params['date_format'] = strtoupper($params['date_order']);
}
unset($params['date_order']); unset($params['date_order']);
} }
return $params; return $params;
@@ -739,4 +770,195 @@ class MP2Migrator {
return $mappings; return $mappings;
} }
/**
* Import the forms
*
*/
private function importForms() {
$imported_forms_count = 0;
if($this->importStopped()) {
return;
}
$this->log(__("Importing forms...", 'mailpoet'));
do {
if($this->importStopped()) {
break;
}
$forms = $this->getForms(self::CHUNK_SIZE);
$forms_count = count($forms);
if(is_array($forms)) {
foreach($forms as $form) {
$new_form = $this->importForm($form);
if(!empty($new_form)) {
$imported_forms_count++;
}
}
}
$this->progressbar->incrementCurrentCount($forms_count);
} while(($forms != null) && ($forms_count > 0));
$this->log(sprintf(_n("%d form imported", "%d forms imported", $imported_forms_count, 'mailpoet'), $imported_forms_count));
}
/**
* Get the Mailpoet 2 forms
*
* @global object $wpdb
* @param int $limit Number of forms max
* @return array Forms
*/
private function getForms($limit) {
global $wpdb;
$forms = array();
$last_id = Setting::getValue('last_imported_form_id', 0);
$table = MP2_FORM_TABLE;
$sql = "
SELECT f.*
FROM `$table` f
WHERE f.form_id > '$last_id'
ORDER BY f.form_id
LIMIT $limit
";
$forms = $wpdb->get_results($sql, ARRAY_A);
return $forms;
}
/**
* Import a form
*
* @param array $form_data Form data
* @return Form
*/
private function importForm($form_data) {
$serialized_data = base64_decode($form_data['data']);
$data = unserialize($serialized_data);
$settings = $data['settings'];
$body = $data['body'];
$segments = $this->getMappedSegmentIds($settings['lists']);
$mp3_form_settings = array(
'on_success' => $settings['on_success'],
'success_message' => $settings['success_message'],
'segments_selected_by' => $settings['lists_selected_by'],
'segments' => $segments,
);
$mp3_form_body = array();
foreach($body as $field) {
$type = $this->mapCustomFieldType($field['type']);
if($type == 'segment') {
$field_id = 'segments';
} else {
switch($field['field']) {
case 'firstname':
$field_id = 'first_name';
break;
case 'lastname':
$field_id = 'last_name';
break;
default:
$field_id = $field['field'];
}
}
$field_id = preg_replace('/^cf_(\d+)$/', '$1', $field_id);
$params = $this->mapCustomFieldParams($field['name'], $field['params']);
if(isset($params['text'])) {
$params['text'] = $this->replaceMP2Shortcodes(html_entity_decode($params['text']));
}
if(isset($params['values'])) {
$params['values'] = $this->replaceListIds($params['values']);
}
$mp3_form_body[] = array(
'type' => $type,
'name' => $field['name'],
'id' => $field_id,
'unique' => !in_array($field['type'], array('html', 'divider', 'email', 'submit'))? "1" : "0",
'static' => in_array($field_id, array('email', 'submit'))? "1" : "0",
'params' => $params,
'position' => isset($field['position'])? $field['position'] : '',
);
}
$form = Form::createOrUpdate(array(
'name' => $form_data['name'],
'body' => $mp3_form_body,
'settings' => $mp3_form_settings,
));
Setting::setValue('last_imported_form_id', $form_data['form_id']);
return $form;
}
/**
* Get the MP3 segments IDs of the MP2 lists IDs
*
* @param array $mp2_list_ids
*/
private function getMappedSegmentIds($mp2_list_ids) {
$mp3_segment_ids = array();
foreach($mp2_list_ids as $list_id) {
if(isset($this->segments_mapping[$list_id])) {
$mp3_segment_ids[] = $this->segments_mapping[$list_id];
}
}
return $mp3_segment_ids;
}
/**
* Replace the MP2 shortcodes used in the textarea fields
*
* @param string $text Text
* @return string Text
*/
private function replaceMP2Shortcodes($text) {
$text = str_replace('[total_subscribers]', '[mailpoet_subscribers_count]', $text);
$text = preg_replace_callback('/\[wysija_subscribers_count list_id="(.*)" \]/', array($this, 'replaceMP2ShortcodesCallback'), $text);
return $text;
}
/**
* Callback function for MP2 shortcodes replacement
*
* @param array $matches PREG matches
* @return string Replacement
*/
private function replaceMP2ShortcodesCallback($matches) {
if(!empty($matches)) {
$mp2_lists = explode(',', $matches[1]);
$segments = $this->getMappedSegmentIds($mp2_lists);
$segments_ids = implode(',', $segments);
return '[mailpoet_subscribers_count segments=' . $segments_ids . ']';
}
}
/**
* Replace the MP2 list IDs by MP3 segment IDs
*
* @param array $values Field values
* @return array Field values
*/
private function replaceListIds($values) {
$mp3_values = array();
foreach($values as $value) {
$mp3_value = array();
foreach($value as $item => $item_value) {
if(($item == 'list_id') && isset($this->segments_mapping[$item_value])) {
$segment_id = $this->segments_mapping[$item_value];
$mp3_value['id'] = $segment_id;
$segment = Segment::findOne($segment_id);
if(isset($segment)) {
$mp3_value['name'] = $segment->get('name');
}
} else {
$mp3_value[$item] = $item_value;
}
}
if(!empty($mp3_value)) {
$mp3_values[] = $mp3_value;
}
}
return $mp3_values;
}
} }

View File

@@ -6,7 +6,7 @@ use MailPoet\Models\MappingToExternalEntities;
use MailPoet\Models\Segment; use MailPoet\Models\Segment;
use MailPoet\Models\Subscriber; use MailPoet\Models\Subscriber;
use MailPoet\Models\SubscriberCustomField; use MailPoet\Models\SubscriberCustomField;
use MailPoet\Models\SubscriberSegment; use MailPoet\Models\Form;
use Helper\Database; use Helper\Database;
class MP2MigratorTest extends MailPoetTest { class MP2MigratorTest extends MailPoetTest {
@@ -349,4 +349,151 @@ class MP2MigratorTest extends MailPoetTest {
expect($result[$old_id])->equals($new_id); expect($result[$old_id])->equals($new_id);
} }
/**
* Test the importForms function
*
* @global object $wpdb
*/
public function testImportForms() {
global $wpdb;
// Check the forms number
$this->initImport();
$this->loadMP2Fixtures();
$this->invokeMethod($this->MP2Migrator, 'importForms');
expect(Form::count())->equals(2);
// Check a form data
$this->initImport();
$id = 999;
$name = 'Test form';
$list_id = 2;
// Insert a MP2 list
$wpdb->insert($wpdb->prefix . 'wysija_list', array(
'list_id' => $list_id,
'name' => 'Test list',
'description' => 'Test list description',
'is_enabled' => 1,
'is_public' => 1,
'created_at' => 1486319877,
));
$this->invokeMethod($this->MP2Migrator, 'importSegments');
$importedSegmentsMapping = $this->MP2Migrator->getImportedMapping('segments');
// Insert a MP2 form
$data = array(
'version' => 0.4,
'settings' => array(
'on_success' => 'message',
'success_message' => 'Test message',
'lists' => array($list_id),
'lists_selected_by' => 'admin',
),
'body' => array(
array(
'name' => 'E-mail',
'type' => 'input',
'field' => 'email',
'params' => array(
'label' => 'E-mail',
'required' => 1,
),
),
),
);
$wpdb->insert($wpdb->prefix . 'wysija_form', array(
'form_id' => $id,
'name' => $name,
'data' => base64_encode(serialize($data)),
));
$this->invokeMethod($this->MP2Migrator, 'importForms');
$table = MP_FORMS_TABLE;
$form = $wpdb->get_row("SELECT * FROM $table WHERE id=" . 1);
expect($form->name)->equals($name);
$settings = unserialize(($form->settings));
expect($settings['on_success'])->equals('message');
expect($settings['success_message'])->equals('Test message');
expect($settings['segments'][0])->equals($importedSegmentsMapping[$list_id]);
$body = unserialize(($form->body));
expect($body[0]['name'])->equals('E-mail');
expect($body[0]['type'])->equals('text');
}
/**
* Test the replaceMP2Shortcodes function
*
*/
public function testReplaceMP2Shortcodes() {
$this->initImport();
$result = $this->invokeMethod($this->MP2Migrator, 'replaceMP2Shortcodes', array('[total_subscribers]'));
expect($result)->equals('[mailpoet_subscribers_count]');
$result = $this->invokeMethod($this->MP2Migrator, 'replaceMP2Shortcodes', array('Total: [total_subscribers]'));
expect($result)->equals('Total: [mailpoet_subscribers_count]');
$result = $this->invokeMethod($this->MP2Migrator, 'replaceMP2Shortcodes', array('Total: [total_subscribers] found'));
expect($result)->equals('Total: [mailpoet_subscribers_count] found');
$result = $this->invokeMethod($this->MP2Migrator, 'replaceMP2Shortcodes', array('[wysija_subscribers_count list_id="1,2" ]'));
expect($result)->notEquals('mailpoet_subscribers_count segments=1,2');
$this->loadMP2Fixtures();
$this->invokeMethod($this->MP2Migrator, 'importSegments');
$result = $this->invokeMethod($this->MP2Migrator, 'replaceMP2Shortcodes', array('[wysija_subscribers_count list_id="1,2" ]'));
$importedSegmentsMapping = $this->MP2Migrator->getImportedMapping('segments');
expect($result)->equals(sprintf('[mailpoet_subscribers_count segments=%d,%d]', $importedSegmentsMapping[1], $importedSegmentsMapping[2]));
}
/**
* Test the getMappedSegmentIds function
*
*/
public function testGetMappedSegmentIds() {
$this->initImport();
$lists = array(1, 2);
$this->loadMP2Fixtures();
$this->invokeMethod($this->MP2Migrator, 'importSegments');
$importedSegmentsMapping = $this->MP2Migrator->getImportedMapping('segments');
$result = $this->invokeMethod($this->MP2Migrator, 'getMappedSegmentIds', array($lists));
$expected_lists = array($importedSegmentsMapping[1],$importedSegmentsMapping[2]);
expect($result)->equals($expected_lists);
}
/**
* Test the replaceListIds function
*
*/
public function testReplaceListIds() {
$this->initImport();
$lists = array(
array(
'list_id' => 1,
'name' => 'List 1',
),
array(
'list_id' => 2,
'name' => 'List 2',
),
);
$this->loadMP2Fixtures();
$this->invokeMethod($this->MP2Migrator, 'importSegments');
$importedSegmentsMapping = $this->MP2Migrator->getImportedMapping('segments');
$result = $this->invokeMethod($this->MP2Migrator, 'replaceListIds', array($lists));
$expected_lists = array(
array(
'id' => $importedSegmentsMapping[1],
'name' => 'List 1',
),
array(
'id' => $importedSegmentsMapping[2],
'name' => 'List 2',
),
);
expect($result)->equals($expected_lists);
}
} }

View File

@@ -10,8 +10,8 @@
<h3><%= __('What will be kept in MailPoet 3') %></h3> <h3><%= __('What will be kept in MailPoet 3') %></h3>
<ul> <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><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><strong><%= __('Forms') %> <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><%= __('Settings') %> (<%= __('soon') %>!)</li>
<li><%= __('Forms') %> (<%= __('soon') %>!)</li>
<li><%= __('Archive of sent newsletters') %> (<%= __('soon') %>!)</li> <li><%= __('Archive of sent newsletters') %> (<%= __('soon') %>!)</li>
</ul> </ul>