Spaces:
No application file
No application file
namespace Mautic\CampaignBundle\Command; | |
use Mautic\CampaignBundle\Entity\Campaign; | |
use Mautic\CampaignBundle\Entity\CampaignRepository; | |
use Mautic\CampaignBundle\Executioner\ContactFinder\Limiter\ContactLimiter; | |
use Mautic\CampaignBundle\Membership\MembershipBuilder; | |
use Mautic\CoreBundle\Command\ModeratedCommand; | |
use Mautic\CoreBundle\Helper\CoreParametersHelper; | |
use Mautic\CoreBundle\Helper\PathsHelper; | |
use Mautic\CoreBundle\Twig\Helper\FormatterHelper; | |
use Psr\Log\LoggerInterface; | |
use Symfony\Component\Console\Input\InputInterface; | |
use Symfony\Component\Console\Input\InputOption; | |
use Symfony\Component\Console\Output\NullOutput; | |
use Symfony\Component\Console\Output\OutputInterface; | |
use Symfony\Contracts\Translation\TranslatorInterface; | |
class UpdateLeadCampaignsCommand extends ModeratedCommand | |
{ | |
private int $runLimit = 0; | |
private ContactLimiter $contactLimiter; | |
private bool $quiet = false; | |
public function __construct( | |
private CampaignRepository $campaignRepository, | |
private TranslatorInterface $translator, | |
private MembershipBuilder $membershipBuilder, | |
private LoggerInterface $logger, | |
private FormatterHelper $formatterHelper, | |
PathsHelper $pathsHelper, | |
CoreParametersHelper $coreParametersHelper | |
) { | |
parent::__construct($pathsHelper, $coreParametersHelper); | |
} | |
protected function configure() | |
{ | |
$this | |
->setName('mautic:campaigns:rebuild') | |
->setAliases(['mautic:campaigns:update']) | |
->addOption('--batch-limit', '-l', InputOption::VALUE_OPTIONAL, 'Set batch size of contacts to process per round. Defaults to 300.', 300) | |
->addOption( | |
'--max-contacts', | |
'-m', | |
InputOption::VALUE_OPTIONAL, | |
'Set max number of contacts to process per campaign for this script execution. Defaults to all.', | |
0 | |
) | |
->addOption( | |
'--campaign-id', | |
'-i', | |
InputOption::VALUE_OPTIONAL, | |
'Build membership for a specific campaign. Otherwise, all campaigns will be rebuilt.', | |
null | |
) | |
->addOption( | |
'--contact-id', | |
null, | |
InputOption::VALUE_OPTIONAL, | |
'Build membership for a specific contact.', | |
null | |
) | |
->addOption( | |
'--contact-ids', | |
null, | |
InputOption::VALUE_OPTIONAL, | |
'CSV of contact IDs to evaluate.' | |
) | |
->addOption( | |
'--min-contact-id', | |
null, | |
InputOption::VALUE_OPTIONAL, | |
'Build membership starting at a specific contact ID.', | |
null | |
) | |
->addOption( | |
'--max-contact-id', | |
null, | |
InputOption::VALUE_OPTIONAL, | |
'Build membership up to a specific contact ID.', | |
null | |
) | |
->addOption( | |
'--thread-id', | |
null, | |
InputOption::VALUE_OPTIONAL, | |
'The number of this current process if running multiple in parallel.' | |
) | |
->addOption( | |
'--max-threads', | |
null, | |
InputOption::VALUE_OPTIONAL, | |
'The maximum number of processes you intend to run in parallel.' | |
) | |
->addOption( | |
'exclude', | |
'd', | |
InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, | |
'Exclude a specific campaign from being rebuilt. Otherwise, all campaigns will be rebuilt.', | |
[] | |
); | |
parent::configure(); | |
} | |
protected function execute(InputInterface $input, OutputInterface $output): int | |
{ | |
$id = $input->getOption('campaign-id'); | |
$batchLimit = $input->getOption('batch-limit'); | |
$contactMinId = $input->getOption('min-contact-id'); | |
$contactMaxId = $input->getOption('max-contact-id'); | |
$contactId = $input->getOption('contact-id'); | |
$contactIds = $this->formatterHelper->simpleCsvToArray($input->getOption('contact-ids'), 'int'); | |
$threadId = $input->getOption('thread-id'); | |
$maxThreads = $input->getOption('max-threads'); | |
$this->runLimit = $input->getOption('max-contacts'); | |
$this->quiet = (bool) $input->getOption('quiet'); | |
$this->output = ($this->quiet) ? new NullOutput() : $output; | |
$excludeCampaigns = $input->getOption('exclude'); | |
if ($threadId && $maxThreads && (int) $threadId > (int) $maxThreads) { | |
$this->output->writeln('--thread-id cannot be larger than --max-thread'); | |
return \Symfony\Component\Console\Command\Command::FAILURE; | |
} | |
if (!$this->checkRunStatus($input, $output, $id)) { | |
return \Symfony\Component\Console\Command\Command::SUCCESS; | |
} | |
$this->contactLimiter = new ContactLimiter($batchLimit, $contactId, $contactMinId, $contactMaxId, $contactIds, $threadId, $maxThreads); | |
if ($id) { | |
$campaign = $this->campaignRepository->getEntity($id); | |
if (null === $campaign) { | |
$output->writeln('<error>'.$this->translator->trans('mautic.campaign.rebuild.not_found', ['%id%' => $id]).'</error>'); | |
return \Symfony\Component\Console\Command\Command::FAILURE; | |
} | |
$this->updateCampaign($campaign); | |
} else { | |
$filter = [ | |
'iterable_mode' => true, | |
]; | |
if (is_array($excludeCampaigns) && count($excludeCampaigns) > 0) { | |
$filter['filter'] = [ | |
'force' => [ | |
[ | |
'expr' => 'notIn', | |
'column' => $this->campaignRepository->getTableAlias().'.id', | |
'value' => $excludeCampaigns, | |
], | |
], | |
]; | |
} | |
$campaigns = $this->campaignRepository->getEntities($filter); | |
foreach ($campaigns as $campaign) { | |
$this->updateCampaign($campaign); | |
unset($campaign); | |
} | |
} | |
$this->completeRun(); | |
return \Symfony\Component\Console\Command\Command::SUCCESS; | |
} | |
/** | |
* @throws \Exception | |
*/ | |
private function updateCampaign(Campaign $campaign): void | |
{ | |
if (!$campaign->isPublished()) { | |
return; | |
} | |
try { | |
$this->output->writeln( | |
'<info>'.$this->translator->trans('mautic.campaign.rebuild.rebuilding', ['%id%' => $campaign->getId()]).'</info>' | |
); | |
// Reset batch limiter | |
$this->contactLimiter->resetBatchMinContactId(); | |
$this->membershipBuilder->build($campaign, $this->contactLimiter, $this->runLimit, ($this->quiet) ? null : $this->output); | |
} catch (\Exception $exception) { | |
if ('prod' !== MAUTIC_ENV) { | |
// Throw the exception for dev/test mode | |
throw $exception; | |
} | |
$this->logger->error('CAMPAIGN: '.$exception->getMessage()); | |
} | |
// Don't detach in tests since this command will be ran multiple times in the same process | |
if ('test' !== MAUTIC_ENV) { | |
$this->campaignRepository->detachEntity($campaign); | |
} | |
$this->output->writeln(''); | |
} | |
protected static $defaultDescription = 'Rebuild campaigns based on contact segments.'; | |
} | |