![]() 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/LeadBundle/Tracker/ |
<?php namespace Mautic\LeadBundle\Tracker; use Mautic\CoreBundle\Entity\IpAddress; use Mautic\CoreBundle\Helper\CoreParametersHelper; use Mautic\CoreBundle\Helper\IpLookupHelper; use Mautic\CoreBundle\Security\Permissions\CorePermissions; use Mautic\LeadBundle\Entity\Lead; use Mautic\LeadBundle\Entity\LeadRepository; use Mautic\LeadBundle\Event\LeadChangeEvent; use Mautic\LeadBundle\Event\LeadEvent; use Mautic\LeadBundle\LeadEvents; use Mautic\LeadBundle\Model\DefaultValueTrait; use Mautic\LeadBundle\Model\FieldModel; use Mautic\LeadBundle\Tracker\Service\ContactTrackingService\ContactTrackingServiceInterface; use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\RequestStack; class ContactTracker { use DefaultValueTrait; private ?Lead $systemContact = null; /** * @var Lead|null */ private $trackedContact; /** * @var FieldModel */ private $leadFieldModel; public function __construct( private LeadRepository $leadRepository, private ContactTrackingServiceInterface $contactTrackingService, private DeviceTracker $deviceTracker, private CorePermissions $security, private LoggerInterface $logger, private IpLookupHelper $ipLookupHelper, private RequestStack $requestStack, private CoreParametersHelper $coreParametersHelper, private EventDispatcherInterface $dispatcher, FieldModel $leadFieldModel ) { $this->leadFieldModel = $leadFieldModel; } /** * @return Lead|null */ public function getContact() { $request = $this->requestStack->getCurrentRequest(); if ($systemContact = $this->getSystemContact()) { return $systemContact; } elseif ($this->isUserSession()) { return null; } if (empty($this->trackedContact)) { $this->trackedContact = $this->getCurrentContact(); $this->generateTrackingCookies(); } if ($request) { $this->logger->debug('CONTACT: Tracking session for contact ID# '.$this->trackedContact->getId().' through '.$request->getMethod().' '.$request->getRequestUri()); } // Log last active for the tracked contact if (!defined('MAUTIC_LEAD_LASTACTIVE_LOGGED')) { $this->leadRepository->updateLastActive($this->trackedContact->getId()); define('MAUTIC_LEAD_LASTACTIVE_LOGGED', 1); } return $this->trackedContact; } /** * Set the contact and generate cookies for future tracking. */ public function setTrackedContact(Lead $trackedContact): void { $this->logger->debug("CONTACT: {$trackedContact->getId()} set as current lead."); if ($this->useSystemContact()) { // Overwrite system current lead $this->setSystemContact($trackedContact); return; } // Take note of previously tracked in order to dispatched change event $previouslyTrackedContact = (is_null($this->trackedContact)) ? null : $this->trackedContact; $previouslyTrackedId = $this->getTrackingId(); // Set the newly tracked contact $this->trackedContact = $trackedContact; // Hydrate custom field data $fields = $trackedContact->getFields(); if (empty($fields)) { $this->hydrateCustomFieldData($trackedContact); } // Set last active $this->trackedContact->setLastActive(new \DateTime()); // If for whatever reason this contact has not been saved yet, don't generate tracking cookies if (!$trackedContact->getId()) { // Delete existing cookies to prevent tracking as someone else $this->deviceTracker->clearTrackingCookies(); return; } // Generate cookies for the newly tracked contact $this->generateTrackingCookies(); if ($previouslyTrackedContact && $previouslyTrackedContact->getId() != $this->trackedContact->getId()) { $this->dispatchContactChangeEvent($previouslyTrackedContact, $previouslyTrackedId); } } /** * System contact bypasses cookie tracking. */ public function setSystemContact(Lead $lead = null): void { if (null !== $lead) { $this->logger->debug("LEAD: {$lead->getId()} set as system lead."); $fields = $lead->getFields(); if (empty($fields)) { $this->hydrateCustomFieldData($lead); } } $this->systemContact = $lead; } /** * @return string|null */ public function getTrackingId() { // Use the new method first if ($trackedDevice = $this->deviceTracker->getTrackedDevice()) { return $trackedDevice->getTrackingId(); } // That failed, so look for the old cookies return $this->contactTrackingService->getTrackedIdentifier(); } /** * @return Lead|null */ private function getSystemContact() { if ($this->useSystemContact() && $this->systemContact) { $this->logger->debug('CONTACT: System lead is being used'); return $this->systemContact; } if ($this->isUserSession()) { $this->logger->debug('CONTACT: In a Mautic user session'); } return null; } /** * @return Lead|null */ private function getCurrentContact() { if ($lead = $this->getContactByTrackedDevice()) { return $lead; } return $this->getContactByIpAddress(); } /** * @return Lead|null */ public function getContactByTrackedDevice() { $lead = null; // Return null for leads that are from a non-trackable IP, prevent anonymous lead with a non-trackable IP to be tracked $ip = $this->ipLookupHelper->getIpAddress(); if ($ip && !$ip->isTrackable()) { return $lead; } // Is there a device being tracked? if ($trackedDevice = $this->deviceTracker->getTrackedDevice()) { $lead = $trackedDevice->getLead(); // Lead associations are not hydrated with custom field values by default $this->hydrateCustomFieldData($lead); } if (null === $lead) { // Check to see if a contact is being tracked via the old cookie method in order to migrate them to the new $lead = $this->contactTrackingService->getTrackedLead(); } if ($lead) { $this->logger->debug("CONTACT: Existing lead found with ID# {$lead->getId()}."); } return $lead; } /** * @return Lead */ private function getContactByIpAddress() { $ip = $this->ipLookupHelper->getIpAddress(); // if no trackingId cookie set the lead is not tracked yet so create a new one if ($ip && !$ip->isTrackable()) { // Don't save leads that are from a non-trackable IP by default return $this->createNewContact($ip, false); } if ($this->coreParametersHelper->get('track_contact_by_ip')) { /** @var Lead[] $leads */ $leads = $this->leadRepository->getLeadsByIp($ip->getIpAddress()); if (count($leads)) { $lead = $leads[0]; $this->logger->debug("CONTACT: Existing lead found with ID# {$lead->getId()}."); return $lead; } } return $this->createNewContact($ip); } /** * @param bool $persist * * @return Lead */ private function createNewContact(IpAddress $ip = null, $persist = true) { // let's create a lead $lead = new Lead(); $lead->setNewlyCreated(true); if ($ip) { $lead->addIpAddress($ip); } if ($persist && !defined('MAUTIC_NON_TRACKABLE_REQUEST')) { // Dispatch events for new lead to write create log, ip address change, etc $event = new LeadEvent($lead, true); $this->dispatcher->dispatch($event, LeadEvents::LEAD_PRE_SAVE); $this->setEntityDefaultValues($lead); $this->leadRepository->saveEntity($lead); $this->hydrateCustomFieldData($lead); $this->dispatcher->dispatch($event, LeadEvents::LEAD_POST_SAVE); $this->logger->debug("CONTACT: New lead created with ID# {$lead->getId()}."); } return $lead; } private function hydrateCustomFieldData(Lead $lead = null): void { if (null === $lead) { return; } // Hydrate fields with custom field data $fields = $this->leadRepository->getFieldValues($lead->getId()); $lead->setFields($fields); } private function useSystemContact(): bool { return $this->isUserSession() || $this->systemContact || defined('IN_MAUTIC_CONSOLE') || null === $this->requestStack->getCurrentRequest(); } private function isUserSession(): bool { return !$this->security->isAnonymous(); } private function dispatchContactChangeEvent(Lead $previouslyTrackedContact, $previouslyTrackedId): void { $newTrackingId = $this->getTrackingId(); $this->logger->debug( "CONTACT: Tracking code changed from $previouslyTrackedId for contact ID# {$previouslyTrackedContact->getId()} to $newTrackingId for contact ID# {$this->trackedContact->getId()}" ); if (null !== $previouslyTrackedId) { if ($this->dispatcher->hasListeners(LeadEvents::CURRENT_LEAD_CHANGED)) { $event = new LeadChangeEvent($previouslyTrackedContact, $previouslyTrackedId, $this->trackedContact, $newTrackingId); $this->dispatcher->dispatch($event, LeadEvents::CURRENT_LEAD_CHANGED); } } } private function generateTrackingCookies(): void { $request = $this->requestStack->getCurrentRequest(); if ($leadId = $this->trackedContact->getId() && null !== $request) { $this->deviceTracker->createDeviceFromUserAgent($this->trackedContact, $request->server->get('HTTP_USER_AGENT')); } } }