Newer
Older
<?php
/**
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
namespace Piwik\Plugins\CoreHome\Tracker;
diosmosis
a validé
use Piwik\Common;
use Piwik\Date;
use Piwik\EventDispatcher;
diosmosis
a validé
use Piwik\Exception\UnexpectedWebsiteFoundException;
use Piwik\Tracker\Cache;
use Piwik\Tracker\Request;
use Piwik\Tracker\RequestProcessor;
diosmosis
a validé
use Piwik\Tracker\Settings;
use Piwik\Tracker\Visit\VisitProperties;
use Piwik\Tracker\VisitExcluded;
diosmosis
a validé
use Piwik\Tracker\VisitorRecognizer;
/**
* Encapsulates core tracking logic related to visits.
* ## Request Metadata
*
* This RequestProcessor exposes the following metadata for the **CoreHome** plugin:
*
* * **visitorId**: A hash that identifies the current visitor being tracked. This value is
* calculated using the Piwik\Tracker\Settings;:getConfigId() method.
*
* Set in `processRequestParams()`.
*
* * **isVisitorKnown**: True if the current visitor has visited the site before. False if
* otherwise.
*
* Set in `processRequestParams()`.
*
* * **isNewVisit**: True if the current action is the start of a new visit, false if it
* is part of an ongoing visit.
*
* Set in `processRequestParams()`. Other RequestProcessors can override
* this value to force a new visit or stop a new visit.
*
* * **visitorNotFoundInDb**: True if the current visit could not be updated.
*
* Set by the Visit object.
*/
class VisitRequestProcessor extends RequestProcessor
{
// TODO: much of the logic in this class should be moved to new service class
/**
* @var EventDispatcher
*/
private $eventDispatcher;
diosmosis
a validé
/**
* @var VisitorRecognizer
*/
private $visitorRecognizer;
/**
* @var Settings
*/
private $userSettings;
/**
* @var int
*/
private $visitStandardLength;
public function __construct(EventDispatcher $eventDispatcher, VisitorRecognizer $visitorRecognizer, Settings $userSettings,
$visitStandardLength)
{
$this->eventDispatcher = $eventDispatcher;
diosmosis
a validé
$this->visitorRecognizer = $visitorRecognizer;
$this->userSettings = $userSettings;
$this->visitStandardLength = $visitStandardLength;
}
public function processRequestParams(VisitProperties $visitProperties, Request $request)
{
// the IP is needed by isExcluded() and GoalManager->recordGoals()
diosmosis
a validé
$visitProperties->setProperty('location_ip', $request->getIp());
diosmosis
a validé
// TODO: move VisitExcluded logic to here (or move to service class stored in DI)
diosmosis
a validé
$excluded = new VisitExcluded($request, $visitProperties->getProperty('location_ip'));
if ($excluded->isExcluded()) {
return true;
}
diosmosis
a validé
// visitor recognition
diosmosis
a validé
$visitorId = $this->userSettings->getConfigId($request, $visitProperties->getProperty('location_ip'));
$request->setMetadata('CoreHome', 'visitorId', $visitorId);
diosmosis
a validé
$isKnown = $this->visitorRecognizer->findKnownVisitor($visitorId, $visitProperties, $request);
$request->setMetadata('CoreHome', 'isVisitorKnown', $isKnown);
diosmosis
a validé
$isNewVisit = $this->isVisitNew($visitProperties, $request);
$request->setMetadata('CoreHome', 'isNewVisit', $isNewVisit);
diosmosis
a validé
return false;
}
public function afterRequestProcessed(VisitProperties $visitProperties, Request $request)
{
diosmosis
a validé
$ip = $visitProperties->getProperty('location_ip');
/**
* Triggered after visits are tested for exclusion so plugins can modify the IP address
* persisted with a visit.
*
* This event is primarily used by the **PrivacyManager** plugin to anonymize IP addresses.
*
* @param string &$ip The visitor's IP address.
*/
diosmosis
a validé
$this->eventDispatcher->postEvent('Tracker.setVisitorIp', array(&$ip));
$visitProperties->setProperty('location_ip', $ip);
}
diosmosis
a validé
/**
* Determines if the tracker if the current action should be treated as the start of a new visit or
* an action in an existing visit.
*
* Note: public only for tests.
*
diosmosis
a validé
* @param VisitProperties $visitProperties The current visit/visitor information.
* @param Request $request
* @return bool
*/
public function isVisitNew(VisitProperties $visitProperties, Request $request)
diosmosis
a validé
{
$isKnown = $request->getMetadata('CoreHome', 'isVisitorKnown');
diosmosis
a validé
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
if (!$isKnown) {
return true;
}
$isLastActionInTheSameVisit = $this->isLastActionInTheSameVisit($visitProperties, $request);
if (!$isLastActionInTheSameVisit) {
Common::printDebug("Visitor detected, but last action was more than 30 minutes ago...");
return true;
}
$wasLastActionYesterday = $this->wasLastActionNotToday($visitProperties, $request);
if ($wasLastActionYesterday) {
Common::printDebug("Visitor detected, but last action was yesterday...");
return true;
}
return false;
}
/**
* Returns true if the last action was done during the last 30 minutes
* @return bool
*/
protected function isLastActionInTheSameVisit(VisitProperties $visitProperties, Request $request)
{
diosmosis
a validé
$lastActionTime = $visitProperties->getProperty('visit_last_action_time');
diosmosis
a validé
return isset($lastActionTime)
&& false !== $lastActionTime
diosmosis
a validé
&& ($lastActionTime > ($request->getCurrentTimestamp() - $this->visitStandardLength));
diosmosis
a validé
}
/**
* Returns true if the last action was not today.
* @param VisitProperties $visitor
* @return bool
*/
private function wasLastActionNotToday(VisitProperties $visitProperties, Request $request)
{
diosmosis
a validé
$lastActionTime = $visitProperties->getProperty('visit_last_action_time');
diosmosis
a validé
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
if (empty($lastActionTime)) {
return false;
}
$idSite = $request->getIdSite();
$timezone = $this->getTimezoneForSite($idSite);
if (empty($timezone)) {
throw new UnexpectedWebsiteFoundException('An unexpected website was found, check idSite in the request');
}
$date = Date::factory((int)$lastActionTime, $timezone);
$now = $request->getCurrentTimestamp();
$now = Date::factory((int)$now, $timezone);
return $date->toString() !== $now->toString();
}
private function getTimezoneForSite($idSite) // TODO: duplicate function in Visit
{
try {
$site = Cache::getCacheWebsiteAttributes($idSite);
} catch (UnexpectedWebsiteFoundException $e) {
return null;
}
if (!empty($site['timezone'])) {
return $site['timezone'];
}
return null;
}