Example #1
0
 /**
  * Add a delete entry to the audit log.
  *
  * @param Events\AssetEvent $event
  */
 public function onAssetDelete(Events\AssetEvent $event)
 {
     $asset = $event->getAsset();
     $log = ['bundle' => 'asset', 'object' => 'asset', 'objectId' => $asset->deletedId, 'action' => 'delete', 'details' => ['name' => $asset->getTitle()], 'ipAddress' => $this->ipLookupHelper->getIpAddressFromRequest()];
     $this->auditLogModel->writeToLog($log);
     //In case of batch delete, this method call remove the uploaded file
     $asset->removeUpload();
 }
Example #2
0
 /**
  * @param CampaignExecutionEvent $event
  */
 public function onCampaignTriggerActionChangePoints(CampaignExecutionEvent $event)
 {
     if (!$event->checkContext('lead.changepoints')) {
         return;
     }
     $lead = $event->getLead();
     $points = $event->getConfig()['points'];
     $somethingHappened = false;
     if ($lead !== null && !empty($points)) {
         $lead->adjustPoints($points);
         //add a lead point change log
         $log = new PointsChangeLog();
         $log->setDelta($points);
         $log->setLead($lead);
         $log->setType('campaign');
         $log->setEventName("{$event->getEvent()['campaign']['id']}: {$event->getEvent()['campaign']['name']}");
         $log->setActionName("{$event->getEvent()['id']}: {$event->getEvent()['name']}");
         $log->setIpAddress($this->ipLookupHelper->getIpAddress());
         $log->setDateAdded(new \DateTime());
         $lead->addPointsChangeLog($log);
         $this->leadModel->saveEntity($lead);
         $somethingHappened = true;
     }
     return $event->setResult($somethingHappened);
 }
Example #3
0
 /**
  * Trigger events for the current lead
  *
  * @param Lead $lead
  */
 public function triggerEvents(Lead $lead)
 {
     $points = $lead->getPoints();
     //find all published triggers that is applicable to this points
     /** @var \Mautic\PointBundle\Entity\TriggerEventRepository $repo */
     $repo = $this->getEventRepository();
     $events = $repo->getPublishedByPointTotal($points);
     if (!empty($events)) {
         //get a list of actions that has already been applied to this lead
         $appliedEvents = $repo->getLeadTriggeredEvents($lead->getId());
         $ipAddress = $this->ipLookupHelper->getIpAddress();
         $persist = array();
         foreach ($events as $event) {
             if (isset($appliedEvents[$event['id']])) {
                 //don't apply the event to the lead if it's already been done
                 continue;
             }
             if ($this->triggerEvent($event, $lead, true)) {
                 $log = new LeadTriggerLog();
                 $log->setIpAddress($ipAddress);
                 $log->setEvent($this->em->getReference('MauticPointBundle:TriggerEvent', $event['id']));
                 $log->setLead($lead);
                 $log->setDateFired(new \DateTime());
                 $persist[] = $log;
             }
         }
         if (!empty($persist)) {
             $this->getEventRepository()->saveEntities($persist);
             $this->em->clear('Mautic\\PointBundle\\Entity\\LeadTriggerLog');
             $this->em->clear('Mautic\\PointBundle\\Entity\\TriggerEvent');
         }
     }
 }
Example #4
0
 /**
  * @param Event|int                                $event
  * @param Campaign                                 $campaign
  * @param \Mautic\LeadBundle\Entity\Lead|null      $lead
  * @param \Mautic\CoreBundle\Entity\IpAddress|null $ipAddress
  * @param bool                                     $systemTriggered
  *
  * @return LeadEventLog
  *
  * @throws \Doctrine\ORM\ORMException
  */
 public function getLogEntity($event, $campaign, $lead = null, $ipAddress = null, $systemTriggered = false)
 {
     $log = new LeadEventLog();
     if ($ipAddress == null) {
         // Lead triggered from system IP
         $ipAddress = $this->ipLookupHelper->getIpAddress();
     }
     $log->setIpAddress($ipAddress);
     if (!$event instanceof Event) {
         $event = $this->em->getReference('MauticCampaignBundle:Event', $event);
     }
     $log->setEvent($event);
     if (!$campaign instanceof Campaign) {
         $campaign = $this->em->getReference('MauticCampaignBundle:Campaign', $campaign);
     }
     $log->setCampaign($campaign);
     if ($lead == null) {
         $lead = $this->leadModel->getCurrentLead();
     }
     $log->setLead($lead);
     $log->setDateTriggered(new \DateTime());
     $log->setSystemTriggered($systemTriggered);
     // Save some RAM for batch processing
     unset($event, $campaign, $lead);
     return $log;
 }
Example #5
0
 /**
  * @param Events\LeadMergeEvent $event
  */
 public function onLeadMerge(Events\LeadMergeEvent $event)
 {
     $this->em->getRepository('MauticLeadBundle:PointsChangeLog')->updateLead($event->getLoser()->getId(), $event->getVictor()->getId());
     $this->em->getRepository('MauticLeadBundle:ListLead')->updateLead($event->getLoser()->getId(), $event->getVictor()->getId());
     $this->em->getRepository('MauticLeadBundle:LeadNote')->updateLead($event->getLoser()->getId(), $event->getVictor()->getId());
     $log = ['bundle' => 'lead', 'object' => 'lead', 'objectId' => $event->getLoser()->getId(), 'action' => 'merge', 'details' => ['merged_into' => $event->getVictor()->getId()], 'ipAddress' => $this->ipLookupHelper->getIpAddressFromRequest()];
     $this->auditLogModel->writeToLog($log);
 }
Example #6
0
 /**
  * Record page hit.
  *
  * @param           $page
  * @param Request   $request
  * @param string    $code
  * @param Lead|null $lead
  * @param array     $query
  *
  * @return Hit $hit
  *
  * @throws \Exception
  */
 public function hitPage($page, Request $request, $code = '200', Lead $lead = null, $query = [])
 {
     // Don't skew results with user hits
     if (!$this->security->isAnonymous()) {
         return;
     }
     // Process the query
     if (empty($query)) {
         $query = $this->getHitQuery($request, $page);
     }
     $hit = new Hit();
     $hit->setDateHit(new \Datetime());
     // Check for existing IP
     $ipAddress = $this->ipLookupHelper->getIpAddress();
     $hit->setIpAddress($ipAddress);
     // Check for any clickthrough info
     $clickthrough = [];
     if (!empty($query['ct'])) {
         $clickthrough = $query['ct'];
         if (!is_array($clickthrough)) {
             $clickthrough = $this->decodeArrayFromUrl($clickthrough);
         }
         if (!empty($clickthrough['channel'])) {
             if (count($clickthrough['channel']) === 1) {
                 $channelId = reset($clickthrough['channel']);
                 $channel = key($clickthrough['channel']);
             } else {
                 $channel = $clickthrough['channel'][0];
                 $channelId = (int) $clickthrough['channel'][1];
             }
             $hit->setSource($channel);
             $hit->setSourceId($channelId);
         } elseif (!empty($clickthrough['source'])) {
             $hit->setSource($clickthrough['source'][0]);
             $hit->setSourceId($clickthrough['source'][1]);
         }
         if (!empty($clickthrough['email'])) {
             $emailRepo = $this->em->getRepository('MauticEmailBundle:Email');
             if ($emailEntity = $emailRepo->getEntity($clickthrough['email'])) {
                 $hit->setEmail($emailEntity);
             }
         }
     }
     // Get lead if required
     if (null == $lead) {
         $lead = $this->leadModel->getContactFromRequest($query);
     }
     $this->leadModel->saveEntity($lead);
     // Set info from request
     $hit->setQuery($query);
     $hit->setUrl(isset($query['page_url']) ? $query['page_url'] : $request->getRequestUri());
     if (isset($query['page_referrer'])) {
         $hit->setReferer($query['page_referrer']);
     }
     if (isset($query['page_language'])) {
         $hit->setPageLanguage($query['page_language']);
     }
     if (isset($query['page_title'])) {
         $hit->setUrlTitle($query['page_title']);
     }
     // Store tracking ID
     list($trackingId, $trackingNewlyGenerated) = $this->leadModel->getTrackingCookie();
     $hit->setTrackingId($trackingId);
     $hit->setLead($lead);
     $isUnique = $trackingNewlyGenerated;
     if (!$trackingNewlyGenerated) {
         $lastHit = $request->cookies->get('mautic_referer_id');
         if (!empty($lastHit)) {
             //this is not a new session so update the last hit if applicable with the date/time the user left
             $this->getHitRepository()->updateHitDateLeft($lastHit);
         }
         // Check if this is a unique page hit
         $isUnique = $this->getHitRepository()->isUniquePageHit($page, $trackingId);
     }
     if (!empty($page)) {
         if ($page instanceof Page) {
             $hit->setPage($page);
             $hit->setPageLanguage($page->getLanguage());
             $isVariant = $isUnique ? $page->getVariantStartDate() : false;
             try {
                 $this->getRepository()->upHitCount($page->getId(), 1, $isUnique, !empty($isVariant));
             } catch (\Exception $exception) {
                 $this->logger->addError($exception->getMessage(), ['exception' => $exception]);
             }
         } elseif ($page instanceof Redirect) {
             $hit->setRedirect($page);
             try {
                 $this->pageRedirectModel->getRepository()->upHitCount($page->getId(), 1, $isUnique);
                 // If this is a trackable, up the trackable counts as well
                 if (!empty($clickthrough['channel'])) {
                     $channelId = reset($clickthrough['channel']);
                     $channel = key($clickthrough['channel']);
                     $this->pageTrackableModel->getRepository()->upHitCount($page->getId(), $channel, $channelId, 1, $isUnique);
                 }
             } catch (\Exception $exception) {
                 if (MAUTIC_ENV === 'dev') {
                     throw $exception;
                 } else {
                     $this->logger->addError($exception->getMessage(), ['exception' => $exception]);
                 }
             }
         }
     }
     //glean info from the IP address
     if ($details = $ipAddress->getIpDetails()) {
         $hit->setCountry($details['country']);
         $hit->setRegion($details['region']);
         $hit->setCity($details['city']);
         $hit->setIsp($details['isp']);
         $hit->setOrganization($details['organization']);
     }
     $hit->setCode($code);
     if (!$hit->getReferer()) {
         $hit->setReferer($request->server->get('HTTP_REFERER'));
     }
     $hit->setUserAgent($request->server->get('HTTP_USER_AGENT'));
     $hit->setRemoteHost($request->server->get('REMOTE_HOST'));
     if ($isUnique) {
         // Add UTM tags entry if a UTM tag exist
         $queryHasUtmTags = false;
         if (!is_array($query)) {
             parse_str($query, $query);
         }
         foreach ($query as $key => $value) {
             if (strpos($key, 'utm_') !== false) {
                 $queryHasUtmTags = true;
                 break;
             }
         }
         if ($queryHasUtmTags) {
             $utmTags = new UtmTag();
             $utmTags->setDateAdded($hit->getDateHit());
             $utmTags->setUrl($hit->getUrl());
             $utmTags->setReferer($hit->getReferer());
             $utmTags->setQuery($hit->getQuery());
             $utmTags->setUserAgent($hit->getUserAgent());
             $utmTags->setRemoteHost($hit->getRemoteHost());
             $utmTags->setLead($lead);
             if (key_exists('utm_campaign', $query)) {
                 $utmTags->setUtmCampaign($query['utm_campaign']);
             }
             if (key_exists('utm_term', $query)) {
                 $utmTags->setUtmTerm($query['utm_term']);
             }
             if (key_exists('utm_content', $query)) {
                 $utmTags->setUtmConent($query['utm_content']);
             }
             if (key_exists('utm_medium', $query)) {
                 $utmTags->setUtmMedium($query['utm_medium']);
             }
             if (key_exists('utm_source', $query)) {
                 $utmTags->setUtmSource($query['utm_source']);
             }
             $repo = $this->em->getRepository('MauticLeadBundle:UtmTag');
             $repo->saveEntity($utmTags);
             $this->leadModel->setUtmTags($lead, $utmTags);
         }
     }
     //get a list of the languages the user prefers
     $browserLanguages = $request->server->get('HTTP_ACCEPT_LANGUAGE');
     if (!empty($browserLanguages)) {
         $languages = explode(',', $browserLanguages);
         foreach ($languages as $k => $l) {
             if ($pos = strpos(';q=', $l) !== false) {
                 //remove weights
                 $languages[$k] = substr($l, 0, $pos);
             }
         }
         $hit->setBrowserLanguages($languages);
     }
     //device granularity
     $dd = new DeviceDetector($request->server->get('HTTP_USER_AGENT'));
     $dd->parse();
     $deviceRepo = $this->leadModel->getDeviceRepository();
     $device = $deviceRepo->getDevice(null, $lead, $dd->getDeviceName(), $dd->getBrand(), $dd->getModel());
     if (empty($device)) {
         $device = new LeadDevice();
         $device->setClientInfo($dd->getClient());
         $device->setDevice($dd->getDeviceName());
         $device->setDeviceBrand($dd->getBrand());
         $device->setDeviceModel($dd->getModel());
         $device->setDeviceOs($dd->getOs());
         $device->setDateOpen($hit->getDateHit());
         $device->setLead($lead);
         $this->em->persist($device);
     } else {
         $device = $deviceRepo->getEntity($device['id']);
     }
     $hit->setDeviceStat($device);
     // Wrap in a try/catch to prevent deadlock errors on busy servers
     try {
         $this->em->persist($hit);
         $this->em->flush($hit);
     } catch (\Exception $exception) {
         if (MAUTIC_ENV === 'dev') {
             throw $exception;
         } else {
             $this->logger->addError($exception->getMessage(), ['exception' => $exception]);
         }
     }
     if ($this->dispatcher->hasListeners(PageEvents::PAGE_ON_HIT)) {
         $event = new PageHitEvent($hit, $request, $code, $clickthrough, $isUnique);
         $this->dispatcher->dispatch(PageEvents::PAGE_ON_HIT, $event);
     }
     //save hit to the cookie to use to update the exit time
     $this->cookieHelper->setCookie('mautic_referer_id', $hit->getId());
     return $hit;
 }
Example #7
0
 /**
  * Add a delete entry to the audit log.
  *
  * @param ReportEvent $event
  */
 public function onReportDelete(ReportEvent $event)
 {
     $report = $event->getReport();
     $log = ['bundle' => 'report', 'object' => 'report', 'objectId' => $report->deletedId, 'action' => 'delete', 'details' => ['name' => $report->getName()], 'ipAddress' => $this->ipLookupHelper->getIpAddressFromRequest()];
     $this->auditLogModel->writeToLog($log);
 }
Example #8
0
 /**
  * Add a delete entry to the audit log.
  *
  * @param WebhookEvent $event
  */
 public function onWebhookDelete(WebhookEvent $event)
 {
     $webhook = $event->getWebhook();
     $log = ['bundle' => 'webhook', 'object' => 'webhook', 'objectId' => $event->getWebhook()->deletedId, 'action' => 'delete', 'details' => ['name' => $webhook->getName()], 'ipAddress' => $this->ipLookupHelper->getIpAddressFromRequest()];
     $this->auditLogModel->writeToLog($log);
 }
Example #9
0
 /**
  * Add a role delete entry to the audit log.
  *
  * @param Events\ClientEvent $event
  */
 public function onClientDelete(Events\ClientEvent $event)
 {
     $client = $event->getClient();
     $log = ['bundle' => 'api', 'object' => 'client', 'objectId' => $client->deletedId, 'action' => 'delete', 'details' => ['name' => $client->getName()], 'ipAddress' => $this->ipLookupHelper->getIpAddressFromRequest()];
     $this->auditLogModel->writeToLog($log);
 }
Example #10
0
 /**
  * @param $asset
  * @param null   $request
  * @param string $code
  * @param array  $systemEntry
  *
  * @throws \Doctrine\ORM\ORMException
  * @throws \Exception
  */
 public function trackDownload($asset, $request = null, $code = '200', $systemEntry = [])
 {
     // Don't skew results with in-house downloads
     if (empty($systemEntry) && !$this->security->isAnonymous()) {
         return;
     }
     if ($request == null) {
         $request = $this->request;
     }
     $download = new Download();
     $download->setDateDownload(new \Datetime());
     // Download triggered by lead
     if (empty($systemEntry)) {
         //check for any clickthrough info
         $clickthrough = $request->get('ct', false);
         if (!empty($clickthrough)) {
             $clickthrough = $this->decodeArrayFromUrl($clickthrough);
             if (!empty($clickthrough['lead'])) {
                 $lead = $this->leadModel->getEntity($clickthrough['lead']);
                 if ($lead !== null) {
                     $this->leadModel->setLeadCookie($clickthrough['lead']);
                     list($trackingId, $trackingNewlyGenerated) = $this->leadModel->getTrackingCookie();
                     $leadClickthrough = true;
                     $this->leadModel->setCurrentLead($lead);
                 }
             }
             if (!empty($clickthrough['channel'])) {
                 if (count($clickthrough['channel']) === 1) {
                     $channelId = reset($clickthrough['channel']);
                     $channel = key($clickthrough['channel']);
                 } else {
                     $channel = $clickthrough['channel'][0];
                     $channelId = (int) $clickthrough['channel'][1];
                 }
                 $download->setSource($channel);
                 $download->setSourceId($channelId);
             } elseif (!empty($clickthrough['source'])) {
                 $download->setSource($clickthrough['source'][0]);
                 $download->setSourceId($clickthrough['source'][1]);
             }
             if (!empty($clickthrough['email'])) {
                 $emailRepo = $this->em->getRepository('MauticEmailBundle:Email');
                 if ($emailEntity = $emailRepo->getEntity($clickthrough['email'])) {
                     $download->setEmail($emailEntity);
                 }
             }
         }
         if (empty($leadClickthrough)) {
             list($lead, $trackingId, $trackingNewlyGenerated) = $this->leadModel->getCurrentLead(true);
         }
         $download->setLead($lead);
     } else {
         $trackingId = '';
         if (isset($systemEntry['lead'])) {
             $lead = $systemEntry['lead'];
             if (!$lead instanceof Lead) {
                 $leadId = is_array($lead) ? $lead['id'] : $lead;
                 $lead = $this->em->getReference('MauticLeadBundle:Lead', $leadId);
             }
             $download->setLead($lead);
         }
         if (!empty($systemEntry['source'])) {
             $download->setSource($systemEntry['source'][0]);
             $download->setSourceId($systemEntry['source'][1]);
         }
         if (isset($systemEntry['email'])) {
             $email = $systemEntry['email'];
             if (!$email instanceof Email) {
                 $emailId = is_array($email) ? $email['id'] : $email;
                 $email = $this->em->getReference('MauticEmailBundle:Email', $emailId);
             }
             $download->setEmail($email);
         }
         if (isset($systemEntry['tracking_id'])) {
             $trackingId = $systemEntry['tracking_id'];
             $trackingNewlyGenerated = false;
         } elseif ($this->security->isAnonymous() && !defined('IN_MAUTIC_CONSOLE')) {
             // If the session is anonymous and not triggered via CLI, assume the lead did something to trigger the
             // system forced download such as an email
             list($trackingId, $trackingNewlyGenerated) = $this->leadModel->getTrackingCookie();
         }
     }
     $isUnique = true;
     if (!empty($trackingNewlyGenerated)) {
         // Cookie was just generated so this is definitely a unique download
         $isUnique = $trackingNewlyGenerated;
     } elseif (!empty($trackingId)) {
         // Determine if this is a unique download
         $isUnique = $this->getDownloadRepository()->isUniqueDownload($asset->getId(), $trackingId);
     }
     $download->setTrackingId($trackingId);
     if (!empty($asset) && empty($systemEntry)) {
         $download->setAsset($asset);
         $this->getRepository()->upDownloadCount($asset->getId(), 1, $isUnique);
     }
     //check for existing IP
     $ipAddress = $this->ipLookupHelper->getIpAddress();
     $download->setCode($code);
     $download->setIpAddress($ipAddress);
     if ($request !== null) {
         $download->setReferer($request->server->get('HTTP_REFERER'));
     }
     // Dispatch event
     if ($this->dispatcher->hasListeners(AssetEvents::ASSET_ON_LOAD)) {
         $event = new AssetLoadEvent($download, $isUnique);
         $this->dispatcher->dispatch(AssetEvents::ASSET_ON_LOAD, $event);
     }
     // Wrap in a try/catch to prevent deadlock errors on busy servers
     try {
         $this->em->persist($download);
         $this->em->flush($download);
     } catch (\Exception $e) {
         if (MAUTIC_ENV === 'dev') {
             throw $e;
         } else {
             error_log($e);
         }
     }
     $this->em->detach($download);
 }
Example #11
0
 /**
  * Triggers a specific point change
  *
  * @param $type
  * @param mixed $eventDetails passthrough from function triggering action to the callback function
  * @param mixed $typeId Something unique to the triggering event to prevent  unnecessary duplicate calls
  * @param Lead  $lead
  *25
  * @return void
  */
 public function triggerAction($type, $eventDetails = null, $typeId = null, Lead $lead = null)
 {
     //only trigger actions for anonymous users
     if (!$this->security->isAnonymous()) {
         return;
     }
     if ($typeId !== null && MAUTIC_ENV === 'prod') {
         //let's prevent some unnecessary DB calls
         $triggeredEvents = $this->session->get('mautic.triggered.point.actions', array());
         if (in_array($typeId, $triggeredEvents)) {
             return;
         }
         $triggeredEvents[] = $typeId;
         $this->session->set('mautic.triggered.point.actions', $triggeredEvents);
     }
     //find all the actions for published points
     /** @var \Mautic\PointBundle\Entity\PointRepository $repo */
     $repo = $this->getRepository();
     $availablePoints = $repo->getPublishedByType($type);
     $ipAddress = $this->ipLookupHelper->getIpAddress();
     if (null === $lead) {
         $lead = $this->leadModel->getCurrentLead();
         if (null === $lead || !$lead->getId()) {
             return;
         }
     }
     //get available actions
     $availableActions = $this->getPointActions();
     //get a list of actions that has already been performed on this lead
     $completedActions = $repo->getCompletedLeadActions($type, $lead->getId());
     $persist = array();
     foreach ($availablePoints as $action) {
         //if it's already been done, then skip it
         if (isset($completedActions[$action->getId()])) {
             continue;
         }
         //make sure the action still exists
         if (!isset($availableActions['actions'][$action->getType()])) {
             continue;
         }
         $settings = $availableActions['actions'][$action->getType()];
         $args = array('action' => array('id' => $action->getId(), 'type' => $action->getType(), 'name' => $action->getName(), 'properties' => $action->getProperties(), 'points' => $action->getDelta()), 'lead' => $lead, 'factory' => $this->factory, 'eventDetails' => $eventDetails);
         $callback = isset($settings['callback']) ? $settings['callback'] : array('\\Mautic\\PointBundle\\Helper\\EventHelper', 'engagePointAction');
         if (is_callable($callback)) {
             if (is_array($callback)) {
                 $reflection = new \ReflectionMethod($callback[0], $callback[1]);
             } elseif (strpos($callback, '::') !== false) {
                 $parts = explode('::', $callback);
                 $reflection = new \ReflectionMethod($parts[0], $parts[1]);
             } else {
                 $reflection = new \ReflectionMethod(null, $callback);
             }
             $pass = array();
             foreach ($reflection->getParameters() as $param) {
                 if (isset($args[$param->getName()])) {
                     $pass[] = $args[$param->getName()];
                 } else {
                     $pass[] = null;
                 }
             }
             $pointsChange = $reflection->invokeArgs($this, $pass);
             if ($pointsChange) {
                 $delta = $action->getDelta();
                 $lead->adjustPoints($delta);
                 $parsed = explode('.', $action->getType());
                 $lead->addPointsChangeLogEntry($parsed[0], $action->getId() . ": " . $action->getName(), $parsed[1], $delta, $ipAddress);
                 $event = new PointActionEvent($action, $lead);
                 $this->dispatcher->dispatch(PointEvents::POINT_ON_ACTION, $event);
                 $log = new LeadPointLog();
                 $log->setIpAddress($ipAddress);
                 $log->setPoint($action);
                 $log->setLead($lead);
                 $log->setDateFired(new \DateTime());
                 $persist[] = $log;
             }
         }
     }
     if (!empty($persist)) {
         $this->leadModel->saveEntity($lead);
         $this->getRepository()->saveEntities($persist);
         // Detach logs to reserve memory
         $this->em->clear('Mautic\\PointBundle\\Entity\\LeadPointLog');
     }
 }
Example #12
0
 /**
  * Add a delete entry to the audit log.
  *
  * @param Events\PageEvent $event
  */
 public function onPageDelete(Events\PageEvent $event)
 {
     $page = $event->getPage();
     $log = ['bundle' => 'page', 'object' => 'page', 'objectId' => $page->deletedId, 'action' => 'delete', 'details' => ['name' => $page->getTitle()], 'ipAddress' => $this->ipLookupHelper->getIpAddressFromRequest()];
     $this->auditLogModel->writeToLog($log);
 }
Example #13
0
 /**
  * Add a role delete entry to the audit log.
  *
  * @param Events\RoleEvent $event
  */
 public function onRoleDelete(Events\RoleEvent $event)
 {
     $role = $event->getRole();
     $log = ['bundle' => 'user', 'object' => 'role', 'objectId' => $role->deletedId, 'action' => 'delete', 'details' => ['name' => $role->getName()], 'ipAddress' => $this->ipLookupHelper->getIpAddressFromRequest()];
     $this->auditLogModel->writeToLog($log);
 }
Example #14
0
 /**
  * Add a delete entry to the audit log.
  *
  * @param Events\TriggerEvent $event
  */
 public function onTriggerDelete(Events\TriggerEvent $event)
 {
     $trigger = $event->getTrigger();
     $log = ['bundle' => 'point', 'object' => 'trigger', 'objectId' => $trigger->deletedId, 'action' => 'delete', 'details' => ['name' => $trigger->getName()], 'ipAddress' => $this->ipLookupHelper->getIpAddressFromRequest()];
     $this->auditLogModel->writeToLog($log);
 }
Example #15
0
 /**
  * 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;
 }
Example #16
0
 /**
  * Add a company delete entry to the audit log.
  *
  * @param Events\CompanyEvent $event
  */
 public function onCompanyDelete(Events\CompanyEvent $event)
 {
     $company = $event->getCompany();
     $log = ['bundle' => 'lead', 'object' => 'field', 'objectId' => $company->deletedId, 'action' => 'delete', 'details' => ['name', $company->getPrimaryIdentifier()], 'ipAddress' => $this->ipLookupHelper->getIpAddressFromRequest()];
     $this->auditLogModel->writeToLog($log);
 }
Example #17
0
 /**
  * @param      $fields
  * @param      $data
  * @param null $owner
  * @param null $list
  * @param null $tags
  * @param bool $persist Persist to the database; otherwise return entity
  *
  * @return bool
  * @throws \Doctrine\ORM\ORMException
  * @throws \Swift_RfcComplianceException
  */
 public function importLead($fields, $data, $owner = null, $list = null, $tags = null, $persist = true)
 {
     // Let's check for an existing lead by email
     $hasEmail = !empty($fields['email']) && !empty($data[$fields['email']]);
     if ($hasEmail) {
         // Validate the email
         MailHelper::validateEmail($data[$fields['email']]);
         $leadFound = $this->getRepository()->getLeadByEmail($data[$fields['email']]);
         $lead = $leadFound ? $this->em->getReference('MauticLeadBundle:Lead', $leadFound['id']) : new Lead();
         $merged = $leadFound;
     } else {
         $lead = new Lead();
         $merged = false;
     }
     if (!empty($fields['dateAdded']) && !empty($data[$fields['dateAdded']])) {
         $dateAdded = new DateTimeHelper($data[$fields['dateAdded']]);
         $lead->setDateAdded($dateAdded->getUtcDateTime());
     }
     unset($fields['dateAdded']);
     if (!empty($fields['dateModified']) && !empty($data[$fields['dateModified']])) {
         $dateModified = new DateTimeHelper($data[$fields['dateModified']]);
         $lead->setDateModified($dateModified->getUtcDateTime());
     }
     unset($fields['dateModified']);
     if (!empty($fields['lastActive']) && !empty($data[$fields['lastActive']])) {
         $lastActive = new DateTimeHelper($data[$fields['lastActive']]);
         $lead->setLastActive($lastActive->getUtcDateTime());
     }
     unset($fields['lastActive']);
     if (!empty($fields['dateIdentified']) && !empty($data[$fields['dateIdentified']])) {
         $dateIdentified = new DateTimeHelper($data[$fields['dateIdentified']]);
         $lead->setDateIdentified($dateIdentified->getUtcDateTime());
     }
     unset($fields['dateIdentified']);
     if (!empty($fields['createdByUser']) && !empty($data[$fields['createdByUser']])) {
         $userRepo = $this->em->getRepository('MauticUserBundle:User');
         $createdByUser = $userRepo->findByIdentifier($data[$fields['createdByUser']]);
         if ($createdByUser !== null) {
             $lead->setCreatedBy($createdByUser);
         }
     }
     unset($fields['createdByUser']);
     if (!empty($fields['modifiedByUser']) && !empty($data[$fields['modifiedByUser']])) {
         $userRepo = $this->em->getRepository('MauticUserBundle:User');
         $modifiedByUser = $userRepo->findByIdentifier($data[$fields['modifiedByUser']]);
         if ($modifiedByUser !== null) {
             $lead->setModifiedBy($modifiedByUser);
         }
     }
     unset($fields['modifiedByUser']);
     if (!empty($fields['ip']) && !empty($data[$fields['ip']])) {
         $addresses = explode(',', $data[$fields['ip']]);
         foreach ($addresses as $address) {
             $ipAddress = new IpAddress();
             $ipAddress->setIpAddress(trim($address));
             $lead->addIpAddress($ipAddress);
         }
     }
     unset($fields['ip']);
     if (!empty($fields['points']) && !empty($data[$fields['points']]) && $lead->getId() === null) {
         // Add points only for new leads
         $lead->setPoints($data[$fields['points']]);
         //add a lead point change log
         $log = new PointsChangeLog();
         $log->setDelta($data[$fields['points']]);
         $log->setLead($lead);
         $log->setType('lead');
         $log->setEventName($this->translator->trans('mautic.lead.import.event.name'));
         $log->setActionName($this->translator->trans('mautic.lead.import.action.name', array('%name%' => $this->user->getUsername())));
         $log->setIpAddress($this->ipLookupHelper->getIpAddress());
         $log->setDateAdded(new \DateTime());
         $lead->addPointsChangeLog($log);
     }
     if (!empty($fields['stage']) && !empty($data[$fields['stage']])) {
         static $stages = [];
         $stageName = $data[$fields['stage']];
         if (!array_key_exists($stageName, $stages)) {
             // Set stage for contact
             $stage = $this->em->getRepository('MauticStageBundle:Stage')->getStageByName($stageName);
             if (empty($stage)) {
                 $stage = new Stage();
                 $stage->setName($stageName);
                 $stages[$stageName] = $stage;
             }
         } else {
             $stage = $stages[$stageName];
         }
         $lead->setStage($stage);
         //add a contact stage change log
         $log = new StagesChangeLog();
         $log->setEventName($stage->getId() . ":" . $stage->getName());
         $log->setLead($lead);
         $log->setActionName($this->translator->trans('mautic.lead.import.action.name', ['%name%' => $this->user->getUsername()]));
         $log->setDateAdded(new \DateTime());
         $lead->stageChangeLog($log);
     }
     unset($fields['stage']);
     // Set unsubscribe status
     if (!empty($fields['doNotEmail']) && !empty($data[$fields['doNotEmail']]) && $hasEmail) {
         $doNotEmail = filter_var($data[$fields['doNotEmail']], FILTER_VALIDATE_BOOLEAN);
         if ($doNotEmail) {
             $reason = $this->translator->trans('mautic.lead.import.by.user', array("%user%" => $this->user->getUsername()));
             // The email must be set for successful unsubscribtion
             $lead->addUpdatedField('email', $data[$fields['email']]);
             $this->addDncForLead($lead, 'email', $reason, DoNotContact::MANUAL);
         }
     }
     unset($fields['doNotEmail']);
     if ($owner !== null) {
         $lead->setOwner($this->em->getReference('MauticUserBundle:User', $owner));
     }
     if ($tags !== null) {
         $this->modifyTags($lead, $tags, null, false);
     }
     // Set profile data using the form so that values are validated
     $fieldData = [];
     foreach ($fields as $leadField => $importField) {
         // Prevent overwriting existing data with empty data
         if (array_key_exists($importField, $data) && !is_null($data[$importField]) && $data[$importField] != '') {
             $fieldData[$leadField] = $data[$importField];
         }
     }
     static $leadFields;
     if (null === $leadFields) {
         $leadFields = $this->leadFieldModel->getEntities(array('force' => array(array('column' => 'f.isPublished', 'expr' => 'eq', 'value' => true)), 'hydration_mode' => 'HYDRATE_ARRAY'));
     }
     $form = $this->createForm($lead, $this->formFactory, null, ['fields' => $leadFields, 'csrf_protection' => false]);
     // Unset stage and owner from the form because it's already been handled
     unset($form['stage'], $form['owner']);
     $form->submit($fieldData);
     if (!$form->isValid()) {
         $fieldErrors = [];
         foreach ($form as $formField) {
             $errors = $formField->getErrors(true);
             if (count($errors)) {
                 $errorString = $formField->getConfig()->getOption('label') . ": ";
                 foreach ($errors as $error) {
                     $errorString .= " {$error->getMessage()}";
                 }
                 $fieldErrors[] = $errorString;
             }
         }
         $fieldErrors = implode("\n", $fieldErrors);
         throw new \Exception($fieldErrors);
     } else {
         // All clear
         foreach ($fieldData as $field => $value) {
             $lead->addUpdatedField($field, $value);
         }
     }
     $lead->imported = true;
     if ($persist) {
         $this->saveEntity($lead);
         if ($list !== null) {
             $this->addToLists($lead, array($list));
         }
     }
     return $merged;
 }
Example #18
0
 /**
  * @param string|Stat $stat
  * @param             $request
  * @param bool        $viaBrowser
  */
 public function hitEmail($stat, $request, $viaBrowser = false)
 {
     if (!$stat instanceof Stat) {
         $stat = $this->getEmailStatus($stat);
     }
     if (!$stat) {
         return;
     }
     $email = $stat->getEmail();
     if ((int) $stat->isRead()) {
         if ($viaBrowser && !$stat->getViewedInBrowser()) {
             //opened via browser so note it
             $stat->setViewedInBrowser($viaBrowser);
         }
     }
     $readDateTime = new DateTimeHelper();
     $stat->setLastOpened($readDateTime->getDateTime());
     $lead = $stat->getLead();
     if ($lead !== null) {
         // Set the lead as current lead
         $this->leadModel->setCurrentLead($lead);
     }
     $firstTime = false;
     if (!$stat->getIsRead()) {
         $firstTime = true;
         $stat->setIsRead(true);
         $stat->setDateRead($readDateTime->getDateTime());
         // Only up counts if associated with both an email and lead
         if ($email && $lead) {
             try {
                 $this->getRepository()->upCount($email->getId(), 'read', 1, $email->isVariant());
             } catch (\Exception $exception) {
                 error_log($exception);
             }
         }
     }
     if ($viaBrowser) {
         $stat->setViewedInBrowser($viaBrowser);
     }
     $stat->addOpenDetails(['datetime' => $readDateTime->toUtcString(), 'useragent' => $request->server->get('HTTP_USER_AGENT'), 'inBrowser' => $viaBrowser]);
     //check for existing IP
     $ipAddress = $this->ipLookupHelper->getIpAddress();
     $stat->setIpAddress($ipAddress);
     if ($this->dispatcher->hasListeners(EmailEvents::EMAIL_ON_OPEN)) {
         $event = new EmailOpenEvent($stat, $request, $firstTime);
         $this->dispatcher->dispatch(EmailEvents::EMAIL_ON_OPEN, $event);
     }
     //device granularity
     $dd = new DeviceDetector($request->server->get('HTTP_USER_AGENT'));
     $dd->parse();
     $deviceRepo = $this->leadModel->getDeviceRepository();
     $emailOpenDevice = $deviceRepo->getDevice(null, $lead, $dd->getDeviceName(), $dd->getBrand(), $dd->getModel());
     if (empty($emailOpenDevice)) {
         $emailOpenDevice = new LeadDevice();
         $emailOpenDevice->setClientInfo($dd->getClient());
         $emailOpenDevice->setDevice($dd->getDeviceName());
         $emailOpenDevice->setDeviceBrand($dd->getBrand());
         $emailOpenDevice->setDeviceModel($dd->getModel());
         $emailOpenDevice->setDeviceOs($dd->getOs());
         $emailOpenDevice->setDateOpen($readDateTime->toUtcString());
         $emailOpenDevice->setLead($lead);
         try {
             $this->em->persist($emailOpenDevice);
             $this->em->flush($emailOpenDevice);
         } catch (\Exception $exception) {
             if (MAUTIC_ENV === 'dev') {
                 throw $exception;
             } else {
                 $this->logger->addError($exception->getMessage(), ['exception' => $exception]);
             }
         }
     } else {
         $emailOpenDevice = $deviceRepo->getEntity($emailOpenDevice['id']);
     }
     if ($email) {
         $this->em->persist($email);
         $this->em->flush($email);
     }
     if (isset($emailOpenDevice) and is_object($emailOpenDevice)) {
         $emailOpenStat = new StatDevice();
         $emailOpenStat->setIpAddress($ipAddress);
         $emailOpenStat->setDevice($emailOpenDevice);
         $emailOpenStat->setDateOpened($readDateTime->toUtcString());
         $emailOpenStat->setStat($stat);
         $this->em->persist($emailOpenStat);
         $this->em->flush($emailOpenStat);
     }
     $this->em->persist($stat);
     $this->em->flush();
 }
Example #19
0
 /**
  * @param Request $request
  * @param string  $code
  *
  * @throws \Doctrine\ORM\ORMException
  * @throws \Exception
  */
 public function hitVideo($request, $code = '200')
 {
     //don't skew results with in-house hits
     if (!$this->security->isAnonymous()) {
         //return;
     }
     $lead = $this->leadModel->getCurrentLead();
     $guid = $request->get('guid');
     $hit = $this->getHitForLeadByGuid($lead, $guid);
     $hit->setGuid($guid);
     $hit->setDateHit(new \Datetime());
     $hit->setDuration($request->get('duration'));
     $hit->setUrl($request->get('url'));
     $hit->setTimeWatched($request->get('total_watched'));
     //check for existing IP
     $ipAddress = $this->ipLookupHelper->getIpAddress();
     $hit->setIpAddress($ipAddress);
     // Store query array
     $query = $request->query->all();
     unset($query['d']);
     $hit->setQuery($query);
     $hit->setLead($lead);
     //glean info from the IP address
     if ($details = $ipAddress->getIpDetails()) {
         $hit->setCountry($details['country']);
         $hit->setRegion($details['region']);
         $hit->setCity($details['city']);
         $hit->setIsp($details['isp']);
         $hit->setOrganization($details['organization']);
     }
     $hit->setCode($code);
     if (!$hit->getReferer()) {
         $hit->setReferer($request->server->get('HTTP_REFERER'));
     }
     $hit->setUserAgent($request->server->get('HTTP_USER_AGENT'));
     $hit->setRemoteHost($request->server->get('REMOTE_HOST'));
     //get a list of the languages the user prefers
     $browserLanguages = $request->server->get('HTTP_ACCEPT_LANGUAGE');
     if (!empty($browserLanguages)) {
         $languages = explode(',', $browserLanguages);
         foreach ($languages as $k => $l) {
             if ($pos = strpos(';q=', $l) !== false) {
                 //remove weights
                 $languages[$k] = substr($l, 0, $pos);
             }
         }
         $hit->setBrowserLanguages($languages);
     }
     // Wrap in a try/catch to prevent deadlock errors on busy servers
     try {
         $this->em->persist($hit);
         $this->em->flush($hit);
     } catch (\Exception $exception) {
         if (MAUTIC_ENV === 'dev') {
             throw $exception;
         } else {
             $this->logger->addError($exception->getMessage(), ['exception' => $exception]);
         }
     }
     if ($this->dispatcher->hasListeners(PageEvents::VIDEO_ON_HIT)) {
         $event = new VideoHitEvent($hit, $request, $code);
         $this->dispatcher->dispatch(PageEvents::VIDEO_ON_HIT, $event);
     }
 }
Example #20
0
 /**
  * Add a delete entry to the audit log.
  *
  * @param Events\EmailEvent $event
  */
 public function onEmailDelete(Events\EmailEvent $event)
 {
     $email = $event->getEmail();
     $log = ['bundle' => 'email', 'object' => 'email', 'objectId' => $email->deletedId, 'action' => 'delete', 'details' => ['name' => $email->getName()], 'ipAddress' => $this->ipLookupHelper->getIpAddressFromRequest()];
     $this->auditLogModel->writeToLog($log);
 }
Example #21
0
 /**
  * Add a delete entry to the audit log.
  *
  * @param Events\CategoryEvent $event
  */
 public function onCategoryDelete(Events\CategoryEvent $event)
 {
     $category = $event->getCategory();
     $log = ['bundle' => 'category', 'object' => 'category', 'objectId' => $category->deletedId, 'action' => 'delete', 'details' => ['name' => $category->getTitle()], 'ipAddress' => $this->ipLookupHelper->getIpAddressFromRequest()];
     $this->auditLogModel->writeToLog($log);
 }
Example #22
0
 /**
  * Add a delete entry to the audit log.
  *
  * @param Events\FormEvent $event
  */
 public function onFormDelete(Events\FormEvent $event)
 {
     $form = $event->getForm();
     $log = ['bundle' => 'form', 'object' => 'form', 'objectId' => $form->deletedId, 'action' => 'delete', 'details' => ['name' => $form->getName()], 'ipAddress' => $this->ipLookupHelper->getIpAddressFromRequest()];
     $this->auditLogModel->writeToLog($log);
 }
Example #23
0
 /**
  * Add a delete entry to the audit log.
  *
  * @param FocusEvent $event
  */
 public function onFocusDelete(FocusEvent $event)
 {
     $entity = $event->getFocus();
     $log = ['bundle' => 'focus', 'object' => 'focus', 'objectId' => $entity->deletedId, 'action' => 'delete', 'details' => ['name' => $entity->getName()], 'ipAddress' => $this->ipHelper->getIpAddressFromRequest()];
     $this->auditLogModel->writeToLog($log);
 }