![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/mautic.corals.io/app/bundles/CoreBundle/Command/ |
<?php namespace Mautic\CoreBundle\Command; use Doctrine\ORM\EntityManager; use Mautic\CoreBundle\IpLookup\DoNotSellList\MaxMindDoNotSellList; use Mautic\LeadBundle\Entity\Lead; use Mautic\LeadBundle\Entity\LeadRepository; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * CLI Command to purge data from Mautic that appears on the * MaxMind Do Not Sell list. */ class MaxMindDoNotSellPurgeCommand extends Command { public function __construct( private EntityManager $em, private LeadRepository $leadRepository, private MaxMindDoNotSellList $doNotSellList ) { parent::__construct(); } protected function configure() { $this->setName('mautic:max-mind:purge') ->addOption( 'dry-run', 'd', InputOption::VALUE_NONE, 'Get a list of data that will be purged.' ) ->setHelp(<<<'EOT' The <info>%command.name%</info> command will purge all data from Mautic which is related to any IP found on the MaxMind Do Not Sell List. <info>php %command.full_name% --dry-run</info> Performs a dry-run which will not actually purge any data, but will produce a list of what would be purged. <info>php %command.full_name% --batch-size</info> Set the number of records to return in a batch when processing the Do Not Sell List. This option is ignored if IPs are passed as an argument. EOT ); } protected function execute(InputInterface $input, OutputInterface $output): int { try { $dryRun = $input->getOption('dry-run'); $output->writeln('<info>Step 1: Searching for contacts with data from Do Not Sell List...</info>'); $this->doNotSellList->loadList(); $doNotSellListIPs = array_map(fn ($item): string => // strip subnet mask characters $this->doNotSellList->stripCIDR($item['value']), $this->doNotSellList->getList()); $doNotSellContacts = $this->findContactsFromIPs($doNotSellListIPs); if (0 == count($doNotSellContacts)) { $output->writeln('<info>No matches found.</info>'); return Command::SUCCESS; } $output->writeln('Found '.count($doNotSellContacts)." contacts with an IP from the Do Not Sell list.\n"); if ($dryRun) { $output->writeln('<info>Dry run; skipping purge.</info>'); return Command::SUCCESS; } $output->writeln('<info>Step 2: Purging data...</info>'); $purgeProgress = new ProgressBar($output, count($doNotSellContacts)); foreach ($doNotSellContacts as $contact) { $this->purgeData($contact['id'], $contact['ip_address']); $purgeProgress->advance(1); } $purgeProgress->finish(); $output->writeln("\n<info>Purge complete.</info>\n"); return Command::SUCCESS; } catch (\Exception $e) { $output->writeln("\n<error>".$e->getMessage().'</error>'); return Command::FAILURE; } } private function findContactsFromIPs(array $ips): array { $in = "'".implode("','", $ips)."'"; $sql = 'SELECT x.lead_id AS id, ip.ip_address AS ip_address '. 'FROM '.MAUTIC_TABLE_PREFIX.'lead_ips_xref x '. 'JOIN '.MAUTIC_TABLE_PREFIX.'ip_addresses ip ON x.ip_id = ip.id '. 'WHERE ip.ip_address IN ('.$in.')'; $conn = $this->em->getConnection(); $stmt = $conn->prepare($sql); $result = $stmt->executeQuery(); return $result->fetchAllAssociative(); } private function purgeData(string $contactId, string $ip): bool { /** @var Lead $lead */ $lead = $this->leadRepository->findOneBy(['id' => $contactId]); $matchedIps = array_filter($lead->getIpAddresses()->getValues(), fn ($item): bool => $item->getIpAddress() == $ip); // We only purge data from the contact if it matches the data in the IP details if ($ipDetails = $matchedIps[0]->getIpDetails()) { return false; } $changed = false; if (($ipDetails['city'] ?? '') == $lead->getCity()) { $lead->setCity(null); $changed = true; } if (($ipDetails['region'] ?? '') == $lead->getState()) { $lead->setState(null); $changed = true; } if (($ipDetails['country'] ?? '') == $lead->getCountry()) { $lead->setCountry(null); $changed = true; } if (($ipDetails['zipcode'] ?? '') == $lead->getZipcode()) { $lead->setZipcode(null); $changed = true; } if ($changed) { $this->leadRepository->saveEntity($lead); return true; } return false; } protected static $defaultDescription = 'Purge data connected to MaxMind Do Not Sell list.'; }