From d995029b91f38bd81fbbb50f4d058f3b6b3c18a2 Mon Sep 17 00:00:00 2001 From: Thomas Steur Date: Wed, 4 Nov 2015 02:30:26 +0000 Subject: refs #9129 added feature Custom Dimensions --- core/API/DataTableManipulator.php | 10 ++++- core/API/DocumentationGenerator.php | 1 + core/DataArray.php | 74 +++++++++++++++++++++++++++---------- core/Plugin/Manager.php | 13 +++++-- core/Plugin/RequestProcessors.php | 3 +- core/Plugin/Visualization.php | 13 ++++++- core/Tracker/Action.php | 19 ++++++---- core/Tracker/Model.php | 32 +++++++++++++++- core/ViewDataTable/Config.php | 35 +++++++++++++++++- 9 files changed, 163 insertions(+), 37 deletions(-) (limited to 'core') diff --git a/core/API/DataTableManipulator.php b/core/API/DataTableManipulator.php index 76c52f4958..d084d6d156 100644 --- a/core/API/DataTableManipulator.php +++ b/core/API/DataTableManipulator.php @@ -152,7 +152,15 @@ abstract class DataTableManipulator $idSite = 'all'; } - $meta = API::getInstance()->getMetadata($idSite, $this->apiModule, $this->apiMethod); + $apiParameters = array(); + if (!empty($request['idDimension'])) { + $apiParameters['idDimension'] = $request['idDimension']; + } + if (!empty($request['idGoal'])) { + $apiParameters['idGoal'] = $request['idGoal']; + } + + $meta = API::getInstance()->getMetadata($idSite, $this->apiModule, $this->apiMethod, $apiParameters); if (empty($meta)) { throw new Exception(sprintf( diff --git a/core/API/DocumentationGenerator.php b/core/API/DocumentationGenerator.php index 64c25bf9b0..60807267df 100644 --- a/core/API/DocumentationGenerator.php +++ b/core/API/DocumentationGenerator.php @@ -291,6 +291,7 @@ class DocumentationGenerator $aParameters['disable_queued_filters'] = false; $aParameters['disable_generic_filters'] = false; $aParameters['expanded'] = false; + $aParameters['idDimenson'] = false; $moduleName = Proxy::getInstance()->getModuleNameFromClassName($class); $aParameters = array_merge(array('module' => 'API', 'method' => $moduleName . '.' . $methodName), $aParameters); diff --git a/core/DataArray.php b/core/DataArray.php index 386eae29a3..1be1942312 100644 --- a/core/DataArray.php +++ b/core/DataArray.php @@ -47,7 +47,7 @@ class DataArray public function sumMetricsVisits($label, $row) { if (!isset($this->data[$label])) { - $this->data[$label] = self::makeEmptyRow(); + $this->data[$label] = static::makeEmptyRow(); } $this->doSumVisitsMetrics($row, $this->data[$label]); } @@ -80,7 +80,7 @@ class DataArray * * @return void */ - protected function doSumVisitsMetrics($newRowToAdd, &$oldRowToUpdate, $onlyMetricsAvailableInActionsTable = false) + protected function doSumVisitsMetrics($newRowToAdd, &$oldRowToUpdate) { // Pre 1.2 format: string indexed rows are returned from the DB // Left here for Backward compatibility with plugins doing custom SQL queries using these metrics as string @@ -88,9 +88,6 @@ class DataArray $oldRowToUpdate[Metrics::INDEX_NB_VISITS] += $newRowToAdd['nb_visits']; $oldRowToUpdate[Metrics::INDEX_NB_ACTIONS] += $newRowToAdd['nb_actions']; $oldRowToUpdate[Metrics::INDEX_NB_UNIQ_VISITORS] += $newRowToAdd['nb_uniq_visitors']; - if ($onlyMetricsAvailableInActionsTable) { - return; - } $oldRowToUpdate[Metrics::INDEX_NB_USERS] += $newRowToAdd['nb_users']; $oldRowToUpdate[Metrics::INDEX_MAX_ACTIONS] = (float)max($newRowToAdd['max_actions'], $oldRowToUpdate[Metrics::INDEX_MAX_ACTIONS]); $oldRowToUpdate[Metrics::INDEX_SUM_VISIT_LENGTH] += $newRowToAdd['sum_visit_length']; @@ -107,9 +104,6 @@ class DataArray $oldRowToUpdate[Metrics::INDEX_NB_VISITS] += $newRowToAdd[Metrics::INDEX_NB_VISITS]; $oldRowToUpdate[Metrics::INDEX_NB_ACTIONS] += $newRowToAdd[Metrics::INDEX_NB_ACTIONS]; $oldRowToUpdate[Metrics::INDEX_NB_UNIQ_VISITORS] += $newRowToAdd[Metrics::INDEX_NB_UNIQ_VISITORS]; - if ($onlyMetricsAvailableInActionsTable) { - return; - } // In case the existing Row had no action metrics (eg. Custom Variable XYZ with "visit" scope) // but the new Row has action metrics (eg. same Custom Variable XYZ this time with a "page" scope) @@ -133,11 +127,50 @@ class DataArray $oldRowToUpdate[Metrics::INDEX_NB_VISITS_CONVERTED] += $newRowToAdd[Metrics::INDEX_NB_VISITS_CONVERTED]; } + /** + * Adds the given row $newRowToAdd to the existing $oldRowToUpdate passed by reference + * The rows are php arrays Name => value + * + * @param array $newRowToAdd + * @param array $oldRowToUpdate + * @param bool $onlyMetricsAvailableInActionsTable + * + * @return void + */ + protected function doSumActionsMetrics($newRowToAdd, &$oldRowToUpdate) + { + // Pre 1.2 format: string indexed rows are returned from the DB + // Left here for Backward compatibility with plugins doing custom SQL queries using these metrics as string + if (!isset($newRowToAdd[Metrics::INDEX_NB_VISITS])) { + $oldRowToUpdate[Metrics::INDEX_NB_VISITS] += $newRowToAdd['nb_visits']; + $oldRowToUpdate[Metrics::INDEX_NB_ACTIONS] += $newRowToAdd['nb_actions']; + $oldRowToUpdate[Metrics::INDEX_NB_UNIQ_VISITORS] += $newRowToAdd['nb_uniq_visitors']; + return; + } + + // Edge case fail safe + if (!isset($oldRowToUpdate[Metrics::INDEX_NB_VISITS])) { + return; + } + + $oldRowToUpdate[Metrics::INDEX_NB_VISITS] += $newRowToAdd[Metrics::INDEX_NB_VISITS]; + if (array_key_exists(Metrics::INDEX_NB_ACTIONS, $newRowToAdd)) { + $oldRowToUpdate[Metrics::INDEX_NB_ACTIONS] += $newRowToAdd[Metrics::INDEX_NB_ACTIONS]; + } + if (array_key_exists(Metrics::INDEX_PAGE_NB_HITS, $newRowToAdd)) { + if (!array_key_exists(Metrics::INDEX_PAGE_NB_HITS, $oldRowToUpdate)) { + $oldRowToUpdate[Metrics::INDEX_PAGE_NB_HITS] = 0; + } + $oldRowToUpdate[Metrics::INDEX_PAGE_NB_HITS] += $newRowToAdd[Metrics::INDEX_PAGE_NB_HITS]; + } + $oldRowToUpdate[Metrics::INDEX_NB_UNIQ_VISITORS] += $newRowToAdd[Metrics::INDEX_NB_UNIQ_VISITORS]; + } + public function sumMetricsGoals($label, $row) { $idGoal = $row['idgoal']; if (!isset($this->data[$label][Metrics::INDEX_GOALS][$idGoal])) { - $this->data[$label][Metrics::INDEX_GOALS][$idGoal] = self::makeEmptyGoalRow($idGoal); + $this->data[$label][Metrics::INDEX_GOALS][$idGoal] = static::makeEmptyGoalRow($idGoal); } $this->doSumGoalsMetrics($row, $this->data[$label][Metrics::INDEX_GOALS][$idGoal]); } @@ -201,9 +234,10 @@ class DataArray public function sumMetricsActions($label, $row) { if (!isset($this->data[$label])) { - $this->data[$label] = self::makeEmptyActionRow(); + $this->data[$label] = static::makeEmptyActionRow(); } - $this->doSumVisitsMetrics($row, $this->data[$label], $onlyMetricsAvailableInActionsTable = true); + + $this->doSumActionsMetrics($row, $this->data[$label]); } protected static function makeEmptyActionRow() @@ -218,7 +252,7 @@ class DataArray public function sumMetricsEvents($label, $row) { if (!isset($this->data[$label])) { - $this->data[$label] = self::makeEmptyEventRow(); + $this->data[$label] = static::makeEmptyEventRow(); } $this->doSumEventsMetrics($row, $this->data[$label], $onlyMetricsAvailableInActionsTable = true); } @@ -250,16 +284,16 @@ class DataArray $oldRowToUpdate[Metrics::INDEX_EVENT_NB_HITS] += $newRowToAdd[Metrics::INDEX_EVENT_NB_HITS]; $oldRowToUpdate[Metrics::INDEX_EVENT_NB_HITS_WITH_VALUE] += $newRowToAdd[Metrics::INDEX_EVENT_NB_HITS_WITH_VALUE]; - $newRowToAdd[Metrics::INDEX_EVENT_SUM_EVENT_VALUE] = round($newRowToAdd[Metrics::INDEX_EVENT_SUM_EVENT_VALUE], self::EVENT_VALUE_PRECISION); + $newRowToAdd[Metrics::INDEX_EVENT_SUM_EVENT_VALUE] = round($newRowToAdd[Metrics::INDEX_EVENT_SUM_EVENT_VALUE], static::EVENT_VALUE_PRECISION); $oldRowToUpdate[Metrics::INDEX_EVENT_SUM_EVENT_VALUE] += $newRowToAdd[Metrics::INDEX_EVENT_SUM_EVENT_VALUE]; - $oldRowToUpdate[Metrics::INDEX_EVENT_MAX_EVENT_VALUE] = round(max($newRowToAdd[Metrics::INDEX_EVENT_MAX_EVENT_VALUE], $oldRowToUpdate[Metrics::INDEX_EVENT_MAX_EVENT_VALUE]), self::EVENT_VALUE_PRECISION); + $oldRowToUpdate[Metrics::INDEX_EVENT_MAX_EVENT_VALUE] = round(max($newRowToAdd[Metrics::INDEX_EVENT_MAX_EVENT_VALUE], $oldRowToUpdate[Metrics::INDEX_EVENT_MAX_EVENT_VALUE]), static::EVENT_VALUE_PRECISION); // Update minimum only if it is set if ($newRowToAdd[Metrics::INDEX_EVENT_MIN_EVENT_VALUE] !== false) { if ($oldRowToUpdate[Metrics::INDEX_EVENT_MIN_EVENT_VALUE] === false) { - $oldRowToUpdate[Metrics::INDEX_EVENT_MIN_EVENT_VALUE] = round($newRowToAdd[Metrics::INDEX_EVENT_MIN_EVENT_VALUE], self::EVENT_VALUE_PRECISION); + $oldRowToUpdate[Metrics::INDEX_EVENT_MIN_EVENT_VALUE] = round($newRowToAdd[Metrics::INDEX_EVENT_MIN_EVENT_VALUE], static::EVENT_VALUE_PRECISION); } else { - $oldRowToUpdate[Metrics::INDEX_EVENT_MIN_EVENT_VALUE] = round(min($newRowToAdd[Metrics::INDEX_EVENT_MIN_EVENT_VALUE], $oldRowToUpdate[Metrics::INDEX_EVENT_MIN_EVENT_VALUE]), self::EVENT_VALUE_PRECISION); + $oldRowToUpdate[Metrics::INDEX_EVENT_MIN_EVENT_VALUE] = round(min($newRowToAdd[Metrics::INDEX_EVENT_MIN_EVENT_VALUE], $oldRowToUpdate[Metrics::INDEX_EVENT_MIN_EVENT_VALUE]), static::EVENT_VALUE_PRECISION); } } } @@ -290,7 +324,7 @@ class DataArray public function sumMetricsVisitsPivot($parentLabel, $label, $row) { if (!isset($this->dataTwoLevels[$parentLabel][$label])) { - $this->dataTwoLevels[$parentLabel][$label] = self::makeEmptyRow(); + $this->dataTwoLevels[$parentLabel][$label] = static::makeEmptyRow(); } $this->doSumVisitsMetrics($row, $this->dataTwoLevels[$parentLabel][$label]); } @@ -299,7 +333,7 @@ class DataArray { $idGoal = $row['idgoal']; if (!isset($this->dataTwoLevels[$parentLabel][$label][Metrics::INDEX_GOALS][$idGoal])) { - $this->dataTwoLevels[$parentLabel][$label][Metrics::INDEX_GOALS][$idGoal] = self::makeEmptyGoalRow($idGoal); + $this->dataTwoLevels[$parentLabel][$label][Metrics::INDEX_GOALS][$idGoal] = static::makeEmptyGoalRow($idGoal); } $this->doSumGoalsMetrics($row, $this->dataTwoLevels[$parentLabel][$label][Metrics::INDEX_GOALS][$idGoal]); } @@ -309,7 +343,7 @@ class DataArray if (!isset($this->dataTwoLevels[$parentLabel][$label])) { $this->dataTwoLevels[$parentLabel][$label] = $this->makeEmptyActionRow(); } - $this->doSumVisitsMetrics($row, $this->dataTwoLevels[$parentLabel][$label], $onlyMetricsAvailableInActionsTable = true); + $this->doSumActionsMetrics($row, $this->dataTwoLevels[$parentLabel][$label]); } public function sumMetricsEventsPivot($parentLabel, $label, $row) @@ -382,7 +416,7 @@ class DataArray */ public static function isRowActions($row) { - return (count($row) == count(self::makeEmptyActionRow())) && isset($row[Metrics::INDEX_NB_ACTIONS]); + return (count($row) == count(static::makeEmptyActionRow())) && isset($row[Metrics::INDEX_NB_ACTIONS]); } /** diff --git a/core/Plugin/Manager.php b/core/Plugin/Manager.php index 150151ee3e..c3974937a0 100644 --- a/core/Plugin/Manager.php +++ b/core/Plugin/Manager.php @@ -1070,11 +1070,20 @@ class Manager if ($saveConfig) { PiwikConfig::getInstance()->forceSave(); + $this->clearCache($pluginName); } } public function isTrackerPlugin(Plugin $plugin) { + if (!$this->isPluginInstalled($plugin->getPluginName())) { + return false; + } + + if ($plugin->isTrackerPlugin()) { + return true; + } + $dimensions = VisitDimension::getDimensions($plugin); if (!empty($dimensions)) { return true; @@ -1101,10 +1110,6 @@ class Manager return true; } - if ($plugin->isTrackerPlugin()) { - return true; - } - return false; } diff --git a/core/Plugin/RequestProcessors.php b/core/Plugin/RequestProcessors.php index ef69eb59d5..827274485e 100644 --- a/core/Plugin/RequestProcessors.php +++ b/core/Plugin/RequestProcessors.php @@ -14,7 +14,8 @@ class RequestProcessors { public function getRequestProcessors() { - $processors = Manager::getInstance()->findMultipleComponents('Tracker', 'Piwik\\Tracker\\RequestProcessor'); + $manager = Manager::getInstance(); + $processors = $manager->findMultipleComponents('Tracker', 'Piwik\\Tracker\\RequestProcessor'); $instances = array(); foreach ($processors as $processor) { diff --git a/core/Plugin/Visualization.php b/core/Plugin/Visualization.php index 8a35a971b2..fcd8891280 100644 --- a/core/Plugin/Visualization.php +++ b/core/Plugin/Visualization.php @@ -272,7 +272,18 @@ class Visualization extends ViewDataTable $idSite = Common::getRequestVar('idSite', null, 'string', $request); $module = $this->requestConfig->getApiModuleToRequest(); $action = $this->requestConfig->getApiMethodToRequest(); - $metadata = ApiApi::getInstance()->getMetadata($idSite, $module, $action); + + $apiParameters = array(); + $idDimension = Common::getRequestVar('idDimension', 0, 'int'); + $idGoal = Common::getRequestVar('idGoal', 0, 'int'); + if ($idDimension > 0) { + $apiParameters['idDimension'] = $idDimension; + } + if ($idGoal > 0) { + $apiParameters['idGoal'] = $idGoal; + } + + $metadata = ApiApi::getInstance()->getMetadata($idSite, $module, $action, $apiParameters); if (!empty($metadata)) { return array_shift($metadata); diff --git a/core/Tracker/Action.php b/core/Tracker/Action.php index b30d695e73..b841c210a9 100644 --- a/core/Tracker/Action.php +++ b/core/Tracker/Action.php @@ -62,6 +62,7 @@ abstract class Action private $idLinkVisitAction; private $actionIdsCached = array(); + private $customFields = array(); private $actionName; private $actionType; @@ -228,6 +229,16 @@ abstract class Action return false; } + public function setCustomField($field, $value) + { + $this->customFields[$field] = $value; + } + + public function getCustomFields() + { + return $this->customFields; + } + public function getIdActionUrl() { $idUrl = $this->actionIdsCached['idaction_url']; @@ -379,13 +390,7 @@ abstract class Action $visitAction[self::DB_COLUMN_CUSTOM_FLOAT] = Common::forceDotAsSeparatorForDecimalPoint($customValue); } - $customVariables = $this->getCustomVariables(); - if (!empty($customVariables)) { - Common::printDebug("Page level Custom Variables: "); - Common::printDebug($customVariables); - } - - $visitAction = array_merge($visitAction, $customVariables); + $visitAction = array_merge($visitAction, $this->customFields); $this->idLinkVisitAction = $this->getModel()->createAction($visitAction); diff --git a/core/Tracker/Model.php b/core/Tracker/Model.php index c39820e571..afffd5faeb 100644 --- a/core/Tracker/Model.php +++ b/core/Tracker/Model.php @@ -289,7 +289,7 @@ class Model public function updateVisit($idSite, $idVisit, $valuesToUpdate) { - list($updateParts, $sqlBind) = $this->visitFieldsToQuery($valuesToUpdate); + list($updateParts, $sqlBind) = $this->fieldsToQuery($valuesToUpdate); $parts = implode($updateParts, ', '); $table = Common::prefixTable('log_visit'); @@ -312,6 +312,34 @@ class Model return $wasInserted; } + public function updateAction($idLinkVa, $valuesToUpdate) + { + if (empty($idLinkVa)) { + return; + } + + list($updateParts, $sqlBind) = $this->fieldsToQuery($valuesToUpdate); + + $parts = implode($updateParts, ', '); + $table = Common::prefixTable('log_link_visit_action'); + + $sqlQuery = "UPDATE $table SET $parts WHERE idlink_va = ?"; + + $sqlBind[] = $idLinkVa; + + $db = $this->getDb(); + $result = $db->query($sqlQuery, $sqlBind); + $wasInserted = $db->rowCount($result) != 0; + + if (!$wasInserted) { + Common::printDebug("Action with this idLinkVa wasn't found in the DB."); + Common::printDebug("$sqlQuery --- "); + Common::printDebug($sqlBind); + } + + return $wasInserted; + } + public function findVisitor($idSite, $configId, $idVisitor, $fieldsToRead, $shouldMatchOneFieldOnly, $isVisitorIdToLookup, $timeLookBack, $timeLookAhead) { $selectCustomVariables = ''; @@ -396,7 +424,7 @@ class Model return $result == null; } - private function visitFieldsToQuery($valuesToUpdate) + private function fieldsToQuery($valuesToUpdate) { $updateParts = array(); $sqlBind = array(); diff --git a/core/ViewDataTable/Config.php b/core/ViewDataTable/Config.php index e856473d46..bd73ea846a 100644 --- a/core/ViewDataTable/Config.php +++ b/core/ViewDataTable/Config.php @@ -10,6 +10,7 @@ namespace Piwik\ViewDataTable; use Piwik\API\Request as ApiRequest; +use Piwik\Common; use Piwik\DataTable; use Piwik\DataTable\Filter\PivotByDimension; use Piwik\Metrics; @@ -486,7 +487,28 @@ class Config { $this->metrics_documentation = array(); - $report = API::getInstance()->getMetadata(0, $this->controllerName, $this->controllerAction); + $idSite = Common::getRequestVar('idSite', 0, 'int'); + + if ($idSite < 1) { + return; + } + + $apiParameters = array(); + $idDimension = Common::getRequestVar('idDimension', 0, 'int'); + $idGoal = Common::getRequestVar('idGoal', 0, 'int'); + if ($idDimension > 0) { + $apiParameters['idDimension'] = $idDimension; + } + if ($idGoal > 0) { + $apiParameters['idGoal'] = $idGoal; + } + + $report = API::getInstance()->getMetadata($idSite, $this->controllerName, $this->controllerAction, $apiParameters); + + if (empty($report)) { + return; + } + $report = $report[0]; if (isset($report['metricsDocumentation'])) { @@ -556,6 +578,17 @@ class Config $this->columns_to_display = array_filter($columnsToDisplay); } + public function removeColumnToDisplay($columnToRemove) + { + if (!empty($this->columns_to_display)) { + + $key = array_search($columnToRemove, $this->columns_to_display); + if (false !== $key) { + unset($this->columns_to_display[$key]); + } + } + } + /** * @ignore */ -- cgit v1.2.3