![]() 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/plugins/MauticSocialBundle/Helper/ |
<?php namespace MauticPlugin\MauticSocialBundle\Helper; use Doctrine\ORM\EntityManagerInterface; use Mautic\CoreBundle\Helper\CoreParametersHelper; use Mautic\CoreBundle\Translation\Translator; use Mautic\LeadBundle\Entity\Lead; use Mautic\LeadBundle\Model\FieldModel; use Mautic\LeadBundle\Model\LeadModel; use MauticPlugin\MauticSocialBundle\Entity\Monitoring; use MauticPlugin\MauticSocialBundle\Exception\ExitMonitorException; use MauticPlugin\MauticSocialBundle\Model\MonitoringModel; use MauticPlugin\MauticSocialBundle\Model\PostCountModel; use Symfony\Component\Console\Output\OutputInterface; class TwitterCommandHelper { private ?OutputInterface $output = null; private int $updatedLeads = 0; private int $newLeads = 0; private array $manipulatedLeads = []; /** * @var string */ private $twitterHandleField; public function __construct( private LeadModel $leadModel, private FieldModel $fieldModel, private MonitoringModel $monitoringModel, private PostCountModel $postCountModel, private Translator $translator, private EntityManagerInterface $em, CoreParametersHelper $coreParametersHelper ) { $this->translator->setLocale($coreParametersHelper->get('locale', 'en_US')); $this->twitterHandleField = $coreParametersHelper->get('twitter_handle_field', 'twitter'); } public function getNewLeadsCount(): int { return $this->newLeads; } public function getUpdatedLeadsCount(): int { return $this->updatedLeads; } /** * @return array */ public function getManipulatedLeads() { return $this->manipulatedLeads; } public function setOutput(OutputInterface $output): void { $this->output = $output; } /** * @param string $message * @param bool $newLine */ private function output($message, $newLine = true): void { if ($newLine) { $this->output->writeln($message); } else { $this->output->write($message); } } /** * Processes a list of tweets and creates / updates leads in Mautic. * * @param array $statusList * @param Monitoring $monitor */ public function createLeadsFromStatuses($statusList, $monitor): int { $leadField = $this->fieldModel->getRepository()->findOneBy(['alias' => $this->twitterHandleField]); if (!$leadField) { // Field has been deleted or something $this->output($this->translator->trans('mautic.social.monitoring.twitter.field.not.found')); return 0; } $handleFieldGroup = $leadField->getGroup(); // Just a means to let any LeadEvents listeners know that many leads are likely coming in case that matters to their logic defined('MASS_LEADS_MANIPULATION') or define('MASS_LEADS_MANIPULATION', 1); defined('SOCIAL_MONITOR_IMPORT') or define('SOCIAL_MONITOR_IMPORT', 1); // Get a list of existing leads to tone down on queries $usersByHandles = []; $usersByName = ['firstnames' => [], 'lastnames' => []]; $expr = $this->leadModel->getRepository()->createQueryBuilder('f')->expr(); $monitorProperties = $monitor->getProperties(); if (!array_key_exists('checknames', $monitorProperties)) { $monitorProperties['checknames'] = 0; } foreach ($statusList as $i => $status) { // If we don't have a screen_name, the rest is irrelevant. Remove from further processing if (empty($status['user']['screen_name'])) { unset($statusList[$i]); continue; } $usersByHandles[] = $expr->literal($status['user']['screen_name']); // Split the twitter user's name into its parts if we're matching to contacts by name if ($monitorProperties['checknames'] && $status['user']['name'] && str_contains($status['user']['name'], ' ')) { [$firstName, $lastName] = $this->splitName($status['user']['name']); if (!empty($firstName) && !empty($lastName)) { $usersByName['firstnames'][] = $expr->literal($firstName); $usersByName['lastnames'][] = $expr->literal($lastName); } unset($firstName, $lastName); } } unset($expr); if (!empty($usersByHandles)) { $leads = $this->leadModel->getRepository()->getEntities( [ 'filter' => [ 'force' => [ [ 'column' => 'l.'.$this->twitterHandleField, 'expr' => 'in', 'value' => $usersByHandles, ], ], ], ] ); // Key by twitter handle $twitterLeads = []; foreach ($leads as $lead) { $fields = $lead->getFields(); $twitterHandle = strtolower($fields[$handleFieldGroup][$this->twitterHandleField]['value']); $twitterLeads[$twitterHandle] = $lead; } unset($leads); } if ($monitorProperties['checknames']) { // Fetch existing contacts who have an unknown twitter // handle in Mautic but are found during monitoring. $leadsByName = $this->leadModel->getRepository()->getEntities( [ 'filter' => [ 'force' => [ [ 'column' => 'l.firstname', 'expr' => 'in', 'value' => $usersByName['firstnames'], ], [ 'column' => 'l.lastname', 'expr' => 'in', 'value' => $usersByName['lastnames'], ], [ 'column' => 'l.'.$this->twitterHandleField, 'expr' => 'isNull', ], ], ], ] ); // key by name $namedLeads = []; /** @var Lead $lead */ foreach ($leadsByName as $lead) { $firstName = $lead->getFirstname(); $lastName = $lead->getLastname(); $namedLeads[$firstName.' '.$lastName] = $lead; } unset($leadsByName, $firstName, $lastName); } $processedLeads = []; foreach ($statusList as $status) { $handle = strtolower($status['user']['screen_name']); /* @var \Mautic\LeadBundle\Entity\Lead $leadEntity */ if (!isset($processedLeads[$handle])) { $processedLeads[$handle] = 1; $lastActive = new \DateTime($status['created_at']); if (isset($namedLeads[$status['user']['name']])) { ++$this->updatedLeads; $isNew = false; $leadEntity = $namedLeads[$status['user']['name']]; $fields = [ $this->twitterHandleField => $handle, ]; $this->leadModel->setFieldValues($leadEntity, $fields, false); $this->output('Updating existing lead ID #'.$leadEntity->getId().' ('.$handle.'). Matched by first and last names.'); } elseif (isset($twitterLeads[$handle])) { ++$this->updatedLeads; $isNew = false; $leadEntity = $twitterLeads[$handle]; $this->output('Updating existing lead ID #'.$leadEntity->getId().' ('.$handle.')'); } else { ++$this->newLeads; $this->output('Creating new lead'); $isNew = true; $leadEntity = new Lead(); $leadEntity->setNewlyCreated(true); [$firstName, $lastName] = $this->splitName($status['user']['name']); // build new lead fields $fields = [ $this->twitterHandleField => $handle, 'firstname' => $firstName, 'lastname' => $lastName, 'country' => $status['user']['location'], ]; $this->leadModel->setFieldValues($leadEntity, $fields, false); // mark as identified just to be sure $leadEntity->setDateIdentified(new \DateTime()); } $leadEntity->setPreferredProfileImage('Twitter'); // save the lead now $leadEntity->setLastActive($lastActive->format('Y-m-d H:i:s')); try { // save the lead entity $this->leadModel->saveEntity($leadEntity); // Note lead ids $this->manipulatedLeads[$leadEntity->getId()] = 1; // add lead entity to the lead list $this->leadModel->addToLists($leadEntity, $monitor->getLists()); if ($isNew) { $this->setMonitorLeadStat($monitor, $leadEntity); } } catch (ExitMonitorException $e) { $this->output($e->getMessage()); return 0; } catch (\Exception $e) { $this->output($e->getMessage()); continue; } } // Increment the post count $this->incrementPostCount($monitor, $status); } unset($processedLeads); return 1; } /** * Set the monitor's stat record with the metadata. * * @param array $searchMeta */ public function setMonitorStats(Monitoring $monitor, $searchMeta): void { $monitor->setStats($searchMeta); $this->monitoringModel->saveEntity($monitor); } /** * Get monitor record entity. * * @param int $mid */ public function getMonitor($mid): ?Monitoring { return $this->monitoringModel->getEntity($mid); } /** * handles splitting a string handle into first / last name based on a space. * * @param string $name Space separated first & last name. Supports multiple first names * * @return array{string, string} */ private function splitName($name): array { // array the entire name $nameParts = explode(' ', $name); // last part of the array is our last $lastName = array_pop($nameParts); // push the rest of the name into first name $firstName = implode(' ', $nameParts); return [$firstName, $lastName]; } /** * Add new monitoring_leads record to track leads found via the search. * * @param Monitoring $monitor * @param Lead $lead */ private function setMonitorLeadStat($monitor, $lead): void { // track the lead in our monitor_leads table $monitorLead = new \MauticPlugin\MauticSocialBundle\Entity\Lead(); $monitorLead->setMonitor($monitor); $monitorLead->setLead($lead); $monitorLead->setDateAdded(new \DateTime()); /* @var \MauticPlugin\MauticSocialBundle\Entity\LeadRepository $monitorRepository */ $monitorRepository = $this->em->getRepository(\MauticPlugin\MauticSocialBundle\Entity\Lead::class); $monitorRepository->saveEntity($monitorLead); } /** * Increment the post counter. * * @param Monitoring $monitor */ private function incrementPostCount($monitor, $tweet): void { $date = new \DateTime($tweet['created_at']); $this->postCountModel->updatePostCount($monitor, $date); } }