forked from vergnet/site-accueil-insa
223 lines
8.2 KiB
PHP
223 lines
8.2 KiB
PHP
<?php
|
|
/**
|
|
* Matomo - free/libre analytics platform
|
|
*
|
|
* @link https://matomo.org
|
|
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
|
*/
|
|
|
|
namespace Piwik\Plugins\CustomDimensions\Tracker;
|
|
|
|
use Piwik\Common;
|
|
use Piwik\Plugins\CustomDimensions\CustomDimensions;
|
|
use Piwik\Plugins\CustomDimensions\Dao;
|
|
use Piwik\Plugins\CustomDimensions\Dimension\Extraction;
|
|
use Piwik\Tracker\Action;
|
|
use Piwik\Tracker\Cache;
|
|
use Piwik\Tracker\Model;
|
|
use Piwik\Tracker\Request;
|
|
use Piwik\Tracker\RequestProcessor;
|
|
use Piwik\Tracker\Visit\VisitProperties;
|
|
|
|
/**
|
|
* Handles tracking of custom dimensions
|
|
*/
|
|
class CustomDimensionsRequestProcessor extends RequestProcessor
|
|
{
|
|
|
|
public function recordLogs(VisitProperties $visitProperties, Request $request)
|
|
{
|
|
if (!self::hasActionCustomDimensionConfiguredInSite($request)) {
|
|
return;
|
|
}
|
|
|
|
$model = new Model();
|
|
|
|
/** @var Action $action */
|
|
$action = $request->getMetadata('Actions', 'action');
|
|
|
|
if (!empty($action) && $request->getMetadata('CoreHome', 'isNewVisit')) {
|
|
// this logic is only for new visits because we have to create the visit to get an idvisit before we can insert
|
|
// the action and only then we can update the last_idink_va of the previously on the visit from the previously created actions.
|
|
// so flow is:
|
|
// * Create visit -> creates idVisit A
|
|
// * Create link visit action (requires idvisit) -> creates idlink_va B
|
|
// * Update visit A and set the idlink_va B
|
|
$idLinkVisit = $action->getIdLinkVisitAction();
|
|
$idVisit = $visitProperties->getProperty('idvisit');
|
|
$model->updateVisit($request->getIdSite(), $idVisit, array('last_idlink_va' => $idLinkVisit));
|
|
}
|
|
|
|
$lastIdLinkVa = $visitProperties->getProperty('last_idlink_va');
|
|
$previousIdLinkVa = $request->getMetadata('CustomDimensions', 'previous_idlink_va');
|
|
if ($previousIdLinkVa) {
|
|
// when last_idlink_va was already updated in this visit because it was existing visit... we need to get the idlink_va from previous tracking request
|
|
// it's actually not needed to store previous_idlink_va in metadata currently but figured it be better just in case the logic changes in the future
|
|
// to prevent updating the wrong idlink_va
|
|
$lastIdLinkVa = $previousIdLinkVa;
|
|
}
|
|
$timeSpent = $visitProperties->getProperty('time_spent_ref_action');
|
|
|
|
if (!empty($lastIdLinkVa) && $timeSpent > 0) {
|
|
// here we don't update the action that was created in this request but the action of the previous tracking request
|
|
// we can only know how much time was spent on the previous action when the next action is recorded.
|
|
$model->updateAction($lastIdLinkVa, array('time_spent' => $timeSpent));
|
|
}
|
|
}
|
|
|
|
public static function hasActionCustomDimensionConfiguredInSite($request)
|
|
{
|
|
$dimensions = self::getCachedCustomDimensions($request);
|
|
if (empty($dimensions)) {
|
|
return false;
|
|
}
|
|
foreach ($dimensions as $dimension) {
|
|
if ($dimension['scope'] == CustomDimensions::SCOPE_ACTION) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public function onNewVisit(VisitProperties $visitProperties, Request $request)
|
|
{
|
|
$dimensionsToSet = $this->getCustomDimensionsInScope(CustomDimensions::SCOPE_VISIT, $request);
|
|
|
|
foreach ($dimensionsToSet as $field => $value) {
|
|
$visitProperties->setProperty($field, $value);
|
|
}
|
|
}
|
|
|
|
public function onExistingVisit(&$valuesToUpdate, VisitProperties $visitProperties, Request $request)
|
|
{
|
|
$dimensionsToSet = $this->getCustomDimensionsInScope(CustomDimensions::SCOPE_VISIT, $request);
|
|
|
|
foreach ($dimensionsToSet as $field => $value) {
|
|
$valuesToUpdate[$field] = $value;
|
|
$visitProperties->setProperty($field, $value);
|
|
}
|
|
|
|
$action = $request->getMetadata('Actions', 'action');
|
|
/** @var Action $action */
|
|
if (!empty($action) && $action->getIdLinkVisitAction() && self::hasActionCustomDimensionConfiguredInSite($request)) {
|
|
// when it is an existing visit, then we first create the action before recording the visit. This allows us
|
|
// to update last_idlink_va in the regular visit update
|
|
$request->setMetadata('CustomDimensions','previous_idlink_va', $visitProperties->getProperty('last_idlink_va'));
|
|
$valuesToUpdate['last_idlink_va'] = $action->getIdLinkVisitAction();
|
|
}
|
|
}
|
|
|
|
public function afterRequestProcessed(VisitProperties $visitProperties, Request $request)
|
|
{
|
|
$action = $request->getMetadata('Actions', 'action');
|
|
|
|
if (empty($action) || !($action instanceof Action)) {
|
|
return;
|
|
}
|
|
|
|
$dimensionsToSet = $this->getCustomDimensionsInScope(CustomDimensions::SCOPE_ACTION, $request);
|
|
|
|
foreach ($dimensionsToSet as $field => $value) {
|
|
$action->setCustomField($field, $value);
|
|
}
|
|
}
|
|
|
|
private function getCustomDimensionsInScope($scope, Request $request)
|
|
{
|
|
$dimensions = self::getCachedCustomDimensions($request);
|
|
$params = $request->getParams();
|
|
|
|
$values = array();
|
|
|
|
foreach ($dimensions as $dimension) {
|
|
if ($dimension['scope'] !== $scope) {
|
|
continue;
|
|
}
|
|
|
|
$field = self::buildCustomDimensionTrackingApiName($dimension);
|
|
$dbField = Dao\LogTable::buildCustomDimensionColumnName($dimension);
|
|
|
|
$value = Common::getRequestVar($field, '', 'string', $params);
|
|
$hasSentEmptyString = isset($params[$field]) && $params[$field] === '';
|
|
if ($value !== '' || $hasSentEmptyString) {
|
|
$values[$dbField] = self::prepareValue($value);
|
|
continue;
|
|
}
|
|
|
|
$extractions = $dimension['extractions'];
|
|
if (is_array($extractions)) {
|
|
foreach ($extractions as $extraction) {
|
|
if (!array_key_exists('dimension', $extraction)
|
|
|| !array_key_exists('pattern', $extraction)
|
|
|| empty($extraction['pattern'])) {
|
|
continue;
|
|
}
|
|
|
|
$extraction = new Extraction($extraction['dimension'], $extraction['pattern']);
|
|
$extraction->setCaseSensitive($dimension['case_sensitive']);
|
|
$value = $extraction->extract($request);
|
|
|
|
if (!isset($value) || '' === $value) {
|
|
continue;
|
|
}
|
|
|
|
$values[$dbField] = self::prepareValue(urldecode($value));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $values;
|
|
}
|
|
|
|
private static function prepareValue($value)
|
|
{
|
|
return mb_substr(trim($value), 0, 250);
|
|
}
|
|
|
|
public static function buildCustomDimensionTrackingApiName($idDimensionOrDimension)
|
|
{
|
|
if (is_array($idDimensionOrDimension) && isset($idDimensionOrDimension['idcustomdimension'])) {
|
|
$idDimensionOrDimension = $idDimensionOrDimension['idcustomdimension'];
|
|
}
|
|
|
|
$idDimensionOrDimension = (int) $idDimensionOrDimension;
|
|
|
|
if ($idDimensionOrDimension >= 1) {
|
|
return 'dimension' . (int) $idDimensionOrDimension;
|
|
}
|
|
}
|
|
|
|
public static function getCachedCustomDimensionIndexes($scope)
|
|
{
|
|
$cache = Cache::getCacheGeneral();
|
|
$key = 'custom_dimension_indexes_installed_' . $scope;
|
|
|
|
if (empty($cache[$key])) {
|
|
return array();
|
|
}
|
|
|
|
return $cache[$key];
|
|
}
|
|
|
|
/**
|
|
* Get Cached Custom Dimensions during tracking. Returns only active custom dimensions.
|
|
*
|
|
* @param Request $request
|
|
* @return array
|
|
* @throws \Piwik\Exception\UnexpectedWebsiteFoundException
|
|
*/
|
|
public static function getCachedCustomDimensions(Request $request)
|
|
{
|
|
$idSite = $request->getIdSite();
|
|
$cache = Cache::getCacheWebsiteAttributes($idSite);
|
|
|
|
if (empty($cache['custom_dimensions'])) {
|
|
// no custom dimensions set
|
|
return array();
|
|
}
|
|
|
|
return $cache['custom_dimensions'];
|
|
}
|
|
|
|
}
|