Files
gustavoo-me/wp-content/plugins/fluent-crm/app/Services/CrmMigrator/ActiveCampaignMigrator.php
T
2026-07-23 22:56:30 -03:00

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>';
}
}