233 lines
8.8 KiB
PHP
Executable File
233 lines
8.8 KiB
PHP
Executable File
<?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();
|
|
}
|
|
}
|
|
}
|