<?php
namespace MailPoet\Config;
if (!defined('ABSPATH')) exit;
use MailPoet\Models\CustomField;
use MailPoet\Models\Form;
use MailPoet\Models\MappingToExternalEntities;
use MailPoet\Models\Segment;
use MailPoet\Models\Subscriber;
use MailPoet\Models\SubscriberCustomField;
use MailPoet\Models\SubscriberSegment;
use MailPoet\Settings\SettingsController;
use MailPoet\Util\Notices\AfterMigrationNotice;
use MailPoet\Util\ProgressBar;
use MailPoet\WP\Functions as WPFunctions;
use MailPoetVendor\Idiorm\ORM;
class MP2Migrator {
const IMPORT_TIMEOUT_IN_SECONDS = 7200; // Timeout = 2 hours
const CHUNK_SIZE = 10; // To import the data by batch
const MIGRATION_COMPLETE_SETTING_KEY = 'mailpoet_migration_complete';
const MIGRATION_STARTED_SETTING_KEY = 'mailpoet_migration_started';
/** @var SettingsController */
private $settings;
/** @var Activator */
private $activator;
private $logFile;
public $logFileUrl;
public $progressbar;
private $segmentsMapping = []; // Mapping between old and new segment IDs
private $wpUsersSegment;
private $doubleOptinEnabled = true;
private $mp2CampaignTable;
private $mp2CustomFieldTable;
private $mp2EmailTable;
private $mp2FormTable;
private $mp2ListTable;
private $mp2UserTable;
private $mp2UserListTable;
public function __construct(
SettingsController $settings,
Activator $activator
) {
$this->defineMP2Tables();
$logFilename = 'mp2migration.log';
$this->logFile = Env::$tempPath . '/' . $logFilename;
$this->logFileUrl = Env::$tempUrl . '/' . $logFilename;
$this->progressbar = new ProgressBar('mp2migration');
$this->settings = $settings;
$this->activator = $activator;
}
private function defineMP2Tables() {
global $wpdb;
$this->mp2CampaignTable = defined('MP2_CAMPAIGN_TABLE')
? MP2_CAMPAIGN_TABLE
: $wpdb->prefix . 'wysija_campaign';
$this->mp2CustomFieldTable = defined('MP2_CUSTOM_FIELD_TABLE')
? MP2_CUSTOM_FIELD_TABLE
: $wpdb->prefix . 'wysija_custom_field';
$this->mp2EmailTable = defined('MP2_EMAIL_TABLE')
? MP2_EMAIL_TABLE
: $wpdb->prefix . 'wysija_email';
$this->mp2FormTable = defined('MP2_FORM_TABLE')
? MP2_FORM_TABLE
: $wpdb->prefix . 'wysija_form';
$this->mp2ListTable = defined('MP2_LIST_TABLE')
? MP2_LIST_TABLE
: $wpdb->prefix . 'wysija_list';
$this->mp2UserTable = defined('MP2_USER_TABLE')
? MP2_USER_TABLE
: $wpdb->prefix . 'wysija_user';
$this->mp2UserListTable = defined('MP2_USER_LIST_TABLE')
? MP2_USER_LIST_TABLE
: $wpdb->prefix . 'wysija_user_list';
}
/**
* Test if the migration is already started but is not completed
*
* @return bool
*/
public function isMigrationStartedAndNotCompleted() {
return $this->settings->get(self::MIGRATION_STARTED_SETTING_KEY, false)
&& !$this->settings->get(self::MIGRATION_COMPLETE_SETTING_KEY, false);
}
/**
* Test if the migration is needed
*
* @return bool
*/
public function isMigrationNeeded() {
if ($this->settings->get(self::MIGRATION_COMPLETE_SETTING_KEY)) {
return false;
} else {
return $this->tableExists($this->mp2CampaignTable); // Check if the MailPoet 2 tables exist
}
}
/**
* Store the "Skip import" choice
*
*/
public function skipImport() {
$this->settings->set(self::MIGRATION_COMPLETE_SETTING_KEY, true);
}
/**
* Test if a table exists
*
* @param string $table Table name
* @return bool
*/
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 (!$this->settings->get(self::MIGRATION_STARTED_SETTING_KEY, false)) {
$this->emptyLog();
$this->progressbar->setTotalCount(0);
}
$this->enqueueScripts();
}
/**
* Register the JavaScript for the admin area.
*
*/
private function enqueueScripts() {
WPFunctions::get()->wpEnqueueScript('jquery-ui-progressbar');
}
/**
* Write a message in the log file
*
* @param string $message
*/
private function log($message) {
file_put_contents($this->logFile, "$message\n", FILE_APPEND);
}
/**
* Import the data from MailPoet 2
*
* @return string Result
*/
public function import() {
if (strpos((string)@ini_get('disable_functions'), 'set_time_limit') === false) {
@set_time_limit(3600);
}
ob_start();
$datetime = new \MailPoet\WP\DateTime();
$this->log(sprintf('=== ' . mb_strtoupper(__('Start import', 'mailpoet'), 'UTF-8') . ' %s ===', $datetime->formatTime(time(), \MailPoet\WP\DateTime::DEFAULT_DATE_TIME_FORMAT)));
$this->settings->set('import_stopped', false); // Reset the stop import action
if (!$this->settings->get(self::MIGRATION_STARTED_SETTING_KEY, false)) {
$this->eraseMP3Data();
$this->settings->set(self::MIGRATION_STARTED_SETTING_KEY, true);
$this->displayDataToMigrate();
}
$this->loadDoubleOptinSettings();
$this->importSegments();
$this->importCustomFields();
$this->importSubscribers();
$this->importForms();
$this->importSettings();
if (!$this->importStopped()) {
$this->settings->set(self::MIGRATION_COMPLETE_SETTING_KEY, true);
$this->log(mb_strtoupper(__('Import complete', 'mailpoet'), 'UTF-8'));
$afterMigrationNotice = new AfterMigrationNotice();
$afterMigrationNotice->enable();
}
$this->log(sprintf('=== ' . mb_strtoupper(__('End import', 'mailpoet'), 'UTF-8') . ' %s ===', $datetime->formatTime(time(), \MailPoet\WP\DateTime::DEFAULT_DATE_TIME_FORMAT)));
$result = ob_get_contents();
ob_clean();
return (string)$result;
}
/**
* Empty the log file
*
*/
private function emptyLog() {
file_put_contents($this->logFile, '');
}
/**
* Erase all the MailPoet 3 data
*
*/
private function eraseMP3Data() {
$this->activator->deactivate();
$this->activator->activate();
$this->deleteSegments();
$this->resetMigrationCounters();
$this->log(__("MailPoet data erased", 'mailpoet'));
}
/**
* Reset the migration counters
*
*/
private function resetMigrationCounters() {
$this->settings->set('last_imported_user_id', 0);
$this->settings->set('last_imported_list_id', 0);
$this->settings->set('last_imported_form_id', 0);
}
private function loadDoubleOptinSettings() {
$encodedOption = WPFunctions::get()->getOption('wysija');
$values = unserialize(base64_decode($encodedOption));
if (isset($values['confirm_dbleoptin']) && $values['confirm_dbleoptin'] === '0') {
$this->doubleOptinEnabled = false;
}
}
/**
* Delete the existing segments except the wp_users and woocommerce_users segments
*
*/
private function deleteSegments() {
global $wpdb;
$table = MP_SEGMENTS_TABLE;
$wpdb->query("DELETE FROM {$table} WHERE type != '" . Segment::TYPE_WP_USERS . "' AND type != '" . Segment::TYPE_WC_USERS . "'");
}
/**
* Stop the import
*
*/
public function stopImport() {
$this->settings->set('import_stopped', true);
$this->log(mb_strtoupper(__('Import stopped by user', 'mailpoet'), 'UTF-8'));
}
/**
* Test if the import must stop
*
* @return bool Import must stop or not
*/
private function importStopped() {
return $this->settings->get('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 = '';
$totalCount = 0;
$this->progressbar->setTotalCount(0);
$result .= WPFunctions::get()->__('MailPoet 2 data found:', 'mailpoet') . "\n";
// User Lists
$usersListsCount = ORM::for_table($this->mp2ListTable)->count();
$totalCount += $usersListsCount;
$result .= sprintf(_n('%d subscribers list', '%d subscribers lists', $usersListsCount, 'mailpoet'), $usersListsCount) . "\n";
// Users
$usersCount = ORM::for_table($this->mp2UserTable)->count();
$totalCount += $usersCount;
$result .= sprintf(_n('%d subscriber', '%d subscribers', $usersCount, 'mailpoet'), $usersCount) . "\n";
// Forms
$formsCount = ORM::for_table($this->mp2FormTable)->count();
$totalCount += $formsCount;
$result .= sprintf(_n('%d form', '%d forms', $formsCount, 'mailpoet'), $formsCount) . "\n";
$this->progressbar->setTotalCount($totalCount);
return $result;
}
/**
* Import the subscribers segments
*
*/
private function importSegments() {
$importedSegmentsCount = 0;
if ($this->importStopped()) {
$this->segmentsMapping = $this->getImportedMapping('segments');
return;
}
$this->log(__("Importing segments...", 'mailpoet'));
do {
if ($this->importStopped()) {
break;
}
$lists = $this->getLists(self::CHUNK_SIZE);
$listsCount = count($lists);
if (is_array($lists)) {
foreach ($lists as $list) {
$segment = $this->importSegment($list);
if (!empty($segment)) {
$importedSegmentsCount++;
}
}
}
$this->progressbar->incrementCurrentCount($listsCount);
} while (($lists != null) && ($listsCount > 0));
$this->segmentsMapping = $this->getImportedMapping('segments');
$this->log(sprintf(_n("%d segment imported", "%d segments imported", $importedSegmentsCount, 'mailpoet'), $importedSegmentsCount));
}
/**
* 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;
$lastId = intval($this->settings->get('last_imported_list_id', 0));
$table = $this->mp2ListTable;
$sql = "
SELECT l.list_id, l.name, l.description, l.is_enabled, l.created_at
FROM `$table` l
WHERE l.list_id > '$lastId'
ORDER BY l.list_id
LIMIT $limit
";
$lists = $wpdb->get_results($sql, ARRAY_A);
return $lists;
}
/**
* Import a segment
*
* @param array $listData List data
* @return Segment
*/
private function importSegment($listData) {
$datetime = new \MailPoet\WP\DateTime();
if ($listData['is_enabled']) {
$segment = Segment::createOrUpdate([
'name' => $listData['name'],
'type' => 'default',
'description' => !empty($listData['description']) ? $listData['description'] : '',
'created_at' => $datetime->formatTime($listData['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([
'old_id' => $listData['list_id'],
'type' => 'segments',
'new_id' => $segment->id,
'created_at' => $datetime->formatTime(time(), \MailPoet\WP\DateTime::DEFAULT_DATE_TIME_FORMAT),
]);
}
$this->settings->set('last_imported_list_id', $listData['list_id']);
return $segment;
}
/**
* Import the custom fields
*
*/
private function importCustomFields() {
$importedCustomFieldsCount = 0;
if ($this->importStopped()) {
return;
}
$this->log(__("Importing custom fields...", 'mailpoet'));
$customFields = $this->getCustomFields();
foreach ($customFields as $customField) {
$result = $this->importCustomField($customField);
if (!empty($result)) {
$importedCustomFieldsCount++;
}
}
$this->log(sprintf(_n("%d custom field imported", "%d custom fields imported", $importedCustomFieldsCount, 'mailpoet'), $importedCustomFieldsCount));
}
/**
* Get the Mailpoet 2 custom fields
*
* @global object $wpdb
* @return array Custom fields
*/
private function getCustomFields() {
global $wpdb;
$customFields = [];
$table = $this->mp2CustomFieldTable;
$sql = "
SELECT cf.id, cf.name, cf.type, cf.required, cf.settings
FROM `$table` cf
";
$customFields = $wpdb->get_results($sql, ARRAY_A);
return $customFields;
}
/**
* Import a custom field
*
* @param array $customField MP2 custom field
* @return CustomField
*/
private function importCustomField($customField) {
$data = [
'id' => $customField['id'],
'name' => $customField['name'],
'type' => $this->mapCustomFieldType($customField['type']),
'params' => $this->mapCustomFieldParams($customField['name'], unserialize($customField['settings'])),
];
$customField = new CustomField();
$customField->createOrUpdate($data);
return $customField;
}
/**
* Map the MailPoet 2 custom field type with the MailPoet custom field type
*
* @param string $mp2Type MP2 custom field type
* @return string MP3 custom field type
*/
private function mapCustomFieldType($mp2Type) {
$type = '';
switch ($mp2Type) {
case 'input':
$type = 'text';
break;
case 'list':
$type = 'segment';
break;
default:
$type = $mp2Type;
}
return $type;
}
/**
* Map the MailPoet 2 custom field settings with the MailPoet custom field params
*
* @param string $name Parameter name
* @param array $params MP2 parameters
* @return array serialized MP3 custom field params
*/
private function mapCustomFieldParams($name, $params) {
if (!isset($params['label'])) {
$params['label'] = $name;
}
if (isset($params['required'])) {
$params['required'] = (bool)$params['required'];
}
if (isset($params['validate'])) {
$params['validate'] = $this->mapCustomFieldValidateValue($params['validate']);
}
if (isset($params['date_order'])) { // Convert the date_order field
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'] = mb_strtoupper($params['date_order'], 'UTF-8');
}
unset($params['date_order']);
}
return $params;
}
/**
* Map the validate value
*
* @param string $mp2Value MP2 value
* @return string MP3 value
*/
private function mapCustomFieldValidateValue($mp2Value) {
$value = '';
switch ($mp2Value) {
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() {
$importedSubscribersCount = 0;
if ($this->importStopped()) {
return;
}
$this->log(__("Importing subscribers...", 'mailpoet'));
$this->wpUsersSegment = Segment::getWPSegment();
do {
if ($this->importStopped()) {
break;
}
$users = $this->getUsers(self::CHUNK_SIZE);
$usersCount = count($users);
if (is_array($users)) {
foreach ($users as $user) {
$subscriber = $this->importSubscriber($user);
if (!empty($subscriber)) {
$importedSubscribersCount++;
$this->importSubscriberSegments($subscriber, $user['user_id']);
$this->importSubscriberCustomFields($subscriber, $user);
}
}
}
$this->progressbar->incrementCurrentCount($usersCount);
} while (($users != null) && ($usersCount > 0));
$this->log(sprintf(_n("%d subscriber imported", "%d subscribers imported", $importedSubscribersCount, 'mailpoet'), $importedSubscribersCount));
}
/**
* Get the Mailpoet 2 users
*
* @global object $wpdb
* @param int $limit Number of users max
* @return array Users
*/
private function getUsers($limit) {
global $wpdb;
$lastId = intval($this->settings->get('last_imported_user_id', 0));
$table = $this->mp2UserTable;
$sql = "
SELECT u.*
FROM `$table` u
WHERE u.user_id > '$lastId'
ORDER BY u.user_id
LIMIT $limit
";
$users = $wpdb->get_results($sql, ARRAY_A);
return $users;
}
/**
* Import a subscriber
*
* @param array $userData User data
* @return Subscriber
*/
private function importSubscriber($userData) {
$datetime = new \MailPoet\WP\DateTime();
$subscriber = Subscriber::createOrUpdate([
'wp_user_id' => !empty($userData['wpuser_id']) ? $userData['wpuser_id'] : null,
'email' => $userData['email'],
'first_name' => $userData['firstname'],
'last_name' => $userData['lastname'],
'status' => $this->mapUserStatus($userData['status']),
'created_at' => $datetime->formatTime($userData['created_at'], \MailPoet\WP\DateTime::DEFAULT_DATE_TIME_FORMAT),
'subscribed_ip' => !empty($userData['ip']) ? $userData['ip'] : null,
'confirmed_ip' => !empty($userData['confirmed_ip']) ? $userData['confirmed_ip'] : null,
'confirmed_at' => !empty($userData['confirmed_at']) ? $datetime->formatTime($userData['confirmed_at'], \MailPoet\WP\DateTime::DEFAULT_DATE_TIME_FORMAT) : null,
]);
$this->settings->set('last_imported_user_id', $userData['user_id']);
if (!empty($subscriber)) {
// Map the subscriber with its old ID
$mapping = new MappingToExternalEntities();
$mapping->create([
'old_id' => $userData['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 $mp2UserStatus MP2 user status
* @return string MP3 user status
*/
private function mapUserStatus($mp2UserStatus) {
switch ($mp2UserStatus) {
case 1:
$status = 'subscribed';
break;
case -1:
$status = 'unsubscribed';
break;
case 0:
default:
//if MP2 double-optin is disabled, we change "unconfirmed" status in MP2 to "confirmed" status in MP3.
if (!$this->doubleOptinEnabled) {
$status = 'subscribed';
} else {
$status = 'unconfirmed';
}
}
return $status;
}
/**
* Import the segments for a subscriber
*
* @param Subscriber $subscriber MP3 subscriber
* @param int $userId MP2 user ID
*/
private function importSubscriberSegments($subscriber, $userId) {
$userLists = $this->getUserLists($userId);
foreach ($userLists as $userList) {
$this->importSubscriberSegment($subscriber->id, $userList);
}
}
/**
* Get the lists for a user
*
* @global object $wpdb
* @param int $userId User ID
* @return array Users Lists
*/
private function getUserLists($userId) {
global $wpdb;
$table = $this->mp2UserListTable;
$sql = "
SELECT ul.list_id, ul.sub_date, ul.unsub_date
FROM `$table` ul
WHERE ul.user_id = '$userId'
";
$userLists = $wpdb->get_results($sql, ARRAY_A);
return $userLists;
}
/**
* Import a subscriber segment
*
* @param int $subscriberId
* @param array $userList
* @return SubscriberSegment|null
*/
private function importSubscriberSegment($subscriberId, $userList) {
$subscriberSegment = null;
$datetime = new \MailPoet\WP\DateTime();
if (isset($this->segmentsMapping[$userList['list_id']])) {
$segmentId = $this->segmentsMapping[$userList['list_id']];
$status = (($segmentId == $this->wpUsersSegment->id) || empty($userList['unsub_date'])) ? 'subscribed' : 'unsubscribed'; // the users belonging to the wp_users segment are always subscribed
$data = [
'subscriber_id' => $subscriberId,
'segment_id' => $segmentId,
'status' => $status,
'created_at' => $datetime->formatTime($userList['sub_date'], \MailPoet\WP\DateTime::DEFAULT_DATE_TIME_FORMAT),
];
$data['updated_at'] = !empty($userList['unsub_date']) ? $datetime->formatTime($userList['unsub_date'], \MailPoet\WP\DateTime::DEFAULT_DATE_TIME_FORMAT) : $data['created_at'];
$subscriberSegment = new SubscriberSegment();
$subscriberSegment->createOrUpdate($data);
}
return $subscriberSegment;
}
/**
* Import the custom fields values for a subscriber
*
* @param Subscriber $subscriber MP3 subscriber
* @param array $user MP2 user
*/
private function importSubscriberCustomFields($subscriber, $user) {
$importedCustomFields = $this->getImportedCustomFields();
foreach ($importedCustomFields as $customField) {
$customFieldColumn = 'cf_' . $customField['id'];
$this->importSubscriberCustomField($subscriber->id, $customField, $user[$customFieldColumn]);
}
}
/**
* 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
";
$customFields = $wpdb->get_results($sql, ARRAY_A);
return $customFields;
}
/**
* Import a subscriber custom field
*
* @param int $subscriberId Subscriber ID
* @param array $customField Custom field
* @param string $customFieldValue Custom field value
* @return SubscriberCustomField
*/
private function importSubscriberCustomField($subscriberId, $customField, $customFieldValue) {
if ($customField['type'] == 'date') {
$datetime = new \MailPoet\WP\DateTime();
$value = $datetime->formatTime($customFieldValue, \MailPoet\WP\DateTime::DEFAULT_DATE_TIME_FORMAT); // Convert the date field
} else {
$value = $customFieldValue;
}
$data = [
'subscriber_id' => $subscriberId,
'custom_field_id' => $customField['id'],
'value' => isset($value) ? $value : '',
];
$subscriberCustomField = new SubscriberCustomField();
$subscriberCustomField->createOrUpdate($data);
return $subscriberCustomField;
}
/**
* Get the mapping between the MP2 and the imported MP3 IDs
*
* @param string $model Model (segment,...)
* @return array Mapping
*/
public function getImportedMapping($model) {
$mappings = [];
$mappingRelations = MappingToExternalEntities::where('type', $model)->findArray();
foreach ($mappingRelations as $relation) {
$mappings[$relation['old_id']] = $relation['new_id'];
}
return $mappings;
}
/**
* Import the forms
*
*/
private function importForms() {
$importedFormsCount = 0;
if ($this->importStopped()) {
return;
}
$this->log(__("Importing forms...", 'mailpoet'));
do {
if ($this->importStopped()) {
break;
}
$forms = $this->getForms(self::CHUNK_SIZE);
$formsCount = count($forms);
if (is_array($forms)) {
foreach ($forms as $form) {
$newForm = $this->importForm($form);
if (!empty($newForm)) {
$importedFormsCount++;
}
}
}
$this->progressbar->incrementCurrentCount($formsCount);
} while (($forms != null) && ($formsCount > 0));
$this->log(sprintf(_n("%d form imported", "%d forms imported", $importedFormsCount, 'mailpoet'), $importedFormsCount));
}
/**
* Get the Mailpoet 2 forms
*
* @global object $wpdb
* @param int $limit Number of forms max
* @return array Forms
*/
private function getForms($limit) {
global $wpdb;
$lastId = intval($this->settings->get('last_imported_form_id', 0));
$table = $this->mp2FormTable;
$sql = "
SELECT f.*
FROM `$table` f
WHERE f.form_id > '$lastId'
ORDER BY f.form_id
LIMIT $limit
";
$forms = $wpdb->get_results($sql, ARRAY_A);
return $forms;
}
/**
* Import a form
*
* @param array $formData Form data
* @return Form
*/
private function importForm($formData) {
$serializedData = base64_decode($formData['data']);
$data = unserialize($serializedData);
$settings = $data['settings'];
$body = $data['body'];
$segments = $this->getMappedSegmentIds($settings['lists']);
$mp3FormSettings = [
'on_success' => $settings['on_success'],
'success_message' => $settings['success_message'],
'segments_selected_by' => $settings['lists_selected_by'],
'segments' => $segments,
];
$mp3FormBody = [];
foreach ($body as $field) {
$type = $this->mapCustomFieldType($field['type']);
if ($type == 'segment') {
$fieldId = 'segments';
} else {
switch ($field['field']) {
case 'firstname':
$fieldId = 'first_name';
break;
case 'lastname':
$fieldId = 'last_name';
break;
default:
$fieldId = $field['field'];
}
}
$fieldId = preg_replace('/^cf_(\d+)$/', '$1', $fieldId);
$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']);
}
$mp3FormBody[] = [
'type' => $type,
'name' => $field['name'],
'id' => $fieldId,
'unique' => !in_array($field['type'], ['html', 'divider', 'email', 'submit']) ? "1" : "0",
'static' => in_array($fieldId, ['email', 'submit']) ? "1" : "0",
'params' => $params,
'position' => isset($field['position']) ? $field['position'] : '',
];
}
$form = Form::createOrUpdate([
'name' => $formData['name'],
'body' => $mp3FormBody,
'settings' => $mp3FormSettings,
]);
$this->settings->set('last_imported_form_id', $formData['form_id']);
return $form;
}
/**
* Get the MP3 segments IDs of the MP2 lists IDs
*
* @param array $mp2ListIds
*/
private function getMappedSegmentIds($mp2ListIds) {
$mp3SegmentIds = [];
foreach ($mp2ListIds as $listId) {
if (isset($this->segmentsMapping[$listId])) {
$mp3SegmentIds[] = $this->segmentsMapping[$listId];
}
}
return $mp3SegmentIds;
}
/**
* Replace the MP2 shortcodes used in the textarea fields
*
* @param string $text Text
* @return string|null Text
*/
private function replaceMP2Shortcodes($text) {
$text = str_replace('[total_subscribers]', '[mailpoet_subscribers_count]', $text);
$text = preg_replace_callback(
'/\[wysija_subscribers_count list_id="(.*)" \]/',
function ($matches) {
return $this->replaceMP2ShortcodesCallback($matches);
},
$text
);
return $text;
}
/**
* Callback function for MP2 shortcodes replacement
*
* @param array $matches PREG matches
* @return string Replacement
*/
private function replaceMP2ShortcodesCallback($matches) {
if (!empty($matches)) {
$mp2Lists = explode(',', $matches[1]);
$segments = $this->getMappedSegmentIds($mp2Lists);
$segmentsIds = implode(',', $segments);
return '[mailpoet_subscribers_count segments=' . $segmentsIds . ']';
}
return '';
}
/**
* Replace the MP2 list IDs by MP3 segment IDs
*
* @param array $values Field values
* @return array Field values
*/
private function replaceListIds($values) {
$mp3Values = [];
foreach ($values as $value) {
$mp3Value = [];
foreach ($value as $item => $itemValue) {
if (($item == 'list_id') && isset($this->segmentsMapping[$itemValue])) {
$segmentId = $this->segmentsMapping[$itemValue];
$mp3Value['id'] = $segmentId;
$segment = Segment::findOne($segmentId);
if ($segment instanceof Segment) {
$mp3Value['name'] = $segment->get('name');
}
} else {
$mp3Value[$item] = $itemValue;
}
}
if (!empty($mp3Value)) {
$mp3Values[] = $mp3Value;
}
}
return $mp3Values;
}
/**
* Import the settings
*
*/
private function importSettings() {
$encodedOptions = WPFunctions::get()->getOption('wysija');
$options = unserialize(base64_decode($encodedOptions));
// Sender
$sender = $this->settings->get('sender');
$sender['name'] = isset($options['from_name']) ? $options['from_name'] : '';
$sender['address'] = isset($options['from_email']) ? $options['from_email'] : '';
$this->settings->set('sender', $sender);
// Reply To
$replyTo = $this->settings->get('reply_to');
$replyTo['name'] = isset($options['replyto_name']) ? $options['replyto_name'] : '';
$replyTo['address'] = isset($options['replyto_email']) ? $options['replyto_email'] : '';
$this->settings->set('reply_to', $replyTo);
// Bounce
$bounce = $this->settings->get('bounce');
$bounce['address'] = isset($options['bounce_email']) && WPFunctions::get()->isEmail($options['bounce_email']) ? $options['bounce_email'] : '';
$this->settings->set('bounce', $bounce);
// Notification
$notification = $this->settings->get('notification');
$notification['address'] = isset($options['emails_notified']) ? $options['emails_notified'] : '';
$this->settings->set('notification', $notification);
// Subscribe
$subscribe = $this->settings->get('subscribe');
$subscribe['on_comment']['enabled'] = isset($options['commentform']) ? $options['commentform'] : '0';
$subscribe['on_comment']['label'] = isset($options['commentform_linkname']) ? $options['commentform_linkname'] : '';
$subscribe['on_comment']['segments'] = isset($options['commentform_lists']) ? $this->getMappedSegmentIds($options['commentform_lists']) : [];
$subscribe['on_register']['enabled'] = isset($options['registerform']) ? $options['registerform'] : '0';
$subscribe['on_register']['label'] = isset($options['registerform_linkname']) ? $options['registerform_linkname'] : '';
$subscribe['on_register']['segments'] = isset($options['registerform_lists']) ? $this->getMappedSegmentIds($options['registerform_lists']) : [];
$this->settings->set('subscribe', $subscribe);
// Subscription
$subscription = $this->settings->get('subscription');
$subscription['pages']['unsubscribe'] = isset($options['unsubscribe_page']) ? $options['unsubscribe_page'] : '';
$subscription['pages']['confirmation'] = isset($options['confirmation_page']) ? $options['confirmation_page'] : '';
$subscription['pages']['manage'] = isset($options['subscriptions_page']) ? $options['subscriptions_page'] : '';
$subscription['segments'] = isset($options['manage_subscriptions_lists']) ? $this->getMappedSegmentIds($options['manage_subscriptions_lists']) : [];
$this->settings->set('subscription', $subscription);
// Confirmation email
$signupConfirmation = $this->settings->get('signup_confirmation');
$signupConfirmation['enabled'] = isset($options['confirm_dbleoptin']) && ($options['confirm_dbleoptin'] == 0) ? 0 : 1;
if (isset($options['confirm_email_id'])) {
$confirmEmailId = $options['confirm_email_id'];
$confirmEmail = $this->getEmail($confirmEmailId);
if (!empty($confirmEmail)) {
$signupConfirmation['subject'] = isset($confirmEmail['subject']) ? $confirmEmail['subject'] : '';
$signupConfirmation['body'] = isset($confirmEmail['body']) ? $confirmEmail['body'] : '';
}
}
$this->settings->set('signup_confirmation', $signupConfirmation);
// Analytics
$analytics = $this->settings->get('analytics');
$analytics['enabled'] = isset($options['analytics']) ? $options['analytics'] : '';
$this->settings->set('analytics', $analytics);
// MTA
$mtaGroup = isset($options['sending_method']) && ($options['sending_method'] == 'smtp') ? 'smtp' : 'website';
$this->settings->set('mta_group', $mtaGroup);
$mta = $this->settings->get('mta');
$mta['method'] = (isset($options['smtp_host']) && ($options['smtp_host'] == 'smtp.sendgrid.net')) ? 'SendGrid' : (isset($options['sending_method']) && ($options['sending_method'] == 'smtp') ? 'SMTP' : 'PHPMail');
$sendingEmailsNumber = isset($options['sending_emails_number']) ? $options['sending_emails_number'] : '';
$sendingEmailsEach = isset($options['sending_emails_each']) ? $options['sending_emails_each'] : '';
$mta['frequency']['emails'] = $this->mapFrequencyEmails($sendingEmailsNumber, $sendingEmailsEach);
$mta['frequency']['interval'] = $this->mapFrequencyInterval($sendingEmailsEach);
$mta['host'] = isset($options['smtp_host']) ? $options['smtp_host'] : '';
$mta['port'] = isset($options['smtp_port']) ? $options['smtp_port'] : '';
$mta['login'] = isset($options['smtp_login']) ? $options['smtp_login'] : '';
$mta['password'] = isset($options['smtp_password']) ? $options['smtp_password'] : '';
$mta['encryption'] = isset($options['smtp_secure']) ? $options['smtp_secure'] : '';
$mta['authentication'] = !isset($options['smtp_auth']) ? '1' : '-1';
$this->settings->set('mta', $mta);
// SMTP Provider
if ($mta['method'] == 'SendGrid') {
$this->settings->set('smtp_provider', 'SendGrid');
}
// Installation date
if (isset($options['installed_time'])) {
$datetime = new \MailPoet\WP\DateTime();
$installedAt = $datetime->formatTime($options['installed_time'], \MailPoet\WP\DateTime::DEFAULT_DATE_TIME_FORMAT);
$this->settings->set('installed_at', $installedAt);
}
$this->log(__("Settings imported", 'mailpoet'));
}
/**
* Get an email
*
* @global object $wpdb
* @param int $emailId
* @return array Email
*/
private function getEmail($emailId) {
global $wpdb;
$email = [];
$table = $this->mp2EmailTable;
$sql = "
SELECT e.*
FROM `$table` e
WHERE e.email_id = '$emailId'
";
$email = $wpdb->get_row($sql, ARRAY_A);
return $email;
}
/**
* Map the Email frequency interval
*
* @param string $intervalStr Interval
* @return string Interval
*/
private function mapFrequencyInterval($intervalStr) {
switch ($intervalStr) {
case 'one_min':
$interval = 1;
break;
case 'two_min':
$interval = 2;
break;
case 'five_min':
$interval = 5;
break;
case 'ten_min':
$interval = 10;
break;
default:
$interval = 15;
}
return (string)$interval;
}
/**
* Map the Email frequency number
*
* @param int $emailsNumber Emails number
* @param string $intervalStr Interval
* @return int Emails number
*/
private function mapFrequencyEmails($emailsNumber, $intervalStr) {
if (empty($emailsNumber)) {
$emailsNumber = 70;
} else {
switch ($intervalStr) {
case 'thirty_min':
$emailsNumber /= 2;
break;
case 'hourly':
case '':
$emailsNumber /= 4;
break;
case 'two_hours':
$emailsNumber /= 8;
break;
}
$emailsNumber = (int)round($emailsNumber);
}
return $emailsNumber;
}
}