File: /var/www/quadcode-site/app/Console/Commands/AbstractSyncBitrixAndActiveCampaign.php
<?php
namespace App\Console\Commands;
use App\Helpers\ActiveCampaignHelper;
use App\Helpers\BitrixHelper;
use Illuminate\Console\Command;
use Throwable;
abstract class AbstractSyncBitrixAndActiveCampaign extends Command
{
protected ActiveCampaignHelper $activeCampaignHelper;
protected BitrixHelper $bitrixHelper;
protected function convertBitrixEntityToActiveCampaignContact(array $entity): ?array
{
$contact = [];
if (!empty($entity['NAME'])) {
$contact['first_name'] = $entity['NAME'];
}
foreach ($entity['EMAIL'] ?? [] as $email) {
$contact['email'] = strtolower($email['VALUE']);
}
if (empty($contact['email'])) {
return null;
}
$contact['phone'] = null;
foreach ($entity['PHONE'] ?? [] as $phone) {
$contact['phone'] = $phone['VALUE'];
}
return $contact;
}
protected function syncDealsToActiveCampaign(int $listId, string $stageId): void
{
$filter = [
'STAGE_ID' => $stageId,
'>CONTACT_ID' => 0,
];
$select = ['CONTACT_ID'];
$deals = $this->bitrixHelper->dealList($filter, select: $select);
$this->line('Deals found: ' . count($deals));
$contactsIds = [];
foreach ($deals as $deal) {
$contactsIds[] = $deal['CONTACT_ID'];
}
$contactsIds = array_unique($contactsIds);
$this->info('Get contacts');
$bitrixContactsFull = [];
$innerLimit = 50;
for ($innerOffset = 0; $innerOffset < count($contactsIds); $innerOffset += $innerLimit) {
$batchContactsIds = array_slice($contactsIds, $innerOffset, $innerLimit);
$filter = ['ID' => $batchContactsIds];
$select = ['NAME', 'EMAIL', 'PHONE'];
$bitrixContactsFull = array_merge($bitrixContactsFull, $this->bitrixHelper->contactsList($filter, $select));
}
$this->line('Contacts found: ' . count($bitrixContactsFull));
$contacts = [];
$bitrixContacts = $bitrixContactsFull;
$pb = $this->output->createProgressBar(count($bitrixContacts));
foreach ($bitrixContacts as $bitrixContact) {
$pb->advance();
$contact = $this->convertBitrixEntityToActiveCampaignContact($bitrixContact);
if (empty($contact)) {
continue;
}
$contacts[$contact['email']] = $contact;
}
$pb->finish();
$this->line('');
$uniqueEmails = array_unique(array_column($contacts, 'email'));
$this->line('Contacts found: ' . count($contactsIds));
$this->line('Unique contacts found: ' . count($uniqueEmails));
$this->syncContactsToActiveCampaign($listId, $contacts);
$this->info('Done');
}
protected function syncContactsToActiveCampaign(string $listId, array $contacts): void
{
$contactsFromList = [];
$threshold = 10000;
$limit = 100;
$offset = 0;
$contactsData = $this->activeCampaignHelper->searchContact(['listid' => $listId, 'status' => ActiveCampaignHelper::STATUS_ACTIVE, 'limit' => $limit]);
while (!empty($contactsData['contacts']) || $threshold < 0) {
foreach ($contactsData['contacts'] as $contactFromList) {
$email = strtolower($contactFromList['email']);
$contactFromList['email'] = $email;
$contactsFromList[$email] = $contactFromList;
}
$offset += $limit;
$contactsData = $this->activeCampaignHelper->searchContact(['listid' => $listId, 'status' => ActiveCampaignHelper::STATUS_ACTIVE, 'limit' => $limit, 'offset' => $offset]);
$threshold--;
}
if (!empty($contacts)) {
$newEmails = [];
foreach ($contacts as $contact) {
$email = $contact['email'];
if (!empty($contactsFromList[$email])) {
unset($contactsFromList[$email]);
continue;
}
$newEmails[] = $email;
}
if (!empty($newEmails)) {
$this->info('Subscribe ' . count($newEmails) . ':');
$pb = $this->output->createProgressBar(count($contacts));
foreach ($contacts as $contact) {
$pb->advance();
$email = $contact['email'];
if (!in_array($email, $newEmails)) {
continue;
}
try {
$response = $this->activeCampaignHelper->searchContact(compact('email'));
if (!$response->successful()) {
$this->warn('Response error: ' . $response->status());
continue;
}
$responseData = $response->json();
$externalContact = $responseData['contacts'][0] ?? null;
if (empty($externalContact)) {
$this->line('Create person ' . $contact['email']);
$response = $this->activeCampaignHelper->createContact($contact);
if (!$response->successful()) {
$this->warn('Response error: ' . $response->status());
continue;
}
$responseData = $response->json();
$externalContact = $responseData['contact'] ?? null;
}
if (empty($contact)) {
$this->warn('Contact not found or create');
continue;
}
$this->activeCampaignHelper->subscribeContact($externalContact['id'], $listId);
if (!$response->successful()) {
$this->warn('Response error: ' . $response->status());
continue;
}
} catch (Throwable $exception) {
$this->warn($exception->getMessage());
}
}
$pb->finish();
$this->line('');
}
}
if (!empty($contactsFromList)) {
$this->info('Unsubscribe ' . count($contactsFromList) . ':');
$pb = $this->output->createProgressBar(count($contactsFromList));
foreach ($contactsFromList as $contactFromList) {
$pb->advance();
$this->activeCampaignHelper->unsubscribeContact($contactFromList['id'], $listId);
}
$pb->finish();
$this->line('');
}
}
}