/** * {@inheritDoc} */ public function setSource($source) { $this->__initializer__ && $this->__initializer__->__invoke($this, 'setSource', array($source)); return parent::setSource($source); }
/** * @param Page $page * @param Request $request * @param string $code * * @return void */ public function hitPage($page, $request, $code = '200') { //don't skew results with in-house hits if (!$this->factory->getSecurity()->isAnonymous()) { return; } $hitRepo = $this->getHitRepository(); $hit = new Hit(); $hit->setDateHit(new \Datetime()); //check for existing IP $ipAddress = $this->factory->getIpAddress(); $hit->setIpAddress($ipAddress); /** @var \Mautic\LeadBundle\Model\LeadModel $leadModel */ $leadModel = $this->factory->getModel('lead'); //check for any clickthrough info $clickthrough = $request->get('ct', array()); if (!empty($clickthrough)) { $clickthrough = $this->decodeArrayFromUrl($clickthrough); if (!empty($clickthrough['lead'])) { $lead = $leadModel->getEntity($clickthrough['lead']); if ($lead !== null) { $leadModel->setLeadCookie($clickthrough['lead']); $leadClickthrough = true; $leadModel->setCurrentLead($lead); } } if (!empty($clickthrough['source'])) { $hit->setSource($clickthrough['source'][0]); $hit->setSourceId($clickthrough['source'][1]); } if (!empty($clickthrough['email'])) { $hit->setEmail($this->em->getReference('MauticEmailBundle:Email', $clickthrough['email'])); } } if (empty($leadClickthrough)) { $lead = $leadModel->getCurrentLead(); } if ($page instanceof Redirect) { //use the configured redirect URL $pageURL = $page->getUrl(); } else { //use current URL // Tracking pixel is used if (strpos($request->server->get('REQUEST_URI'), '/mtracking.gif') !== false) { $pageURL = $request->server->get('HTTP_REFERER'); // if additional data were sent with the tracking pixel if ($request->server->get('QUERY_STRING')) { parse_str($request->server->get('QUERY_STRING'), $query); // URL attr 'd' is encoded so let's decode it first. $decoded = false; if (isset($query['d'])) { // parse_str auto urldecodes $query = unserialize(base64_decode($query['d'])); $decoded = true; } if (!empty($query)) { if (isset($query['page_url'])) { $pageURL = $query['page_url']; if (!$decoded) { $pageURL = urldecode($pageURL); } } elseif (isset($query['url'])) { $pageURL = $query['url']; if (!$decoded) { $pageURL = urldecode($pageURL); } } if (isset($query['page_referrer'])) { if (!$decoded) { $query['page_referrer'] = urldecode($query['page_referrer']); } $hit->setReferer($query['page_referrer']); } elseif (isset($query['referrer'])) { if (!$decoded) { $query['referrer'] = urldecode($query['referrer']); } $hit->setReferer($query['referrer']); } if (isset($query['page_language'])) { if (!$decoded) { $query['page_language'] = urldecode($query['page_language']); } $hit->setPageLanguage($query['page_language']); } elseif (isset($query['language'])) { if (!$decoded) { $query['language'] = urldecode($query['language']); } $hit->setPageLanguage($query['language']); } if (isset($query['page_title'])) { if (!$decoded) { $query['page_title'] = urldecode($query['page_title']); } $hit->setUrlTitle($query['page_title']); } elseif (isset($query['title'])) { if (!$decoded) { $query['title'] = urldecode($query['title']); } $hit->setUrlTitle($query['title']); } // Update lead fields if some data were sent in the URL query /** @var \Mautic\LeadBundle\Model\FieldModel $leadFieldModel */ $leadFieldModel = $this->factory->getModel('lead.field'); $availableLeadFields = $leadFieldModel->getFieldList(false, false, array('isPublished' => true, 'isPubliclyUpdatable' => true)); $uniqueLeadFields = $this->factory->getModel('lead.field')->getUniqueIdentiferFields(); $uniqueLeadFieldData = array(); $inQuery = array_intersect_key($query, $availableLeadFields); foreach ($inQuery as $k => $v) { if (empty($query[$k])) { unset($inQuery[$k]); } if (array_key_exists($k, $uniqueLeadFields)) { $uniqueLeadFieldData[$k] = $v; } } $persistLead = false; if (count($inQuery)) { if (count($uniqueLeadFieldData)) { $existingLeads = $this->em->getRepository('MauticLeadBundle:Lead')->getLeadsByUniqueFields($uniqueLeadFieldData, $lead->getId()); if (!empty($existingLeads)) { $lead = $leadModel->mergeLeads($lead, $existingLeads[0]); } $leadIpAddresses = $lead->getIpAddresses(); if (!$leadIpAddresses->contains($ipAddress)) { $lead->addIpAddress($ipAddress); } $leadModel->setCurrentLead($lead); } $leadModel->setFieldValues($lead, $inQuery); $persistLead = true; } if (isset($query['tags'])) { if (!$decoded) { $query['tags'] = urldecode($query['tags']); } $leadTags = $lead->getTags(); $tags = explode(',', $query['tags']); array_walk($tags, create_function('&$val', '$val = trim($val); \\Mautic\\CoreBundle\\Helper\\InputHelper::clean($val);')); // See which tags already exist $foundTags = $leadModel->getTagRepository()->getTagsByName($tags); foreach ($tags as $tag) { if (strpos($tag, '-') === 0) { // Tag to be removed $tag = substr($tag, 1); if (array_key_exists($tag, $foundTags) && $leadTags->contains($foundTags[$tag])) { $lead->removeTag($foundTags[$tag]); $persistLead = true; } } else { // Tag to be added if (!array_key_exists($tag, $foundTags)) { // New tag $newTag = new Tag(); $newTag->setTag($tag); $lead->addTag($newTag); $persistLead = true; } elseif (!$leadTags->contains($foundTags[$tag])) { $lead->addTag($foundTags[$tag]); $persistLead = true; } } } } if ($persistLead) { $leadModel->saveEntity($lead); } } } } else { $pageURL = 'http'; if ($request->server->get('HTTPS') == 'on') { $pageURL .= 's'; } $pageURL .= '://'; if ($request->server->get('SERVER_PORT') != '80') { $pageURL .= $request->server->get('SERVER_NAME') . ':' . $request->server->get('SERVER_PORT') . $request->server->get('REQUEST_URI'); } else { $pageURL .= $request->server->get('SERVER_NAME') . $request->server->get('REQUEST_URI'); } } } $hit->setUrl($pageURL); // Store query array $query = $request->query->all(); unset($query['d']); $hit->setQuery($query); list($trackingId, $generated) = $leadModel->getTrackingCookie(); $hit->setTrackingId($trackingId); $hit->setLead($lead); if (!$generated) { $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); } } if (!empty($page)) { //check for a hit from tracking id $countById = $hitRepo->getHitCountForTrackingId($page, $trackingId); $isUnique = empty($countById); 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) { error_log($exception); } } elseif ($page instanceof Redirect) { $hit->setRedirect($page); /** @var \Mautic\PageBundle\Model\RedirectModel $redirectModel */ $redirectModel = $this->factory->getModel('page.redirect'); try { $redirectModel->getRepository()->upHitCount($page->getId(), 1, $isUnique); } catch (\Exception $exception) { error_log($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')); //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); } $this->em->persist($hit); // Wrap in a try/catch to prevent deadlock errors on busy servers try { $this->em->flush(); } catch (\Exception $e) { error_log($e); } if ($this->dispatcher->hasListeners(PageEvents::PAGE_ON_HIT)) { $event = new PageHitEvent($hit, $request, $code, $clickthrough); $this->dispatcher->dispatch(PageEvents::PAGE_ON_HIT, $event); } //save hit to the cookie to use to update the exit time $this->factory->getHelper('cookie')->setCookie('mautic_referer_id', $hit->getId()); }
/** * 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; }