HEX
Server: nginx/1.18.0
System: Linux test-ipsremont 5.4.0-214-generic #234-Ubuntu SMP Fri Mar 14 23:50:27 UTC 2025 x86_64
User: ips (1000)
PHP: 8.0.30
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
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('');
        }
    }

}