Exemple #1
0
 /**
  * Get the contat from request (ct/clickthrough) and handles auto merging of contact data from request parameters
  *
  * @param array $queryFields
  */
 public function getContactFromRequest($queryFields = [])
 {
     $lead = null;
     // Check for a lead requested through clickthrough query parameter
     if (isset($queryFields['ct'])) {
         $clickthrough = $queryFields['ct'];
     } elseif ($clickthrough = $this->request->get('ct', [])) {
         $clickthrough = $this->decodeArrayFromUrl($clickthrough);
     }
     if (is_array($clickthrough) && !empty($clickthrough['lead'])) {
         $lead = $this->getEntity($clickthrough['lead']);
         $this->logger->addDebug("LEAD: Contact ID# {$clickthrough['lead']} tracked through clickthrough query.");
     }
     // First determine if this request is already tracked as a specific lead
     list($trackingId, $generated) = $this->getTrackingCookie();
     if ($leadId = $this->request->cookies->get($trackingId)) {
         if ($lead = $this->getEntity($leadId)) {
             $this->logger->addDebug("LEAD: Contact ID# {$leadId} tracked through tracking ID ({$trackingId}}.");
         }
     }
     // Search for lead by request and/or update lead fields if some data were sent in the URL query
     $availableLeadFields = $this->leadFieldModel->getFieldList(false, false, ['isPublished' => true, 'isPubliclyUpdatable' => true]);
     $uniqueLeadFields = $this->leadFieldModel->getUniqueIdentiferFields();
     $uniqueLeadFieldData = [];
     $inQuery = array_intersect_key($queryFields, $availableLeadFields);
     foreach ($inQuery as $k => $v) {
         if (empty($queryFields[$k])) {
             unset($inQuery[$k]);
         }
         if (array_key_exists($k, $uniqueLeadFields)) {
             $uniqueLeadFieldData[$k] = $v;
         }
     }
     if (count($inQuery)) {
         // Check for leads using unique identifier
         if (count($uniqueLeadFieldData)) {
             $existingLeads = $this->getRepository()->getLeadsByUniqueFields($uniqueLeadFieldData, $lead ? $lead->getId() : null);
             if (!empty($existingLeads)) {
                 $this->logger->addDebug("LEAD: Existing contact ID# {$existingLeads[0]->getId()} found through query identifiers.");
                 // Merge with existing lead or use the one found
                 $lead = $lead ? $this->mergeLeads($lead, $existingLeads[0]) : $existingLeads[0];
             }
         }
     }
     if (empty($lead)) {
         // No lead found so generate one
         $lead = $this->getCurrentLead();
     }
     $leadIpAddresses = $lead->getIpAddresses();
     $ipAddress = $this->ipLookupHelper->getIpAddress();
     if (!$leadIpAddresses->contains($ipAddress)) {
         $lead->addIpAddress($ipAddress);
     }
     $this->setFieldValues($lead, $inQuery);
     if (isset($queryFields['tags'])) {
         $this->modifyTags($lead, $queryFields['tags']);
     }
     $this->setCurrentLead($lead);
     return $lead;
 }
 /**
  * Create/update lead from form submit.
  *
  * @param       $form
  * @param array $leadFieldMatches
  *
  * @return Lead
  */
 protected function createLeadFromSubmit($form, array $leadFieldMatches, $leadFields)
 {
     //set the mapped data
     $inKioskMode = $form->isInKioskMode();
     if (!$inKioskMode) {
         // Default to currently tracked lead
         $lead = $this->leadModel->getCurrentLead();
         $leadId = $lead->getId();
         $currentFields = $this->leadModel->flattenFields($lead->getFields());
         $this->logger->debug('FORM: Not in kiosk mode so using current contact ID #' . $lead->getId());
     } else {
         // Default to a new lead in kiosk mode
         $lead = new Lead();
         $lead->setNewlyCreated(true);
         $currentFields = $leadFieldMatches;
         $leadId = null;
         $this->logger->debug('FORM: In kiosk mode so assuming a new contact');
     }
     $uniqueLeadFields = $this->leadFieldModel->getUniqueIdentiferFields();
     // Closure to get data and unique fields
     $getData = function ($currentFields, $uniqueOnly = false) use($leadFields, $uniqueLeadFields) {
         $uniqueFieldsWithData = $data = [];
         foreach ($leadFields as $alias => $properties) {
             $data[$alias] = '';
             if (isset($currentFields[$alias])) {
                 $value = $currentFields[$alias];
                 $data[$alias] = $value;
                 // make sure the value is actually there and the field is one of our uniques
                 if (!empty($value) && array_key_exists($alias, $uniqueLeadFields)) {
                     $uniqueFieldsWithData[$alias] = $value;
                 }
             }
         }
         return $uniqueOnly ? $uniqueFieldsWithData : [$data, $uniqueFieldsWithData];
     };
     // Closure to help search for a conflict
     $checkForIdentifierConflict = function ($fieldSet1, $fieldSet2) {
         // Find fields in both sets
         $potentialConflicts = array_keys(array_intersect_key($fieldSet1, $fieldSet2));
         $this->logger->debug('FORM: Potential conflicts ' . implode(', ', array_keys($potentialConflicts)) . ' = ' . implode(', ', $potentialConflicts));
         $conflicts = [];
         foreach ($potentialConflicts as $field) {
             if (!empty($fieldSet1[$field]) && !empty($fieldSet2[$field])) {
                 if (strtolower($fieldSet1[$field]) !== strtolower($fieldSet2[$field])) {
                     $conflicts[] = $field;
                 }
             }
         }
         return [count($conflicts), $conflicts];
     };
     // Get data for the form submission
     list($data, $uniqueFieldsWithData) = $getData($leadFieldMatches);
     $this->logger->debug('FORM: Unique fields submitted include ' . implode(', ', $uniqueFieldsWithData));
     // Check for duplicate lead
     /** @var \Mautic\LeadBundle\Entity\Lead[] $leads */
     $leads = !empty($uniqueFieldsWithData) ? $this->em->getRepository('MauticLeadBundle:Lead')->getLeadsByUniqueFields($uniqueFieldsWithData, $leadId) : [];
     $uniqueFieldsCurrent = $getData($currentFields, true);
     if (count($leads)) {
         $this->logger->debug(count($leads) . ' found based on unique identifiers');
         /** @var \Mautic\LeadBundle\Entity\Lead $foundLead */
         $foundLead = $leads[0];
         $this->logger->debug('FORM: Testing contact ID# ' . $foundLead->getId() . ' for conflicts');
         // Check for a conflict with the currently tracked lead
         $foundLeadFields = $this->leadModel->flattenFields($foundLead->getFields());
         // Get unique identifier fields for the found lead then compare with the lead currently tracked
         $uniqueFieldsFound = $getData($foundLeadFields, true);
         list($hasConflict, $conflicts) = $checkForIdentifierConflict($uniqueFieldsFound, $uniqueFieldsCurrent);
         if ($inKioskMode || $hasConflict) {
             // Use the found lead without merging because there is some sort of conflict with unique identifiers or in kiosk mode and thus should not merge
             $lead = $foundLead;
             if ($hasConflict) {
                 $this->logger->debug('FORM: Conflicts found in ' . implode(', ', $conflicts) . ' so not merging');
             } else {
                 $this->logger->debug('FORM: In kiosk mode so not merging');
             }
         } else {
             $this->logger->debug('FORM: Merging contacts ' . $lead->getId() . ' and ' . $foundLead->getId());
             // Merge the found lead with currently tracked lead
             $lead = $this->leadModel->mergeLeads($lead, $foundLead);
         }
         // Update unique fields data for comparison with submitted data
         $currentFields = $this->leadModel->flattenFields($lead->getFields());
         $uniqueFieldsCurrent = $getData($currentFields, true);
     }
     if (!$inKioskMode) {
         // Check for conflicts with the submitted data and the currently tracked lead
         list($hasConflict, $conflicts) = $checkForIdentifierConflict($uniqueFieldsWithData, $uniqueFieldsCurrent);
         $this->logger->debug('FORM: Current unique contact fields ' . implode(', ', array_keys($uniqueFieldsCurrent)) . ' = ' . implode(', ', $uniqueFieldsCurrent));
         $this->logger->debug('FORM: Submitted unique contact fields ' . implode(', ', array_keys($uniqueFieldsWithData)) . ' = ' . implode(', ', $uniqueFieldsWithData));
         if ($hasConflict) {
             // There's a conflict so create a new lead
             $lead = new Lead();
             $lead->setNewlyCreated(true);
             $this->logger->debug('FORM: Conflicts found in ' . implode(', ', $conflicts) . ' between current tracked contact and submitted data so assuming a new contact');
         }
     }
     //check for existing IP address
     $ipAddress = $this->ipLookupHelper->getIpAddress();
     //no lead was found by a mapped email field so create a new one
     if ($lead->isNewlyCreated()) {
         if (!$inKioskMode) {
             $lead->addIpAddress($ipAddress);
             $this->logger->debug('FORM: Associating ' . $ipAddress->getIpAddress() . ' to contact');
         }
     } elseif (!$inKioskMode) {
         $leadIpAddresses = $lead->getIpAddresses();
         if (!$leadIpAddresses->contains($ipAddress)) {
             $lead->addIpAddress($ipAddress);
             $this->logger->debug('FORM: Associating ' . $ipAddress->getIpAddress() . ' to contact');
         }
     }
     //set the mapped fields
     $this->leadModel->setFieldValues($lead, $data, false);
     if (!empty($event)) {
         $event->setIpAddress($ipAddress);
         $lead->addPointsChangeLog($event);
     }
     // last active time
     $lead->setLastActive(new \DateTime());
     //create a new lead
     $this->leadModel->saveEntity($lead, false);
     if (!$inKioskMode) {
         // Set the current lead which will generate tracking cookies
         $this->leadModel->setCurrentLead($lead);
     } else {
         // Set system current lead which will still allow execution of events without generating tracking cookies
         $this->leadModel->setSystemCurrentLead($lead);
     }
     return $lead;
 }