/** * Get a list of places for the lead based on IP location * * @param Lead $lead * * @return array */ protected function getPlaces(Lead $lead) { // Get Places from IP addresses $places = []; if ($lead->getIpAddresses()) { foreach ($lead->getIpAddresses() as $ip) { if ($details = $ip->getIpDetails()) { if (!empty($details['latitude']) && !empty($details['longitude'])) { $name = 'N/A'; if (!empty($details['city'])) { $name = $details['city']; } elseif (!empty($details['region'])) { $name = $details['region']; } $place = ['latLng' => [$details['latitude'], $details['longitude']], 'name' => $name]; $places[] = $place; } } } } return $places; }
/** * Create/update lead from form submit * * @param $form * @param array $leadFieldMatches * * @return Lead */ protected function createLeadFromSubmit($form, array $leadFieldMatches) { /** @var \Mautic\LeadBundle\Model\LeadModel $model */ $model = $this->factory->getModel('lead'); $em = $this->factory->getEntityManager(); $logger = $this->factory->getLogger(); //set the mapped data $leadFields = $this->factory->getModel('lead.field')->getRepository()->getAliases(null, true, false); $inKioskMode = $form->isInKioskMode(); if (!$inKioskMode) { // Default to currently tracked lead $lead = $model->getCurrentLead(); $leadId = $lead->getId(); $currentFields = $model->flattenFields($lead->getFields()); $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; $logger->debug('FORM: In kiosk mode so assuming a new contact'); } $uniqueLeadFields = $this->factory->getModel('lead.field')->getUniqueIdentiferFields(); // Closure to get data and unique fields $getData = function ($currentFields, $uniqueOnly = false) use($leadFields, $uniqueLeadFields) { $uniqueFieldsWithData = $data = array(); foreach ($leadFields as $alias) { $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 : array($data, $uniqueFieldsWithData); }; // Closure to help search for a conflict $checkForIdentifierConflict = function ($fieldSet1, $fieldSet2) use($logger) { // Find fields in both sets $potentialConflicts = array_keys(array_intersect_key($fieldSet1, $fieldSet2)); $logger->debug('FORM: Potential conflicts ' . implode(', ', array_keys($potentialConflicts)) . ' = ' . implode(', ', $potentialConflicts)); $conflicts = array(); foreach ($potentialConflicts as $field) { if (!empty($fieldSet1[$field]) && !empty($fieldSet2[$field])) { if (strtolower($fieldSet1[$field]) !== strtolower($fieldSet2[$field])) { $conflicts[] = $field; } } } return array(count($conflicts), $conflicts); }; // Get data for the form submission list($data, $uniqueFieldsWithData) = $getData($leadFieldMatches); $logger->debug('FORM: Unique fields submitted include ' . implode(', ', $uniqueFieldsWithData)); // Check for duplicate lead /** @var \Mautic\LeadBundle\Entity\LeadRepository $leads */ $leads = !empty($uniqueFieldsWithData) ? $em->getRepository('MauticLeadBundle:Lead')->getLeadsByUniqueFields($uniqueFieldsWithData, $leadId) : array(); $uniqueFieldsCurrent = $getData($currentFields, true); if (count($leads)) { $logger->debug(count($leads) . ' found based on unique identifiers'); /** @var \Mautic\LeadBundle\Entity\Lead $foundLead */ $foundLead = $leads[0]; $logger->debug('FORM: Testing contact ID# ' . $foundLead->getId() . ' for conflicts'); // Check for a conflict with the currently tracked lead $foundLeadFields = $model->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) { $logger->debug('FORM: Conflicts found in ' . implode(', ', $conflicts) . ' so not merging'); } else { $logger->debug('FORM: In kiosk mode so not merging'); } } else { $logger->debug('FORM: Merging contacts ' . $lead->getId() . ' and ' . $foundLead->getId()); // Merge the found lead with currently tracked lead $lead = $model->mergeLeads($lead, $foundLead); } // Update unique fields data for comparison with submitted data $currentFields = $model->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); $logger->debug('FORM: Current unique contact fields ' . implode(', ', array_keys($uniqueFieldsCurrent)) . ' = ' . implode(', ', $uniqueFieldsCurrent)); $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); $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->factory->getIpAddress(); //no lead was found by a mapped email field so create a new one if ($lead->isNewlyCreated()) { if (!$inKioskMode) { $lead->addIpAddress($ipAddress); $logger->debug('FORM: Associating ' . $ipAddress->getIpAddress() . ' to contact'); } } elseif (!$inKioskMode) { $leadIpAddresses = $lead->getIpAddresses(); if (!$leadIpAddresses->contains($ipAddress)) { $lead->addIpAddress($ipAddress); $logger->debug('FORM: Associating ' . $ipAddress->getIpAddress() . ' to contact'); } } //set the mapped fields $model->setFieldValues($lead, $data, false); if (!empty($event)) { $event->setIpAddress($ipAddress); $lead->addPointsChangeLog($event); } // last active time $lead->setLastActive(new \DateTime()); //create a new lead $model->saveEntity($lead, false); if (!$inKioskMode) { // Set the current lead which will generate tracking cookies $model->setCurrentLead($lead); } else { // Set system current lead which will still allow execution of events without generating tracking cookies $model->setSystemCurrentLead($lead); } return $lead; }
/** * {@inheritdoc} * * @param Lead $entity * @param bool $unlock */ public function saveEntity($entity, $unlock = true) { //check to see if we can glean information from ip address if (!$entity->imported && count($ips = $entity->getIpAddresses())) { $fields = $entity->getFields(); $details = $ips->first()->getIpDetails(); if (!empty($details['city']) && empty($fields['core']['city']['value'])) { $entity->addUpdatedField('city', $details['city']); } if (!empty($details['region']) && empty($fields['core']['state']['value'])) { $entity->addUpdatedField('state', $details['region']); } if (!empty($details['country']) && empty($fields['core']['country']['value'])) { $entity->addUpdatedField('country', $details['country']); } if (!empty($details['zipcode']) && empty($fields['core']['zipcode']['value'])) { $entity->addUpdatedField('zipcode', $details['zipcode']); } } parent::saveEntity($entity, $unlock); }
/** * Create/update lead from form submit * * @param $form * @param array $leadFieldMatches * * @return Lead */ protected function createLeadFromSubmit($form, array $leadFieldMatches) { /** @var \Mautic\LeadBundle\Model\LeadModel $model */ $model = $this->factory->getModel('lead'); $em = $this->factory->getEntityManager(); //set the mapped data $leadFields = $this->factory->getModel('lead.field')->getRepository()->getAliases(null, true, false); $inKioskMode = $form->isInKioskMode(); if (!$inKioskMode) { // Default to currently tracked lead $lead = $model->getCurrentLead(); $leadId = $lead->getId(); $currentFields = $model->flattenFields($lead->getFields()); } else { // Default to a new lead in kiosk mode $lead = new Lead(); $lead->setNewlyCreated(true); $currentFields = $leadFieldMatches; $leadId = null; } $uniqueLeadFields = $this->factory->getModel('lead.field')->getUniqueIdentiferFields(); // Closure to get data and unique fields $getData = function ($currentFields, $uniqueOnly = false) use($leadFields, $uniqueLeadFields) { $uniqueFieldsWithData = $data = array(); foreach ($leadFields as $alias) { $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 : array($data, $uniqueFieldsWithData); }; // Closure to help search for a conflict $checkForIdentifierConflict = function ($fieldSet1, $fieldSet2) { // Find conflicts $diff = array_diff($fieldSet1, $fieldSet2); // Remove empty values $diff = array_filter($diff); return count($diff); }; // Get data for the form submission list($data, $uniqueFieldsWithData) = $getData($leadFieldMatches); // Check for duplicate lead /** @var \Mautic\LeadBundle\Entity\LeadRepository $leads */ $leads = !empty($uniqueFieldsWithData) ? $em->getRepository('MauticLeadBundle:Lead')->getLeadsByUniqueFields($uniqueFieldsWithData, $leadId) : array(); $uniqueFieldsCurrent = $getData($currentFields, true); if (count($leads)) { /** @var \Mautic\LeadBundle\Entity\Lead $foundLead */ $foundLead = $leads[0]; // Check for a conflict with the currently tracked lead $foundLeadFields = $model->flattenFields($foundLead->getFields()); // Get unique identifier fields for the found lead then compare with the lead currently tracked $uniqueFieldsFound = $getData($foundLeadFields, true); $hasConflict = $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; } else { // Merge the found lead with currently tracked lead $lead = $model->mergeLeads($lead, $foundLead); } // Update unique fields data for comparison with submitted data $currentFields = $model->flattenFields($lead->getFields()); $uniqueFieldsCurrent = $getData($currentFields, true); } if (!$inKioskMode) { // Check for conflicts with the submitted data and the currently tracked lead $hasConflict = $checkForIdentifierConflict($uniqueFieldsWithData, $uniqueFieldsCurrent); if ($hasConflict) { // There's a conflict so create a new lead $lead = new Lead(); $lead->setNewlyCreated(true); } } //check for existing IP address $ipAddress = $this->factory->getIpAddress(); //no lead was found by a mapped email field so create a new one if ($lead->isNewlyCreated()) { if (!$inKioskMode) { $lead->addIpAddress($ipAddress); } // last active time $lead->setLastActive(new \DateTime()); } elseif (!$inKioskMode) { $leadIpAddresses = $lead->getIpAddresses(); if (!$leadIpAddresses->contains($ipAddress)) { $lead->addIpAddress($ipAddress); } } //set the mapped fields $model->setFieldValues($lead, $data, false); if (!empty($event)) { $event->setIpAddress($ipAddress); $lead->addPointsChangeLog($event); } //create a new lead $model->saveEntity($lead, false); if (!$inKioskMode) { // Set the current lead which will generate tracking cookies $model->setCurrentLead($lead); } else { // Set system current lead which will still allow execution of events without generating tracking cookies $model->setSystemCurrentLead($lead); } return $lead; }
/** * {@inheritDoc} */ public function getIpAddresses() { $this->__initializer__ && $this->__initializer__->__invoke($this, 'getIpAddresses', array()); return parent::getIpAddresses(); }
/** * Create/update lead from form submit * * @param $form * @param array $leadFieldMatches * * @return Lead */ protected function createLeadFromSubmit($form, array $leadFieldMatches) { /** @var \Mautic\LeadBundle\Model\LeadModel $model */ $model = $this->factory->getModel('lead'); $em = $this->factory->getEntityManager(); //set the mapped data $leadFields = $this->factory->getModel('lead.field')->getRepository()->getAliases(null, true, false); $data = array(); $inKioskMode = $form->isInKioskMode(); if (!$inKioskMode) { $lead = $model->getCurrentLead(); $leadId = $lead->getId(); $currentFields = $lead->getFields(); } else { $lead = new Lead(); $lead->setNewlyCreated(true); $leadId = null; } $uniqueLeadFields = $this->factory->getModel('lead.field')->getUniqueIdentiferFields(); $uniqueFieldsWithData = array(); foreach ($leadFields as $alias) { $data[$alias] = ''; if (isset($leadFieldMatches[$alias])) { $value = $leadFieldMatches[$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; } } } //update the lead rather than creating a new one if there is for sure identifier match ($leadId is to exclude lead from getCurrentLead()) /** @var \Mautic\LeadBundle\Entity\LeadRepository $leads */ $leads = !empty($uniqueFieldsWithData) ? $em->getRepository('MauticLeadBundle:Lead')->getLeadsByUniqueFields($uniqueFieldsWithData, $leadId) : array(); if (count($leads)) { //merge with current lead if not in kiosk mode $lead = $inKioskMode ? $leads[0] : $model->mergeLeads($lead, $leads[0]); } elseif (!$inKioskMode) { // Flatten current fields $currentFields = $model->flattenFields($currentFields); // Create a new lead if unique identifiers differ from getCurrentLead() and submitted data foreach ($uniqueLeadFields as $alias => $value) { //create a new lead if details differ $currentValue = $currentFields[$alias]; if (!empty($currentValue) && strtolower($currentValue) != strtolower($value)) { //for sure a different lead so create a new one $lead = new Lead(); $lead->setNewlyCreated(true); break; } } } //check for existing IP address $ipAddress = $this->factory->getIpAddress(); //no lead was found by a mapped email field so create a new one if ($lead->isNewlyCreated()) { if (!$inKioskMode) { $lead->addIpAddress($ipAddress); } // last active time $lead->setLastActive(new \DateTime()); } elseif (!$inKioskMode) { $leadIpAddresses = $lead->getIpAddresses(); if (!$leadIpAddresses->contains($ipAddress)) { $lead->addIpAddress($ipAddress); } } //set the mapped fields $model->setFieldValues($lead, $data, false); if (!empty($event)) { $event->setIpAddress($ipAddress); $lead->addPointsChangeLog($event); } //create a new lead $model->saveEntity($lead, false); if (!$inKioskMode) { // Set the current lead which will generate tracking cookies $model->setCurrentLead($lead); } else { // Set system current lead which will still allow execution of events without generating tracking cookies $model->setSystemCurrentLead($lead); } return $lead; }
/** * {@inheritdoc} * * @param Lead $entity * @param bool $unlock */ public function saveEntity($entity, $unlock = true) { $companyFieldMatches = []; $fields = $entity->getFields(); $updatedFields = $entity->getUpdatedFields(); $company = null; if (isset($updatedFields['company'])) { $companyFieldMatches['company'] = $updatedFields['company']; } //check to see if we can glean information from ip address if (!$entity->imported && count($ips = $entity->getIpAddresses())) { $details = $ips->first()->getIpDetails(); if (!empty($details['city']) && empty($fields['core']['city']['value'])) { $entity->addUpdatedField('city', $details['city']); $companyFieldMatches['city'] = $details['city']; } if (!empty($details['region']) && empty($fields['core']['state']['value'])) { $entity->addUpdatedField('state', $details['region']); $companyFieldMatches['state'] = $details['region']; } if (!empty($details['country']) && empty($fields['core']['country']['value'])) { $entity->addUpdatedField('country', $details['country']); $companyFieldMatches['country'] = $details['country']; } if (!empty($details['zipcode']) && empty($fields['core']['zipcode']['value'])) { $entity->addUpdatedField('zipcode', $details['zipcode']); } } if (!empty($companyFieldMatches)) { list($company, $leadAdded) = IdentifyCompanyHelper::identifyLeadsCompany($companyFieldMatches, $entity, $this->companyModel); if ($leadAdded) { $entity->addCompanyChangeLogEntry('form', 'Identify Company', 'Lead added to the company, ' . $company['companyname'], $company['id']); } unset($updatedFields['company']); } parent::saveEntity($entity, $unlock); if (!empty($company)) { // Save after the lead in for new leads created through the API and maybe other places $this->companyModel->addLeadToCompany($company['id'], $entity, true); } }