357 lines
12 KiB
PHP
357 lines
12 KiB
PHP
<?php
|
|
|
|
namespace FluentCrm\App\Services\CrmMigrator;
|
|
|
|
use FluentCrm\App\Services\CrmMigrator\Api\ActiveCampaign;
|
|
use FluentCrm\Framework\Support\Arr;
|
|
|
|
class ActiveCampaignMigrator extends BaseMigrator
|
|
{
|
|
public function getInfo()
|
|
{
|
|
$infoSvg = $this->getInfoIcon();
|
|
|
|
$logo = $this->getSvgLogo();
|
|
|
|
return [
|
|
'title' => 'ActiveCampaign',
|
|
'description' => __('Transfer your ActiveCampaign tags and contacts to FluentCRM', 'fluent-crm'),
|
|
'logo' => fluentCrmMix('images/migrators/active_campaign.png'),
|
|
'logo_svg' => $logo,
|
|
'supports' => [
|
|
'tags' => false,
|
|
'lists' => false,
|
|
'empty_tags' => true,
|
|
'active_imports_only' => true,
|
|
'has_list_mapper' => true
|
|
],
|
|
'credentials' => [
|
|
'api_key' => '',
|
|
'api_url' => ''
|
|
],
|
|
'field_map_info' => __('Email and main contact fields will be mapped automatically', 'fluent-crm'),
|
|
'credential_fields' => [
|
|
'api_url' => [
|
|
'label' => __('API Access URL', 'fluent-crm'),
|
|
'placeholder' => __('API Access URL', 'fluent-crm'),
|
|
'data_type' => 'url',
|
|
'type' => 'input-text',
|
|
'inline_help' => $infoSvg . ' ' . __('You can find Account ID Settings -> Developer -> API Access', 'fluent-crm')
|
|
],
|
|
'api_key' => [
|
|
'label' => __('API Access Key', 'fluent-crm'),
|
|
'placeholder' => __('ActiveCampaign API Token', 'fluent-crm'),
|
|
'data_type' => 'password',
|
|
'type' => 'input-text',
|
|
'inline_help' => $infoSvg . ' ' . __('You can find your API key at ActiveCampaign Settings -> Developer -> API Access', 'fluent-crm')
|
|
]
|
|
],
|
|
'refresh_on_list_change' => false,
|
|
'doc_url' => 'https://fluentcrm.com/docs/migrating-into-fluentcrm-from-activecampaign/'
|
|
];
|
|
}
|
|
|
|
public function verifyCredentials($credential)
|
|
{
|
|
$api = $this->getApi($credential);
|
|
|
|
try {
|
|
$result = $api->auth_test();
|
|
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']);
|
|
|
|
$data = [];
|
|
|
|
$lists = $api->get_lists();
|
|
|
|
if (is_wp_error($lists)) {
|
|
return $lists;
|
|
}
|
|
|
|
$formattedLists = [];
|
|
foreach ($lists as $list) {
|
|
if (!is_array($list)) {
|
|
continue;
|
|
}
|
|
$formattedLists[] = [
|
|
'remote_id' => (string)$list['id'],
|
|
'local_id' => '',
|
|
'will_create' => 'no',
|
|
'remote_name' => (string)$list['name']
|
|
];
|
|
}
|
|
|
|
$data['mapped_lists'] = $formattedLists;
|
|
|
|
$tags = $api->getTags();
|
|
|
|
if (is_wp_error($tags)) {
|
|
return $tags;
|
|
}
|
|
|
|
$formattedTags = [];
|
|
|
|
foreach ($tags as $tag) {
|
|
$formattedTags[] = [
|
|
'remote_name' => $tag['name'],
|
|
'remote_id' => $tag['id'],
|
|
'will_create' => 'no',
|
|
'fluentcrm_id' => ''
|
|
];
|
|
}
|
|
$data['tags'] = $formattedTags;
|
|
|
|
$mergeFields = $api->get_custom_fields();
|
|
|
|
if (is_wp_error($mergeFields)) {
|
|
$mergeFields = [];
|
|
}
|
|
|
|
$formattedContactFields = [];
|
|
|
|
foreach ($mergeFields as $field) {
|
|
if (!is_array($field)) {
|
|
continue;
|
|
}
|
|
$item = [
|
|
'type' => 'any',
|
|
'remote_label' => $field['title'],
|
|
'remote_tag' => $field['id'],
|
|
'fluentcrm_field' => '',
|
|
'remote_type' => $field['type'],
|
|
'will_skip' => 'no'
|
|
];
|
|
|
|
$formattedContactFields[] = $item;
|
|
}
|
|
|
|
$data['contact_fields'] = $formattedContactFields;
|
|
$data['contact_fillables'] = $this->getFillables();
|
|
|
|
unset($data['contact_fillables']['first_name']);
|
|
unset($data['contact_fillables']['last_name']);
|
|
unset($data['contact_fillables']['full_name']);
|
|
unset($data['contact_fillables']['phone']);
|
|
|
|
$data['all_ready'] = true;
|
|
|
|
return $data;
|
|
}
|
|
|
|
public function getSummary($postedData)
|
|
{
|
|
$mappedLists = Arr::get($postedData, 'mapped_lists', []);
|
|
|
|
$listCounts = count($mappedLists);
|
|
|
|
$message = __('Based on your selections ', 'fluent-crm') . $listCounts . __(' lists and associate contacts will be imported', 'fluent-crm');
|
|
|
|
return [
|
|
'subscribed_count' => 1,
|
|
'unsubscribed_count' => 0,
|
|
'all_count' => 1,
|
|
'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']);
|
|
|
|
// Initialize or retrieve the current offset
|
|
$offset = Arr::get($postedData, 'completed', 0);
|
|
|
|
$tagMappings = Arr::get($postedData, 'tags', []);
|
|
|
|
$taggingArray = $this->mapTags($tagMappings);
|
|
|
|
$mapSettings = Arr::get($postedData, 'map_settings', []);
|
|
|
|
$listingArray = $this->getListingArray(Arr::get($postedData, 'mapped_lists', []));
|
|
|
|
$subscribedOnly = false;
|
|
if ($mapSettings['import_active_only'] == 'yes') {
|
|
$subscribedOnly = true;
|
|
}
|
|
|
|
// Prepare the API parameters
|
|
$params = [
|
|
'offset' => $offset,
|
|
'status' => $subscribedOnly ? '1' : '-1',
|
|
];
|
|
$subscribers = $api->getContacts($params);
|
|
|
|
if (is_wp_error($subscribers)) {
|
|
if ($offset > 0) {
|
|
return [
|
|
'completed' => $offset,
|
|
'total' => $offset,
|
|
'has_more' => false,
|
|
'hide_progress' => true
|
|
];
|
|
}
|
|
|
|
return $subscribers;
|
|
}
|
|
|
|
$fieldMaps = Arr::get($postedData, 'contact_fields', []);
|
|
$stepCompletedCount = 0;
|
|
foreach ($subscribers as $subscriber) {
|
|
|
|
if (!is_array($subscriber)) {
|
|
continue;
|
|
}
|
|
$stepCompletedCount++;
|
|
|
|
if ($subscribedOnly && $subscriber['status'] != 1) {
|
|
continue;
|
|
}
|
|
|
|
$status = 'subscribed';
|
|
if ($subscriber['status'] != 1) {
|
|
$status = 'pending';
|
|
}
|
|
|
|
$data = [
|
|
'email' => $subscriber['email'],
|
|
'first_name' => $subscriber['first_name'],
|
|
'last_name' => $subscriber['last_name'],
|
|
'phone' => $subscriber['phone'],
|
|
'created_at' => gmdate('Y-m-d H:i:s', strtotime($subscriber['cdate'])),
|
|
'source' => 'ActiveCampaign',
|
|
'ip' => $subscriber['ip'],
|
|
'status' => $status,
|
|
'lists' => []
|
|
];
|
|
|
|
|
|
if (!empty($subscriber['fields'])) {
|
|
$customFields = [];
|
|
foreach ($subscriber['fields'] as $field) {
|
|
$val = $field['val'];
|
|
/**
|
|
* ActiveCampaign api return checkbox & listbox field value as ||VALUE|| format
|
|
* For example: ||a||, ||yes||
|
|
* Here we remove the || from the value
|
|
*/
|
|
if (in_array($field['type'], ['checkbox', 'listbox'])) {
|
|
$val = array_values( array_filter( explode( '||', $val ) ) );
|
|
}
|
|
$customFields[$field['perstag']] = $val;
|
|
}
|
|
if ($customFields) {
|
|
$mergeData = $this->getMergedData($customFields, $fieldMaps);
|
|
|
|
// Create values for multiselect and checkbox fields.
|
|
$this->maybeCreateFieldOptions( $mergeData );
|
|
|
|
if ($mergeData) {
|
|
$data = array_merge($data, $mergeData);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Map Lists here
|
|
if ($listingArray && $subscriber['lists']) {
|
|
foreach ($subscriber['lists'] as $subList) {
|
|
$listId = $subList['listid'];
|
|
if (isset($listingArray[$listId])) {
|
|
$data['lists'][] = $listingArray[$listId];
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!empty($mapSettings['local_list_id'])) {
|
|
$data['lists'][] = $mapSettings['local_list_id'];
|
|
}
|
|
|
|
if (!empty($subscriber['tags']) && $taggingArray) {
|
|
$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 ($subscribedOnly && $contact && $contact->status != 'subscribed') {
|
|
$contact->updateStatus('subscribed');
|
|
}
|
|
}
|
|
|
|
return [
|
|
'completed' => $offset + 100,
|
|
'total' => $offset + 100,
|
|
'has_more' => !empty($subscribers),
|
|
'hide_progress' => true,
|
|
'message' => ($offset + 100) . __(' contacts have been imported so far.', 'fluent-crm')
|
|
];
|
|
}
|
|
|
|
private function getApi($credentials)
|
|
{
|
|
return new ActiveCampaign($credentials['api_url'], $credentials['api_key']);
|
|
}
|
|
|
|
private function getListingArray($listMappings)
|
|
{
|
|
$formattedMaps = [];
|
|
|
|
foreach ($listMappings as $listMapping) {
|
|
$remoteId = $listMapping['remote_id'];
|
|
|
|
if ($listMapping['will_create'] == 'yes') {
|
|
$remoteName = sanitize_text_field($listMapping['remote_name']);
|
|
if (!$remoteName) {
|
|
continue;
|
|
}
|
|
$listMapping['fluentcrm_id'] = $this->getListId($remoteName);
|
|
}
|
|
|
|
if (empty($listMapping['fluentcrm_id'])) {
|
|
continue;
|
|
}
|
|
|
|
$formattedMaps[$remoteId] = (int)$listMapping['fluentcrm_id'];
|
|
}
|
|
|
|
return $formattedMaps;
|
|
}
|
|
|
|
public function getSvgLogo()
|
|
{
|
|
return '<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none">
|
|
<path d="M16 30C23.732 30 30 23.732 30 16C30 8.26801 23.732 2 16 2C8.26801 2 2 8.26801 2 16C2 23.732 8.26801 30 16 30Z" fill="#004CFF"/>
|
|
<path d="M20.7497 15.9683L12.5577 21.4086C12.1782 21.6616 11.9883 22.0727 11.9883 22.4839V23.8439L21.92 17.3283C22.3628 17.0121 22.6475 16.5059 22.6475 15.9683C22.6475 15.4306 22.3945 14.9244 21.92 14.6081L11.9883 8.15576V9.42089C11.9883 9.8638 12.2097 10.2749 12.5577 10.4963L20.7497 15.9683Z" fill="white"/>
|
|
<path d="M15.8155 16.4112C16.2583 16.6958 16.8277 16.6958 17.2705 16.4112L17.9663 15.9367L12.779 12.4259C12.4628 12.2044 11.9883 12.4259 11.9883 12.837V13.8807L14.6768 15.6837L15.8155 16.4112Z" fill="white"/>
|
|
</svg>';
|
|
}
|
|
}
|