312 lines
11 KiB
PHP
312 lines
11 KiB
PHP
<?php
|
|
|
|
namespace FluentCrm\App\Services\CrmMigrator;
|
|
|
|
use FluentCrm\App\Services\CrmMigrator\Api\Drip;
|
|
use FluentCrm\Framework\Support\Arr;
|
|
|
|
class DripMigrator extends BaseMigrator
|
|
{
|
|
public function getInfo()
|
|
{
|
|
$infoSvg = $this->getInfoIcon();
|
|
|
|
$logo = $this->getSvgLogo();
|
|
|
|
return [
|
|
'title' => 'Drip',
|
|
'description' => __('Transfer your Drip tags and contacts to FluentCRM', 'fluent-crm'),
|
|
'logo' => fluentCrmMix('images/migrators/drip.png'),
|
|
'logo_svg' => $logo,
|
|
'supports' => [
|
|
'tags' => true,
|
|
'lists' => false,
|
|
'empty_tags' => true,
|
|
'active_imports_only' => true
|
|
],
|
|
'credentials' => [
|
|
'api_key' => '',
|
|
'account_id' => ''
|
|
],
|
|
'field_map_info' => __('Email and main contact fields will be mapped automatically', 'fluent-crm'),
|
|
'credential_fields' => [
|
|
'api_key' => [
|
|
'label' => __('API Token', 'fluent-crm'),
|
|
'placeholder' => __('Drip API Token', 'fluent-crm'),
|
|
'data_type' => 'password',
|
|
'type' => 'input-text',
|
|
'inline_help' => $infoSvg . ' ' . __('You can find your API key at Drip Profile -> User Info -> API Token', 'fluent-crm')
|
|
],
|
|
'account_id' => [
|
|
'label' => __('Account ID', 'fluent-crm'),
|
|
'placeholder' => __('Drip Account ID', 'fluent-crm'),
|
|
'data_type' => 'text',
|
|
'type' => 'input-text',
|
|
'inline_help' => $infoSvg . ' ' . __('You can find Account ID Settings -> General Info -> Account ID', 'fluent-crm')
|
|
]
|
|
],
|
|
'refresh_on_list_change' => false,
|
|
'doc_url' => 'https://fluentcrm.com/docs/migrating-into-fluentcrm-from-drip/'
|
|
];
|
|
}
|
|
|
|
public function verifyCredentials($credential)
|
|
{
|
|
$api = $this->getApi($credential);
|
|
|
|
try {
|
|
$result = $api->make_request('accounts', [], 'GET');
|
|
if (is_wp_error($result)) {
|
|
return $result;
|
|
}
|
|
} catch (\Exception $exception) {
|
|
return new \WP_Error('api_error', $exception->getMessage());
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public function getListTagMappings($postedData)
|
|
{
|
|
$api = $this->getApi($postedData['credential']);
|
|
|
|
$tags = $api->sendAccountItems('tags');
|
|
|
|
$data = [];
|
|
|
|
if (is_wp_error($tags)) {
|
|
return $tags;
|
|
}
|
|
|
|
$formattedTags = [];
|
|
|
|
foreach ($tags['tags'] as $tag) {
|
|
$formattedTags[] = [
|
|
'remote_name' => (string)$tag,
|
|
'remote_id' => (string)$tag,
|
|
'will_create' => 'no',
|
|
'fluentcrm_id' => ''
|
|
];
|
|
}
|
|
$data['tags'] = $formattedTags;
|
|
|
|
$mergeFields = $api->sendAccountItems('custom_field_identifiers');
|
|
|
|
$contactFields = $mergeFields['custom_field_identifiers'];
|
|
$formattedContactFields = [];
|
|
|
|
$defaultFields = [
|
|
'First_Name',
|
|
'Last_Name',
|
|
'address1',
|
|
'address2',
|
|
'city',
|
|
'phone',
|
|
'state',
|
|
'zip',
|
|
'country'
|
|
];
|
|
|
|
$contactFields = array_values(array_diff($contactFields, $defaultFields));
|
|
|
|
foreach ($contactFields as $field) {
|
|
$item = [
|
|
'type' => 'any',
|
|
'remote_label' => $field,
|
|
'remote_tag' => $field,
|
|
'fluentcrm_field' => '',
|
|
'remote_type' => '',
|
|
'will_skip' => 'no'
|
|
];
|
|
|
|
$formattedContactFields[] = $item;
|
|
}
|
|
|
|
$data['contact_fields'] = $formattedContactFields;
|
|
$data['contact_fillables'] = $this->getFillables();
|
|
|
|
$data['all_ready'] = true;
|
|
|
|
|
|
return $data;
|
|
}
|
|
|
|
public function getSummary($postedData)
|
|
{
|
|
$api = $this->getApi($postedData['credential']);
|
|
|
|
$status = 'all';
|
|
|
|
$settings = Arr::get($postedData, 'map_settings', []);
|
|
|
|
if (Arr::get($settings, 'import_active_only') == 'yes') {
|
|
$status = 'active';
|
|
}
|
|
|
|
$members = $api->sendAccountItems('subscribers', [
|
|
'status' => $status,
|
|
'page' => 1,
|
|
'per_page' => 10
|
|
]);
|
|
|
|
if (is_wp_error($members)) {
|
|
return $members;
|
|
}
|
|
|
|
$meta = $members['meta'];
|
|
|
|
$message = __('Based on your selections ', 'fluent-crm') . $meta['total_count'] . __(' contacts will be imported', 'fluent-crm');
|
|
|
|
return [
|
|
'subscribed_count' => $meta['total_count'],
|
|
'unsubscribed_count' => 0,
|
|
'all_count' => $meta['total_count'],
|
|
'message' => $message
|
|
];
|
|
|
|
}
|
|
|
|
public function runImport($postedData)
|
|
{
|
|
if (!defined('FLUENTCRM_DISABLE_TAG_LIST_EVENTS')) {
|
|
define('FLUENTCRM_DISABLE_TAG_LIST_EVENTS', true);
|
|
}
|
|
|
|
$api = $this->getApi($postedData['credential']);
|
|
|
|
$processPerPage = 10;
|
|
|
|
$page = Arr::get($postedData, 'completed', 0);
|
|
|
|
if (!$page) {
|
|
$page = 1;
|
|
}
|
|
|
|
$params = [
|
|
'page' => $page,
|
|
'per_page' => $processPerPage,
|
|
'status' => 'all'
|
|
];
|
|
|
|
$tagMappings = Arr::get($postedData, 'tags', []);
|
|
|
|
$taggingArray = $this->mapTags($tagMappings);
|
|
|
|
$mapSettings = Arr::get($postedData, 'map_settings', []);
|
|
|
|
if ($mapSettings['import_active_only'] == 'yes') {
|
|
$params['status'] = 'subscribed';
|
|
}
|
|
|
|
$members = $api->sendAccountItems('subscribers', $params);
|
|
|
|
if (is_wp_error($members)) {
|
|
return $members;
|
|
}
|
|
|
|
$memberMeta = $members['meta'];
|
|
|
|
$subscribers = $members['subscribers'];
|
|
|
|
$fieldMaps = Arr::get($postedData, 'contact_fields', []);
|
|
|
|
foreach ($subscribers as $subscriber) {
|
|
|
|
$statusMaps = [
|
|
'active' => 'subscribed',
|
|
'unsubscribed' => 'unsubscribed'
|
|
];
|
|
$status = (isset($statusMaps[$subscriber['status']])) ? $statusMaps[$subscriber['status']] : 'pending';
|
|
if ($mapSettings['import_active_only'] == 'yes') {
|
|
$status = 'subscribed';
|
|
}
|
|
|
|
$data = [
|
|
'email' => $subscriber['email'],
|
|
'first_name' => $subscriber['first_name'],
|
|
'last_name' => $subscriber['last_name'],
|
|
'address_line_1' => $subscriber['address1'],
|
|
'address_line_2' => $subscriber['address2'],
|
|
'city' => $subscriber['city'],
|
|
'state' => $subscriber['state'],
|
|
'postal_code' => $subscriber['zip'],
|
|
'phone' => $subscriber['phone'],
|
|
'created_at' => gmdate('Y-m-d H:i:s', strtotime($subscriber['created_at'])),
|
|
'source' => 'Drip',
|
|
'ip' => $subscriber['ip_address'],
|
|
'country' => Arr::get($subscriber, 'country'),
|
|
'status' => $status
|
|
];
|
|
|
|
$mergeData = $this->getMergedData($subscriber['custom_fields'], $fieldMaps);
|
|
|
|
if ($mergeData) {
|
|
$data = array_merge($data, $mergeData);
|
|
}
|
|
|
|
if (!empty($mapSettings['local_list_id'])) {
|
|
$data['lists'] = [$mapSettings['local_list_id']];
|
|
}
|
|
|
|
if (!empty($subscriber['tags'])) {
|
|
$tagIds = [];
|
|
foreach ($subscriber['tags'] as $contactTag) {
|
|
if (!empty($taggingArray[$contactTag])) {
|
|
$tagIds[] = $taggingArray[$contactTag];
|
|
}
|
|
}
|
|
|
|
if (empty($tagIds) && !empty($mapSettings['local_tag_id'])) {
|
|
$tagIds = [$mapSettings['local_tag_id']];
|
|
}
|
|
|
|
$data['tags'] = $tagIds;
|
|
|
|
} else if (!empty($mapSettings['local_tag_id'])) {
|
|
$data['tags'] = [$mapSettings['local_tag_id']];
|
|
}
|
|
|
|
$contact = FluentCrmApi('contacts')->createOrUpdate($data);
|
|
|
|
if ($status == 'subscribed' && $contact && $contact->status != 'subscribed') {
|
|
$contact->updateStatus('subscribed');
|
|
}
|
|
}
|
|
|
|
$completed = $memberMeta['page'] + 1;
|
|
|
|
return [
|
|
'completed' => $completed,
|
|
'total' => $memberMeta['total_pages'],
|
|
'has_more' => $memberMeta['page'] < $memberMeta['total_pages']
|
|
];
|
|
}
|
|
|
|
private function getApi($credentials)
|
|
{
|
|
return new Drip($credentials['api_key'], $credentials['account_id']);
|
|
}
|
|
|
|
public function getSvgLogo()
|
|
{
|
|
return '<svg class="logo nav__logo" height="30" viewBox="0 0 84 30" width="84" xmlns="http://www.w3.org/2000/svg">
|
|
<title>Drip</title>
|
|
<g class="logo__logomark nav__logo-logomark" id="logomark">
|
|
<path d="M18 14.5L15.3 14.5C15.3 14.6 15.3 14.7 15.3 14.8 15.3 18.8 12 21.2 9 21.2 6 21.2 2.7 18.8 2.7 14.8 2.7 14.7 2.7 14.6 2.7 14.5L0 14.5C0 14.6 0 14.7 0 14.8 0 20.3 4.5 23.9 9 23.9 13.5 23.9 18 20.3 18 14.8 18 14.7 18 14.6 18 14.5Z" id="logo-mouth"></path>
|
|
<path d="M9 3.4L10.9 6 14.3 6C12.7 3.9 11 1.8 9 0 7 1.8 5.3 3.9 3.7 6L7.1 6 9 3.4Z" id="logo-hat"></path>
|
|
<g id="logo-eyes">
|
|
<ellipse cx="3.6" cy="10.3" id="logo-eye-left" rx="1.8" ry="1.8"></ellipse>
|
|
<ellipse cx="9" cy="10.3" id="logo-eye-center" rx="1.8" ry="1.8"></ellipse>
|
|
<ellipse cx="14.4" cy="10.3" id="logo-eye-right" rx="1.8" ry="1.8"></ellipse>
|
|
</g>
|
|
</g>
|
|
<g class="logo__wordmark nav__logo-wordmark" id="wordmark">
|
|
<path d="M40.8 23.5L37.6 23.5 37.6 20.9C35.9 23 33.6 24 30.9 24 28.2 24 25.8 23.1 24.2 21.5 22.6 19.9 21.6 17.6 21.6 14.9 21.6 12.1 22.5 9.9 24.2 8.3 25.9 6.7 28.2 5.8 30.9 5.8 33.8 5.8 35.8 6.7 37.6 8.7L37.6 0 40.8 0 40.8 23.5ZM31.2 8.6C27.3 8.6 24.9 10.9 24.9 14.9 24.9 18.8 27.3 21.1 31.2 21.1 35.2 21.1 37.6 18.8 37.6 14.9 37.6 11 35.2 8.6 31.2 8.6Z" id="wordmark-d"></path>
|
|
<polygon id="wordmark-r" points="55.2 8.9 47.5 8.9 47.5 24 44.4 24 44.4 6 55.2 6"></polygon>
|
|
<path d="M57.6 1.9C57.6 1.2 57.9 0.6 58.5 0.3 59.1-0.1 59.7-0.1 60.3 0.3 60.9 0.6 61.2 1.2 61.2 1.9 61.2 2.6 60.9 3.3 60.3 3.6 59.7 4 59.1 4 58.5 3.6 57.9 3.3 57.6 2.6 57.6 1.9ZM57.9 6.2L60.9 6.2 60.9 24 57.9 24 57.9 6.2Z" id="wordmark-i"></path>
|
|
<path d="M64.8 6.4L68 6.4 68 9C69.6 7.1 71.7 6 74.7 6 77.4 6 79.7 6.9 81.4 8.5 83.1 10.1 84 12.4 84 15.1 84 17.9 83.1 20.1 81.4 21.7 79.7 23.3 77.4 24.2 74.6 24.2 71.8 24.2 69.8 23.3 68 21.3L68 30 64.8 30 64.8 6.4ZM74.3 21.4C78.3 21.4 80.7 19.1 80.7 15.1 80.7 11.2 78.3 8.9 74.3 8.9 70.4 8.9 68 11.2 68 15.1 68 19 70.4 21.4 74.3 21.4Z" id="wordmark-p"></path>
|
|
</g>
|
|
</svg>';
|
|
}
|
|
}
|