Initial commit: CloudOps infrastructure platform
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\CampaignBundle\Membership\Action;
|
||||
|
||||
use Mautic\CampaignBundle\Entity\Campaign;
|
||||
use Mautic\CampaignBundle\Entity\Lead as CampaignMember;
|
||||
use Mautic\CampaignBundle\Entity\LeadEventLogRepository;
|
||||
use Mautic\CampaignBundle\Entity\LeadRepository;
|
||||
use Mautic\CampaignBundle\Membership\Exception\ContactCannotBeAddedToCampaignException;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
|
||||
class Adder
|
||||
{
|
||||
public const NAME = 'added';
|
||||
|
||||
public function __construct(
|
||||
private LeadRepository $leadRepository,
|
||||
private LeadEventLogRepository $leadEventLogRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
public function createNewMembership(Lead $contact, Campaign $campaign, $isManualAction): CampaignMember
|
||||
{
|
||||
// BC support for prior to 2.14.
|
||||
// If the contact was in the campaign to start with then removed, their logs remained but the original membership was removed
|
||||
// Start the new rotation at 2
|
||||
$rotation = 1;
|
||||
if ($this->leadEventLogRepository->hasBeenInCampaignRotation($contact->getId(), $campaign->getId(), 1)) {
|
||||
$rotation = 2;
|
||||
}
|
||||
|
||||
$campaignMember = new CampaignMember();
|
||||
$campaignMember->setLead($contact);
|
||||
$campaignMember->setCampaign($campaign);
|
||||
$campaignMember->setManuallyAdded($isManualAction);
|
||||
$campaignMember->setDateAdded(new \DateTime());
|
||||
$campaignMember->setRotation($rotation);
|
||||
$this->saveCampaignMember($campaignMember);
|
||||
|
||||
return $campaignMember;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $isManualAction
|
||||
*
|
||||
* @throws ContactCannotBeAddedToCampaignException
|
||||
*/
|
||||
public function updateExistingMembership(CampaignMember $campaignMember, $isManualAction): void
|
||||
{
|
||||
$wasRemoved = $campaignMember->wasManuallyRemoved();
|
||||
if (!($wasRemoved && $isManualAction) && !$campaignMember->getCampaign()->allowRestart()) {
|
||||
// A contact cannot restart this campaign
|
||||
|
||||
throw new ContactCannotBeAddedToCampaignException('Contacts cannot restart the campaign');
|
||||
}
|
||||
|
||||
if ($wasRemoved && !$isManualAction && null === $campaignMember->getDateLastExited()) {
|
||||
// Prevent contacts from being added back if they were manually removed but automatically added back
|
||||
|
||||
throw new ContactCannotBeAddedToCampaignException('Contact was manually removed');
|
||||
}
|
||||
|
||||
if ($wasRemoved && $isManualAction) {
|
||||
// If they were manually removed and manually added back, mark it as so
|
||||
$campaignMember->setManuallyAdded($isManualAction);
|
||||
}
|
||||
|
||||
// Contact exited but has been added back to the campaign
|
||||
$campaignMember->setManuallyRemoved(false);
|
||||
$campaignMember->setDateLastExited(null);
|
||||
$campaignMember->startNewRotation();
|
||||
|
||||
$this->saveCampaignMember($campaignMember);
|
||||
}
|
||||
|
||||
private function saveCampaignMember($campaignMember): void
|
||||
{
|
||||
$this->leadRepository->saveEntity($campaignMember);
|
||||
$this->leadRepository->detachEntity($campaignMember);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\CampaignBundle\Membership\Action;
|
||||
|
||||
use Mautic\CampaignBundle\Entity\Lead as CampaignMember;
|
||||
use Mautic\CampaignBundle\Entity\LeadEventLogRepository;
|
||||
use Mautic\CampaignBundle\Entity\LeadRepository;
|
||||
use Mautic\CampaignBundle\Membership\Exception\ContactAlreadyRemovedFromCampaignException;
|
||||
use Mautic\CoreBundle\Twig\Helper\DateHelper;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class Remover
|
||||
{
|
||||
public const NAME = 'removed';
|
||||
|
||||
private string $unscheduledMessage;
|
||||
|
||||
public function __construct(
|
||||
private LeadRepository $leadRepository,
|
||||
private LeadEventLogRepository $leadEventLogRepository,
|
||||
TranslatorInterface $translator,
|
||||
DateHelper $dateHelper,
|
||||
) {
|
||||
$dateRemoved = $dateHelper->toFull(new \DateTime());
|
||||
$this->unscheduledMessage = $translator->trans('mautic.campaign.member.removed', ['%date%' => $dateRemoved]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $isExit
|
||||
*
|
||||
* @throws ContactAlreadyRemovedFromCampaignException
|
||||
*/
|
||||
public function updateExistingMembership(CampaignMember $campaignMember, $isExit): void
|
||||
{
|
||||
if ($isExit) {
|
||||
// Contact was removed by the change campaign action or a segment
|
||||
$campaignMember->setDateLastExited(new \DateTime());
|
||||
} else {
|
||||
$campaignMember->setDateLastExited(null);
|
||||
}
|
||||
|
||||
if ($campaignMember->wasManuallyRemoved()) {
|
||||
$this->saveCampaignMember($campaignMember);
|
||||
|
||||
// Contact was already removed from this campaign
|
||||
throw new ContactAlreadyRemovedFromCampaignException();
|
||||
}
|
||||
|
||||
// Unschedule any scheduled events
|
||||
$this->leadEventLogRepository->unscheduleEvents($campaignMember, $this->unscheduledMessage);
|
||||
|
||||
// Remove this contact from the campaign
|
||||
$campaignMember->setManuallyRemoved(true);
|
||||
$campaignMember->setManuallyAdded(false);
|
||||
|
||||
$this->saveCampaignMember($campaignMember);
|
||||
}
|
||||
|
||||
private function saveCampaignMember($campaignMember): void
|
||||
{
|
||||
$this->leadRepository->saveEntity($campaignMember);
|
||||
$this->leadRepository->detachEntity($campaignMember);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\CampaignBundle\Membership;
|
||||
|
||||
use Mautic\CampaignBundle\CampaignEvents;
|
||||
use Mautic\CampaignBundle\Entity\Campaign;
|
||||
use Mautic\CampaignBundle\Event\CampaignLeadChangeEvent;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
class EventDispatcher
|
||||
{
|
||||
public function __construct(
|
||||
private EventDispatcherInterface $dispatcher,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $action
|
||||
*/
|
||||
public function dispatchMembershipChange(Lead $contact, Campaign $campaign, $action): void
|
||||
{
|
||||
$this->dispatcher->dispatch(
|
||||
new CampaignLeadChangeEvent($campaign, $contact, $action),
|
||||
CampaignEvents::CAMPAIGN_ON_LEADCHANGE
|
||||
);
|
||||
}
|
||||
|
||||
public function dispatchBatchMembershipChange(array $contacts, Campaign $campaign, $action): void
|
||||
{
|
||||
$this->dispatcher->dispatch(
|
||||
new CampaignLeadChangeEvent($campaign, $contacts, $action),
|
||||
CampaignEvents::LEAD_CAMPAIGN_BATCH_CHANGE
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\CampaignBundle\Membership\Exception;
|
||||
|
||||
use Mautic\CoreBundle\Exception\FlattenableException;
|
||||
|
||||
class ContactAlreadyRemovedFromCampaignException extends FlattenableException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\CampaignBundle\Membership\Exception;
|
||||
|
||||
use Mautic\CoreBundle\Exception\FlattenableException;
|
||||
|
||||
class ContactCannotBeAddedToCampaignException extends FlattenableException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\CampaignBundle\Membership\Exception;
|
||||
|
||||
class RunLimitReachedException extends \Exception
|
||||
{
|
||||
private int $contactsProcessed;
|
||||
|
||||
public function __construct($contactsProcessed)
|
||||
{
|
||||
$this->contactsProcessed = (int) $contactsProcessed;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function getContactsProcessed(): int
|
||||
{
|
||||
return $this->contactsProcessed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\CampaignBundle\Membership;
|
||||
|
||||
use Mautic\CampaignBundle\Entity\Campaign;
|
||||
use Mautic\CampaignBundle\Entity\LeadRepository as CampaignLeadRepository;
|
||||
use Mautic\CampaignBundle\Executioner\ContactFinder\Limiter\ContactLimiter;
|
||||
use Mautic\CampaignBundle\Membership\Exception\RunLimitReachedException;
|
||||
use Mautic\CoreBundle\Helper\ProgressBarHelper;
|
||||
use Mautic\LeadBundle\Entity\LeadRepository;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class MembershipBuilder
|
||||
{
|
||||
private ?Campaign $campaign = null;
|
||||
|
||||
private ?ContactLimiter $contactLimiter = null;
|
||||
|
||||
private ?int $runLimit = null;
|
||||
|
||||
private ?OutputInterface $output = null;
|
||||
|
||||
private ?\Symfony\Component\Console\Helper\ProgressBar $progressBar = null;
|
||||
|
||||
public function __construct(
|
||||
private MembershipManager $manager,
|
||||
private CampaignLeadRepository $campaignLeadRepository,
|
||||
private LeadRepository $leadRepository,
|
||||
private TranslatorInterface $translator,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $runLimit
|
||||
*/
|
||||
public function build(Campaign $campaign, ContactLimiter $contactLimiter, $runLimit, ?OutputInterface $output = null): int
|
||||
{
|
||||
defined('MAUTIC_REBUILDING_CAMPAIGNS') or define('MAUTIC_REBUILDING_CAMPAIGNS', 1);
|
||||
|
||||
$this->campaign = $campaign;
|
||||
$this->contactLimiter = $contactLimiter;
|
||||
$this->runLimit = (int) $runLimit;
|
||||
$this->output = $output;
|
||||
|
||||
$contactsProcessed = 0;
|
||||
|
||||
try {
|
||||
$contactsProcessed += $this->addNewlyQualifiedMembers($contactsProcessed);
|
||||
} catch (RunLimitReachedException $exception) {
|
||||
return $exception->getContactsProcessed();
|
||||
}
|
||||
|
||||
try {
|
||||
$contactsProcessed += $this->removeUnqualifiedMembers($contactsProcessed);
|
||||
} catch (RunLimitReachedException $exception) {
|
||||
return $exception->getContactsProcessed();
|
||||
}
|
||||
|
||||
return $contactsProcessed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add contacts to a campaign.
|
||||
*
|
||||
* @throws RunLimitReachedException
|
||||
*/
|
||||
private function addNewlyQualifiedMembers(int $totalContactsProcessed): int
|
||||
{
|
||||
$contactsProcessed = 0;
|
||||
|
||||
if ($this->output) {
|
||||
$countResult = $this->campaignLeadRepository->getCountsForCampaignContactsBySegment(
|
||||
$this->campaign->getId(),
|
||||
$this->contactLimiter
|
||||
);
|
||||
|
||||
$this->output->writeln(
|
||||
$this->translator->trans(
|
||||
'mautic.campaign.rebuild.to_be_added',
|
||||
['%leads%' => $countResult->getCount(), '%batch%' => $this->contactLimiter->getBatchLimit()]
|
||||
)
|
||||
);
|
||||
|
||||
if (0 === $countResult->getCount()) {
|
||||
// No use continuing
|
||||
return 0;
|
||||
}
|
||||
|
||||
$this->startProgressBar($countResult->getCount());
|
||||
}
|
||||
|
||||
$contacts = $this->campaignLeadRepository->getCampaignContactsBySegments(
|
||||
$this->campaign->getId(),
|
||||
$this->contactLimiter,
|
||||
$this->campaign->allowRestart()
|
||||
);
|
||||
|
||||
while (count($contacts)) {
|
||||
// get an array of contact entities based on the contact id
|
||||
$contactCollection = $this->leadRepository->getContactCollection($contacts);
|
||||
if ($contactCollection->count() <= 0) {
|
||||
// Prevent endless loop just in case
|
||||
break;
|
||||
}
|
||||
|
||||
// increase the total nr of contacts processed by this batch
|
||||
$contactsProcessed += $contactCollection->count();
|
||||
|
||||
// Add the contacts to this segment
|
||||
$this->manager->addContacts($contactCollection, $this->campaign, false);
|
||||
|
||||
// Clear Lead entities from RAM
|
||||
$this->leadRepository->detachEntities($contactCollection->toArray());
|
||||
|
||||
// Have we hit the run limit?
|
||||
if ($this->runLimit && $contactsProcessed >= $this->runLimit) {
|
||||
$this->finishProgressBar();
|
||||
throw new RunLimitReachedException($contactsProcessed + $totalContactsProcessed);
|
||||
}
|
||||
|
||||
// Get next batch
|
||||
$contacts = $this->campaignLeadRepository->getCampaignContactsBySegments(
|
||||
$this->campaign->getId(),
|
||||
$this->contactLimiter,
|
||||
$this->campaign->allowRestart()
|
||||
);
|
||||
}
|
||||
|
||||
$this->finishProgressBar();
|
||||
|
||||
return $contactsProcessed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RunLimitReachedException
|
||||
*/
|
||||
private function removeUnqualifiedMembers(int $totalContactsProcessed): int
|
||||
{
|
||||
$contactsProcessed = 0;
|
||||
|
||||
if ($this->output) {
|
||||
$countResult = $this->campaignLeadRepository->getCountsForOrphanedContactsBySegments($this->campaign->getId(), $this->contactLimiter);
|
||||
|
||||
$this->output->writeln(
|
||||
$this->translator->trans(
|
||||
'mautic.lead.list.rebuild.to_be_removed',
|
||||
['%leads%' => $countResult->getCount(), '%batch%' => $this->contactLimiter->getBatchLimit()]
|
||||
)
|
||||
);
|
||||
|
||||
if (0 === $countResult->getCount()) {
|
||||
// No use continuing
|
||||
return 0;
|
||||
}
|
||||
|
||||
$this->startProgressBar($countResult->getCount());
|
||||
}
|
||||
|
||||
$contacts = $this->campaignLeadRepository->getOrphanedContacts($this->campaign->getId(), $this->contactLimiter);
|
||||
while (count($contacts)) {
|
||||
$contactCollection = $this->leadRepository->getContactCollection($contacts);
|
||||
if (!$contactCollection->count()) {
|
||||
// Prevent endless loop just in case
|
||||
break;
|
||||
}
|
||||
|
||||
$contactsProcessed += $contactCollection->count();
|
||||
|
||||
// Add the contacts to this segment
|
||||
$this->manager->removeContacts($contactCollection, $this->campaign, true);
|
||||
|
||||
// Clear Lead entities from RAM
|
||||
$this->leadRepository->detachEntities($contactCollection->toArray());
|
||||
|
||||
// Have we hit the run limit?
|
||||
if ($this->runLimit && $contactsProcessed >= $this->runLimit) {
|
||||
$this->finishProgressBar();
|
||||
throw new RunLimitReachedException($contactsProcessed + $totalContactsProcessed);
|
||||
}
|
||||
|
||||
// Get next batch
|
||||
$contacts = $this->campaignLeadRepository->getOrphanedContacts($this->campaign->getId(), $this->contactLimiter);
|
||||
}
|
||||
|
||||
$this->finishProgressBar();
|
||||
|
||||
return $contactsProcessed;
|
||||
}
|
||||
|
||||
private function startProgressBar(int $total): void
|
||||
{
|
||||
if (!$this->output) {
|
||||
$this->progressBar = null;
|
||||
$this->manager->setProgressBar($this->progressBar);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->progressBar = ProgressBarHelper::init($this->output, $total);
|
||||
$this->progressBar->start();
|
||||
|
||||
// Notify the manager to increment progress as contacts are added
|
||||
$this->manager->setProgressBar($this->progressBar);
|
||||
}
|
||||
|
||||
private function finishProgressBar(): void
|
||||
{
|
||||
if ($this->progressBar) {
|
||||
$this->progressBar->finish();
|
||||
$this->output->writeln('');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\CampaignBundle\Membership;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Mautic\CampaignBundle\Entity\Campaign;
|
||||
use Mautic\CampaignBundle\Entity\Lead as CampaignMember;
|
||||
use Mautic\CampaignBundle\Entity\LeadRepository;
|
||||
use Mautic\CampaignBundle\Membership\Action\Adder;
|
||||
use Mautic\CampaignBundle\Membership\Action\Remover;
|
||||
use Mautic\CampaignBundle\Membership\Exception\ContactAlreadyRemovedFromCampaignException;
|
||||
use Mautic\CampaignBundle\Membership\Exception\ContactCannotBeAddedToCampaignException;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Console\Helper\ProgressBar;
|
||||
|
||||
class MembershipManager
|
||||
{
|
||||
public const ACTION_ADDED = 'added';
|
||||
|
||||
public const ACTION_REMOVED = 'removed';
|
||||
|
||||
private ?ProgressBar $progressBar = null;
|
||||
|
||||
public function __construct(
|
||||
private Adder $adder,
|
||||
private Remover $remover,
|
||||
private EventDispatcher $eventDispatcher,
|
||||
private LeadRepository $leadRepository,
|
||||
private LoggerInterface $logger,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $isManualAction
|
||||
*/
|
||||
public function addContact(Lead $contact, Campaign $campaign, $isManualAction = true): void
|
||||
{
|
||||
// Validate that contact is not already in the Campaign
|
||||
/** @var CampaignMember $campaignMember */
|
||||
$campaignMember = $this->leadRepository->findOneBy(
|
||||
[
|
||||
'lead' => $contact,
|
||||
'campaign' => $campaign,
|
||||
]
|
||||
);
|
||||
|
||||
if ($campaignMember) {
|
||||
try {
|
||||
$this->adder->updateExistingMembership($campaignMember, $isManualAction);
|
||||
$this->logger->debug(
|
||||
"CAMPAIGN: Membership for contact ID {$contact->getId()} in campaign ID {$campaign->getId()} was updated to be included."
|
||||
);
|
||||
|
||||
// Notify listeners
|
||||
$this->eventDispatcher->dispatchMembershipChange($campaignMember->getLead(), $campaignMember->getCampaign(), Adder::NAME);
|
||||
} catch (ContactCannotBeAddedToCampaignException $exception) {
|
||||
// Do nothing
|
||||
$this->logger->debug(
|
||||
"CAMPAIGN: Contact ID {$contact->getId()} could not be added to campaign ID {$campaign->getId()}.",
|
||||
$exception->toArray()
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Contact is not already in the campaign so create a new entry
|
||||
$this->adder->createNewMembership($contact, $campaign, $isManualAction);
|
||||
} catch (ContactCannotBeAddedToCampaignException $exception) {
|
||||
// Do nothing
|
||||
$this->logger->debug(
|
||||
"CAMPAIGN: Contact ID {$contact->getId()} could not be added to campaign ID {$campaign->getId()}.",
|
||||
$exception->toArray()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->logger->debug("CAMPAIGN: Contact ID {$contact->getId()} was added to campaign ID {$campaign->getId()} as a new member.");
|
||||
|
||||
// Notify listeners the contact has been added
|
||||
$this->eventDispatcher->dispatchMembershipChange($contact, $campaign, Adder::NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ArrayCollection<int, Lead> $contacts
|
||||
* @param bool $isManualAction
|
||||
*/
|
||||
public function addContacts(ArrayCollection $contacts, Campaign $campaign, $isManualAction = true): void
|
||||
{
|
||||
// Get a list of existing campaign members
|
||||
$campaignMembers = $this->leadRepository->getCampaignMembers($contacts->getKeys(), $campaign);
|
||||
|
||||
foreach ($contacts as $contact) {
|
||||
$this->advanceProgressBar();
|
||||
|
||||
$this->logger->debug(
|
||||
'CAMPAIGN: Contacts: '.count($contacts),
|
||||
array_map(fn ($item) => $item->getId(), $contacts->toArray())
|
||||
);
|
||||
|
||||
// is the contact an existing campaign member? update and continue
|
||||
if (isset($campaignMembers[$contact->getId()])) {
|
||||
try {
|
||||
$this->adder->updateExistingMembership($campaignMembers[$contact->getId()], $isManualAction);
|
||||
$this->logger->debug(
|
||||
"CAMPAIGN: Membership for contact ID {$contact->getId()} in campaign ID {$campaign->getId()} was updated to be included."
|
||||
);
|
||||
} catch (ContactCannotBeAddedToCampaignException $exception) {
|
||||
$contacts->remove($contact->getId());
|
||||
|
||||
$this->logger->debug(
|
||||
"CAMPAIGN: Contact ID {$contact->getId()} could not be added to campaign ID {$campaign->getId()}.",
|
||||
$exception->toArray()
|
||||
);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Existing membership does not exist so create a new one
|
||||
$this->adder->createNewMembership($contact, $campaign, $isManualAction);
|
||||
|
||||
$this->logger->debug("CAMPAIGN: Contact ID {$contact->getId()} was added to campaign ID {$campaign->getId()} as a new member.");
|
||||
}
|
||||
|
||||
if ($contacts->count()) {
|
||||
// Notifiy listeners
|
||||
$this->eventDispatcher->dispatchBatchMembershipChange($contacts->toArray(), $campaign, Adder::NAME);
|
||||
}
|
||||
|
||||
// Clear entities from RAM
|
||||
$this->leadRepository->detachEntities($campaignMembers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $isExit
|
||||
*/
|
||||
public function removeContact(Lead $contact, Campaign $campaign, $isExit = false): void
|
||||
{
|
||||
// Validate that contact is not already in the Campaign
|
||||
/** @var CampaignMember $campaignMember */
|
||||
$campaignMember = $this->leadRepository->findOneBy(
|
||||
[
|
||||
'lead' => $contact,
|
||||
'campaign' => $campaign,
|
||||
]
|
||||
);
|
||||
|
||||
if (!$campaignMember) {
|
||||
// Contact is not in this campaign
|
||||
$this->logger->debug("CAMPAIGN: Contact ID {$contact->getId()} is not in campaign ID {$campaign->getId()}.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->remover->updateExistingMembership($campaignMember, $isExit);
|
||||
$this->logger->debug("CAMPAIGN: Contact ID {$contact->getId()} was removed from campaign ID {$campaign->getId()}.");
|
||||
|
||||
// Notify listeners
|
||||
$this->eventDispatcher->dispatchMembershipChange($contact, $campaign, Remover::NAME);
|
||||
} catch (ContactAlreadyRemovedFromCampaignException $exception) {
|
||||
// Do nothing
|
||||
|
||||
$this->logger->debug(
|
||||
"CAMPAIGN: Contact ID {$contact->getId()} was already removed from campaign ID {$campaign->getId()}.",
|
||||
$exception->toArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ArrayCollection<int, Lead> $contacts
|
||||
* @param bool $isExit If true, the contact can be added by a segment/source. If false, the contact can only be added back
|
||||
* by a manual process.
|
||||
*/
|
||||
public function removeContacts(ArrayCollection $contacts, Campaign $campaign, $isExit = false): void
|
||||
{
|
||||
// Get a list of existing campaign members
|
||||
$campaignMembers = $this->leadRepository->getCampaignMembers($contacts->getKeys(), $campaign);
|
||||
|
||||
foreach ($contacts as $contact) {
|
||||
$this->advanceProgressBar();
|
||||
|
||||
if (!isset($campaignMembers[$contact->getId()])) {
|
||||
// Contact is not in the campaign
|
||||
$contacts->remove($contact->getId());
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @var CampaignMember $campaignMember */
|
||||
$campaignMember = $campaignMembers[$contact->getId()];
|
||||
|
||||
try {
|
||||
$this->remover->updateExistingMembership($campaignMember, $isExit);
|
||||
$this->logger->debug("CAMPAIGN: Contact ID {$contact->getId()} was removed from campaign ID {$campaign->getId()}.");
|
||||
} catch (ContactAlreadyRemovedFromCampaignException $exception) {
|
||||
// Contact was already removed from this campaign
|
||||
$contacts->remove($contact->getId());
|
||||
|
||||
$this->logger->debug(
|
||||
"CAMPAIGN: Contact ID {$contact->getId()} was already removed from campaign ID {$campaign->getId()}.",
|
||||
$exception->toArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ($contacts->count()) {
|
||||
// Notify listeners
|
||||
$this->eventDispatcher->dispatchBatchMembershipChange($contacts->toArray(), $campaign, Remover::NAME);
|
||||
}
|
||||
|
||||
// Clear entities from RAM
|
||||
$this->leadRepository->detachEntities($campaignMembers);
|
||||
}
|
||||
|
||||
public function setProgressBar(?ProgressBar $progressBar = null): void
|
||||
{
|
||||
$this->progressBar = $progressBar;
|
||||
}
|
||||
|
||||
private function advanceProgressBar(): void
|
||||
{
|
||||
if ($this->progressBar) {
|
||||
$this->progressBar->advance();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user