diff --git a/core/Metrics/Formatter.php b/core/Metrics/Formatter.php index 5d9eb73a35daefbd4a51ac7072617fa1dc80b256..bdf920e6a0f96d6b92c372bd2b2ce15dabaf0c46 100644 --- a/core/Metrics/Formatter.php +++ b/core/Metrics/Formatter.php @@ -134,10 +134,15 @@ class Formatter } $units = array('B', 'K', 'M', 'G', 'T'); + $numUnits = count($units) - 1; $currentUnit = null; foreach ($units as $idx => $currentUnit) { - if ($size >= 1024 && $unit != $currentUnit && $idx != count($units) - 1) { + if ($unit && $unit !== $currentUnit) { + $size = $size / 1024; + } elseif ($unit && $unit === $currentUnit) { + break; + } elseif ($size >= 1024 && $idx != $numUnits) { $size = $size / 1024; } else { break; diff --git a/plugins/Actions/API.php b/plugins/Actions/API.php index 37a38153944f3f9789e4f3260add3b8c16e28f95..2f0b8f5f9da2a79fb268816dfe2e94e2726e93dc 100644 --- a/plugins/Actions/API.php +++ b/plugins/Actions/API.php @@ -14,7 +14,7 @@ use Piwik\Archive; use Piwik\Common; use Piwik\DataTable; use Piwik\Date; -use Piwik\Metrics; +use Piwik\Metrics as PiwikMetrics; use Piwik\Piwik; use Piwik\Plugin\Report; use Piwik\Plugins\Actions\Columns\Metrics\AveragePageGenerationTime; @@ -247,7 +247,7 @@ class API extends \Piwik\Plugin\API public function getSiteSearchKeywords($idSite, $period, $date, $segment = false) { $dataTable = $this->getSiteSearchKeywordsRaw($idSite, $period, $date, $segment); - $dataTable->deleteColumn(Metrics::INDEX_SITE_SEARCH_HAS_NO_RESULT); + $dataTable->deleteColumn(PiwikMetrics::INDEX_SITE_SEARCH_HAS_NO_RESULT); $this->filterActionsDataTable($dataTable); $this->addPagesPerSearchColumn($dataTable); return $dataTable; @@ -276,13 +276,13 @@ class API extends \Piwik\Plugin\API // Delete all rows that have some results $dataTable->filter('ColumnCallbackDeleteRow', array( - Metrics::INDEX_SITE_SEARCH_HAS_NO_RESULT, + PiwikMetrics::INDEX_SITE_SEARCH_HAS_NO_RESULT, function ($value) { return $value < 1; } )); $dataTable->deleteRow(DataTable::ID_SUMMARY_ROW); - $dataTable->deleteColumn(Metrics::INDEX_SITE_SEARCH_HAS_NO_RESULT); + $dataTable->deleteColumn(PiwikMetrics::INDEX_SITE_SEARCH_HAS_NO_RESULT); $this->filterActionsDataTable($dataTable); $this->addPagesPerSearchColumn($dataTable); return $dataTable; diff --git a/plugins/Actions/Archiver.php b/plugins/Actions/Archiver.php index 199438445e829cf53fcc9a2b2bcf43f1afab44de..639ee81c5004a32650abf5426974dfe19505d14f 100644 --- a/plugins/Actions/Archiver.php +++ b/plugins/Actions/Archiver.php @@ -9,7 +9,7 @@ namespace Piwik\Plugins\Actions; use Piwik\DataTable; -use Piwik\Metrics; +use Piwik\Metrics as PiwikMetrics; use Piwik\RankingQuery; use Piwik\Tracker\Action; use Piwik\Plugins\Actions\Actions\ActionSiteSearch; @@ -37,39 +37,6 @@ class Archiver extends \Piwik\Plugin\Archiver const METRIC_SEARCHES_RECORD_NAME = 'Actions_nb_searches'; const METRIC_KEYWORDS_RECORD_NAME = 'Actions_nb_keywords'; - /* Metrics in use by the API Actions.get */ - public static $actionsAggregateMetrics = array( - self::METRIC_PAGEVIEWS_RECORD_NAME => 'nb_pageviews', - self::METRIC_UNIQ_PAGEVIEWS_RECORD_NAME => 'nb_uniq_pageviews', - self::METRIC_DOWNLOADS_RECORD_NAME => 'nb_downloads', - self::METRIC_UNIQ_DOWNLOADS_RECORD_NAME => 'nb_uniq_downloads', - self::METRIC_OUTLINKS_RECORD_NAME => 'nb_outlinks', - self::METRIC_UNIQ_OUTLINKS_RECORD_NAME => 'nb_uniq_outlinks', - self::METRIC_SEARCHES_RECORD_NAME => 'nb_searches', - self::METRIC_KEYWORDS_RECORD_NAME => 'nb_keywords', - ); - - public static $actionTypes = array( - Action::TYPE_PAGE_URL, - Action::TYPE_OUTLINK, - Action::TYPE_DOWNLOAD, - Action::TYPE_PAGE_TITLE, - Action::TYPE_SITE_SEARCH, - ); - protected static $columnsToRenameAfterAggregation = array( - Metrics::INDEX_NB_UNIQ_VISITORS => Metrics::INDEX_SUM_DAILY_NB_UNIQ_VISITORS, - Metrics::INDEX_PAGE_ENTRY_NB_UNIQ_VISITORS => Metrics::INDEX_PAGE_ENTRY_SUM_DAILY_NB_UNIQ_VISITORS, - Metrics::INDEX_PAGE_EXIT_NB_UNIQ_VISITORS => Metrics::INDEX_PAGE_EXIT_SUM_DAILY_NB_UNIQ_VISITORS, - ); - public static $columnsToDeleteAfterAggregation = array( - Metrics::INDEX_NB_UNIQ_VISITORS, - Metrics::INDEX_PAGE_ENTRY_NB_UNIQ_VISITORS, - Metrics::INDEX_PAGE_EXIT_NB_UNIQ_VISITORS, - ); - private static $columnsAggregationOperation = array( - Metrics::INDEX_PAGE_MAX_TIME_GENERATION => 'max', - Metrics::INDEX_PAGE_MIN_TIME_GENERATION => 'min' - ); protected $actionsTablesByType = null; protected $isSiteSearchEnabled = false; @@ -133,10 +100,10 @@ class Archiver extends \Piwik\Plugin\Archiver protected function updateQuerySelectFromForSiteSearch(&$select, &$from) { $selectFlagNoResultKeywords = ", - CASE WHEN (MAX(log_link_visit_action.custom_var_v" . ActionSiteSearch::CVAR_INDEX_SEARCH_COUNT . ") = 0 - AND log_link_visit_action.custom_var_k" . ActionSiteSearch::CVAR_INDEX_SEARCH_COUNT . " = '" . ActionSiteSearch::CVAR_KEY_SEARCH_COUNT . "') - THEN 1 ELSE 0 END - AS `" . Metrics::INDEX_SITE_SEARCH_HAS_NO_RESULT . "`"; + CASE WHEN (MAX(log_link_visit_action.custom_var_v" . ActionSiteSearch::CVAR_INDEX_SEARCH_COUNT . ") = 0 + AND log_link_visit_action.custom_var_k" . ActionSiteSearch::CVAR_INDEX_SEARCH_COUNT . " = '" . ActionSiteSearch::CVAR_KEY_SEARCH_COUNT . "') + THEN 1 ELSE 0 END + AS `" . PiwikMetrics::INDEX_SITE_SEARCH_HAS_NO_RESULT . "`"; //we need an extra JOIN to know whether the referrer "idaction_name_ref" was a Site Search request $from[] = array( @@ -146,9 +113,9 @@ class Archiver extends \Piwik\Plugin\Archiver ); $selectPageIsFollowingSiteSearch = ", - SUM( CASE WHEN log_action_name_ref.type = " . Action::TYPE_SITE_SEARCH . " - THEN 1 ELSE 0 END) - AS `" . Metrics::INDEX_PAGE_IS_FOLLOWING_SITE_SEARCH_NB_HITS . "`"; + SUM( CASE WHEN log_action_name_ref.type = " . Action::TYPE_SITE_SEARCH . " + THEN 1 ELSE 0 END) + AS `" . PiwikMetrics::INDEX_PAGE_IS_FOLLOWING_SITE_SEARCH_NB_HITS . "`"; $select .= $selectFlagNoResultKeywords . $selectPageIsFollowingSiteSearch; @@ -160,7 +127,7 @@ class Archiver extends \Piwik\Plugin\Archiver private function initActionsTables() { $this->actionsTablesByType = array(); - foreach (self::$actionTypes as $type) { + foreach (Metrics::$actionTypes as $type) { $dataTable = new DataTable(); $dataTable->setMaximumAllowedRows(ArchivingHelper::$maximumRowsInDataTableLevelZero); @@ -168,7 +135,7 @@ class Archiver extends \Piwik\Plugin\Archiver || $type == Action::TYPE_PAGE_TITLE ) { // for page urls and page titles, performance metrics exist and have to be aggregated correctly - $dataTable->setMetadata(DataTable::COLUMN_AGGREGATION_OPS_METADATA_NAME, self::$columnsAggregationOperation); + $dataTable->setMetadata(DataTable::COLUMN_AGGREGATION_OPS_METADATA_NAME, Metrics::$columnsAggregationOperation); } $this->actionsTablesByType[$type] = $dataTable; @@ -177,30 +144,17 @@ class Archiver extends \Piwik\Plugin\Archiver protected function archiveDayActions($rankingQueryLimit) { + $metricsConfig = Metrics::getActionMetrics(); + $select = "log_action.name, - log_action.type, - log_action.idaction, - log_action.url_prefix, - count(distinct log_link_visit_action.idvisit) as `" . Metrics::INDEX_NB_VISITS . "`, - count(distinct log_link_visit_action.idvisitor) as `" . Metrics::INDEX_NB_UNIQ_VISITORS . "`, - count(*) as `" . Metrics::INDEX_PAGE_NB_HITS . "`, - sum( - case when " . Action::DB_COLUMN_CUSTOM_FLOAT . " is null - then 0 - else " . Action::DB_COLUMN_CUSTOM_FLOAT . " - end - ) / 1000 as `" . Metrics::INDEX_PAGE_SUM_TIME_GENERATION . "`, - sum( - case when " . Action::DB_COLUMN_CUSTOM_FLOAT . " is null - then 0 - else 1 - end - ) as `" . Metrics::INDEX_PAGE_NB_HITS_WITH_TIME_GENERATION . "`, - min(" . Action::DB_COLUMN_CUSTOM_FLOAT . ") / 1000 - as `" . Metrics::INDEX_PAGE_MIN_TIME_GENERATION . "`, - max(" . Action::DB_COLUMN_CUSTOM_FLOAT . ") / 1000 - as `" . Metrics::INDEX_PAGE_MAX_TIME_GENERATION . "` - "; + log_action.type, + log_action.idaction, + log_action.url_prefix, + count(distinct log_link_visit_action.idvisit) as `" . PiwikMetrics::INDEX_NB_VISITS . "`, + count(distinct log_link_visit_action.idvisitor) as `" . PiwikMetrics::INDEX_NB_UNIQ_VISITORS . "`, + count(*) as `" . PiwikMetrics::INDEX_PAGE_NB_HITS . "`"; + + $select = $this->addMetricsToSelect($select, $metricsConfig); $from = array( "log_link_visit_action", @@ -211,29 +165,29 @@ class Archiver extends \Piwik\Plugin\Archiver ); $where = "log_link_visit_action.server_time >= ? - AND log_link_visit_action.server_time <= ? - AND log_link_visit_action.idsite = ? - AND log_link_visit_action.%s IS NOT NULL" + AND log_link_visit_action.server_time <= ? + AND log_link_visit_action.idsite = ? + AND log_link_visit_action.%s IS NOT NULL" . $this->getWhereClauseActionIsNotEvent(); $groupBy = "log_action.idaction"; - $orderBy = "`" . Metrics::INDEX_PAGE_NB_HITS . "` DESC, name ASC"; + $orderBy = "`" . PiwikMetrics::INDEX_PAGE_NB_HITS . "` DESC, name ASC"; $rankingQuery = false; if ($rankingQueryLimit > 0) { $rankingQuery = new RankingQuery($rankingQueryLimit); $rankingQuery->setOthersLabel(DataTable::LABEL_SUMMARY_ROW); $rankingQuery->addLabelColumn(array('idaction', 'name')); - $rankingQuery->addColumn(array('url_prefix', Metrics::INDEX_NB_UNIQ_VISITORS)); - $rankingQuery->addColumn(array(Metrics::INDEX_PAGE_NB_HITS, Metrics::INDEX_NB_VISITS), 'sum'); + $rankingQuery->addColumn(array('url_prefix', PiwikMetrics::INDEX_NB_UNIQ_VISITORS)); + $rankingQuery->addColumn(array(PiwikMetrics::INDEX_PAGE_NB_HITS, PiwikMetrics::INDEX_NB_VISITS), 'sum'); + if ($this->isSiteSearchEnabled()) { - $rankingQuery->addColumn(Metrics::INDEX_SITE_SEARCH_HAS_NO_RESULT, 'min'); - $rankingQuery->addColumn(Metrics::INDEX_PAGE_IS_FOLLOWING_SITE_SEARCH_NB_HITS, 'sum'); + $rankingQuery->addColumn(PiwikMetrics::INDEX_SITE_SEARCH_HAS_NO_RESULT, 'min'); + $rankingQuery->addColumn(PiwikMetrics::INDEX_PAGE_IS_FOLLOWING_SITE_SEARCH_NB_HITS, 'sum'); } - $rankingQuery->addColumn(Metrics::INDEX_PAGE_SUM_TIME_GENERATION, 'sum'); - $rankingQuery->addColumn(Metrics::INDEX_PAGE_NB_HITS_WITH_TIME_GENERATION, 'sum'); - $rankingQuery->addColumn(Metrics::INDEX_PAGE_MIN_TIME_GENERATION, 'min'); - $rankingQuery->addColumn(Metrics::INDEX_PAGE_MAX_TIME_GENERATION, 'max'); + + $this->addMetricsToRankingQuery($rankingQuery, $metricsConfig); + $rankingQuery->partitionResultIntoMultipleGroups('type', array_keys($this->actionsTablesByType)); } @@ -244,9 +198,30 @@ class Archiver extends \Piwik\Plugin\Archiver $this->updateQuerySelectFromForSiteSearch($select, $from); } - $this->archiveDayQueryProcess($select, $from, $where, $groupBy, $orderBy, "idaction_name", $rankingQuery); + $this->archiveDayQueryProcess($select, $from, $where, $groupBy, $orderBy, "idaction_name", $rankingQuery, $metricsConfig); + $this->archiveDayQueryProcess($select, $from, $where, $groupBy, $orderBy, "idaction_url", $rankingQuery, $metricsConfig); + } - $this->archiveDayQueryProcess($select, $from, $where, $groupBy, $orderBy, "idaction_url", $rankingQuery); + private function addMetricsToSelect($select, $metricsConfig) + { + if (!empty($metricsConfig)) { + foreach ($metricsConfig as $metric => $config) { + $select .= ', ' . $config['query'] . " as `" . $metric . "`"; + } + } + + return $select; + } + + private function addMetricsToRankingQuery(RankingQuery $rankingQuery, $metricsConfig) + { + foreach ($metricsConfig as $metric => $config) { + if (!empty($config['aggregation'])) { + $rankingQuery->addColumn($metric, $config['aggregation']); + } else { + $rankingQuery->addColumn($metric); + } + } } protected function isSiteSearchEnabled() @@ -254,7 +229,7 @@ class Archiver extends \Piwik\Plugin\Archiver return $this->isSiteSearchEnabled; } - protected function archiveDayQueryProcess($select, $from, $where, $groupBy, $orderBy, $sprintfField, RankingQuery $rankingQuery = null) + protected function archiveDayQueryProcess($select, $from, $where, $groupBy, $orderBy, $sprintfField, RankingQuery $rankingQuery = null, $metricsConfig = array()) { $select = sprintf($select, $sprintfField); @@ -271,7 +246,7 @@ class Archiver extends \Piwik\Plugin\Archiver // get result $resultSet = $this->getLogAggregator()->getDb()->query($querySql, $query['bind']); - $modified = ArchivingHelper::updateActionsTableWithRowQuery($resultSet, $sprintfField, $this->actionsTablesByType); + $modified = ArchivingHelper::updateActionsTableWithRowQuery($resultSet, $sprintfField, $this->actionsTablesByType, $metricsConfig); return $modified; } @@ -285,11 +260,11 @@ class Archiver extends \Piwik\Plugin\Archiver $rankingQuery = new RankingQuery($rankingQueryLimit); $rankingQuery->setOthersLabel(DataTable::LABEL_SUMMARY_ROW); $rankingQuery->addLabelColumn('idaction'); - $rankingQuery->addColumn(Metrics::INDEX_PAGE_ENTRY_NB_UNIQ_VISITORS); - $rankingQuery->addColumn(array(Metrics::INDEX_PAGE_ENTRY_NB_VISITS, - Metrics::INDEX_PAGE_ENTRY_NB_ACTIONS, - Metrics::INDEX_PAGE_ENTRY_SUM_VISIT_LENGTH, - Metrics::INDEX_PAGE_ENTRY_BOUNCE_COUNT), 'sum'); + $rankingQuery->addColumn(PiwikMetrics::INDEX_PAGE_ENTRY_NB_UNIQ_VISITORS); + $rankingQuery->addColumn(array(PiwikMetrics::INDEX_PAGE_ENTRY_NB_VISITS, + PiwikMetrics::INDEX_PAGE_ENTRY_NB_ACTIONS, + PiwikMetrics::INDEX_PAGE_ENTRY_SUM_VISIT_LENGTH, + PiwikMetrics::INDEX_PAGE_ENTRY_BOUNCE_COUNT), 'sum'); $rankingQuery->partitionResultIntoMultipleGroups('type', array_keys($this->actionsTablesByType)); $extraSelects = 'log_action.type, log_action.name,'; @@ -300,7 +275,7 @@ class Archiver extends \Piwik\Plugin\Archiver "joinOn" => "log_visit.%s = log_action.idaction" ) ); - $orderBy = "`" . Metrics::INDEX_PAGE_ENTRY_NB_ACTIONS . "` DESC, log_action.name ASC"; + $orderBy = "`" . PiwikMetrics::INDEX_PAGE_ENTRY_NB_ACTIONS . "` DESC, log_action.name ASC"; } else { $extraSelects = false; $from = "log_visit"; @@ -308,16 +283,16 @@ class Archiver extends \Piwik\Plugin\Archiver } $select = "log_visit.%s as idaction, $extraSelects - count(distinct log_visit.idvisitor) as `" . Metrics::INDEX_PAGE_ENTRY_NB_UNIQ_VISITORS . "`, - count(*) as `" . Metrics::INDEX_PAGE_ENTRY_NB_VISITS . "`, - sum(log_visit.visit_total_actions) as `" . Metrics::INDEX_PAGE_ENTRY_NB_ACTIONS . "`, - sum(log_visit.visit_total_time) as `" . Metrics::INDEX_PAGE_ENTRY_SUM_VISIT_LENGTH . "`, - sum(case log_visit.visit_total_actions when 1 then 1 when 0 then 1 else 0 end) as `" . Metrics::INDEX_PAGE_ENTRY_BOUNCE_COUNT . "`"; + count(distinct log_visit.idvisitor) as `" . PiwikMetrics::INDEX_PAGE_ENTRY_NB_UNIQ_VISITORS . "`, + count(*) as `" . PiwikMetrics::INDEX_PAGE_ENTRY_NB_VISITS . "`, + sum(log_visit.visit_total_actions) as `" . PiwikMetrics::INDEX_PAGE_ENTRY_NB_ACTIONS . "`, + sum(log_visit.visit_total_time) as `" . PiwikMetrics::INDEX_PAGE_ENTRY_SUM_VISIT_LENGTH . "`, + sum(case log_visit.visit_total_actions when 1 then 1 when 0 then 1 else 0 end) as `" . PiwikMetrics::INDEX_PAGE_ENTRY_BOUNCE_COUNT . "`"; $where = "log_visit.visit_last_action_time >= ? - AND log_visit.visit_last_action_time <= ? - AND log_visit.idsite = ? - AND log_visit.%s > 0"; + AND log_visit.visit_last_action_time <= ? + AND log_visit.idsite = ? + AND log_visit.%s > 0"; $groupBy = "log_visit.%s, idaction"; @@ -336,8 +311,8 @@ class Archiver extends \Piwik\Plugin\Archiver $rankingQuery = new RankingQuery($rankingQueryLimit); $rankingQuery->setOthersLabel(DataTable::LABEL_SUMMARY_ROW); $rankingQuery->addLabelColumn('idaction'); - $rankingQuery->addColumn(Metrics::INDEX_PAGE_EXIT_NB_UNIQ_VISITORS); - $rankingQuery->addColumn(Metrics::INDEX_PAGE_EXIT_NB_VISITS, 'sum'); + $rankingQuery->addColumn(PiwikMetrics::INDEX_PAGE_EXIT_NB_UNIQ_VISITORS); + $rankingQuery->addColumn(PiwikMetrics::INDEX_PAGE_EXIT_NB_VISITS, 'sum'); $rankingQuery->partitionResultIntoMultipleGroups('type', array_keys($this->actionsTablesByType)); $extraSelects = 'log_action.type, log_action.name,'; @@ -348,7 +323,7 @@ class Archiver extends \Piwik\Plugin\Archiver "joinOn" => "log_visit.%s = log_action.idaction" ) ); - $orderBy = "`" . Metrics::INDEX_PAGE_EXIT_NB_VISITS . "` DESC, log_action.name ASC"; + $orderBy = "`" . PiwikMetrics::INDEX_PAGE_EXIT_NB_VISITS . "` DESC, log_action.name ASC"; } else { $extraSelects = false; $from = "log_visit"; @@ -356,13 +331,13 @@ class Archiver extends \Piwik\Plugin\Archiver } $select = "log_visit.%s as idaction, $extraSelects - count(distinct log_visit.idvisitor) as `" . Metrics::INDEX_PAGE_EXIT_NB_UNIQ_VISITORS . "`, - count(*) as `" . Metrics::INDEX_PAGE_EXIT_NB_VISITS . "`"; + count(distinct log_visit.idvisitor) as `" . PiwikMetrics::INDEX_PAGE_EXIT_NB_UNIQ_VISITORS . "`, + count(*) as `" . PiwikMetrics::INDEX_PAGE_EXIT_NB_VISITS . "`"; $where = "log_visit.visit_last_action_time >= ? - AND log_visit.visit_last_action_time <= ? - AND log_visit.idsite = ? - AND log_visit.%s > 0"; + AND log_visit.visit_last_action_time <= ? + AND log_visit.idsite = ? + AND log_visit.%s > 0"; $groupBy = "log_visit.%s, idaction"; @@ -382,10 +357,10 @@ class Archiver extends \Piwik\Plugin\Archiver $rankingQuery = new RankingQuery($rankingQueryLimit); $rankingQuery->setOthersLabel(DataTable::LABEL_SUMMARY_ROW); $rankingQuery->addLabelColumn('idaction'); - $rankingQuery->addColumn(Metrics::INDEX_PAGE_SUM_TIME_SPENT, 'sum'); + $rankingQuery->addColumn(PiwikMetrics::INDEX_PAGE_SUM_TIME_SPENT, 'sum'); $rankingQuery->partitionResultIntoMultipleGroups('type', array_keys($this->actionsTablesByType)); - $extraSelects = "log_action.type, log_action.name, count(*) as `" . Metrics::INDEX_PAGE_NB_HITS . "`,"; + $extraSelects = "log_action.type, log_action.name, count(*) as `" . PiwikMetrics::INDEX_PAGE_NB_HITS . "`,"; $from = array( "log_link_visit_action", array( @@ -393,7 +368,7 @@ class Archiver extends \Piwik\Plugin\Archiver "joinOn" => "log_link_visit_action.%s = log_action.idaction" ) ); - $orderBy = "`" . Metrics::INDEX_PAGE_NB_HITS . "` DESC, log_action.name ASC"; + $orderBy = "`" . PiwikMetrics::INDEX_PAGE_NB_HITS . "` DESC, log_action.name ASC"; } else { $extraSelects = false; $from = "log_link_visit_action"; @@ -401,13 +376,13 @@ class Archiver extends \Piwik\Plugin\Archiver } $select = "log_link_visit_action.%s as idaction, $extraSelects - sum(log_link_visit_action.time_spent_ref_action) as `" . Metrics::INDEX_PAGE_SUM_TIME_SPENT . "`"; + sum(log_link_visit_action.time_spent_ref_action) as `" . PiwikMetrics::INDEX_PAGE_SUM_TIME_SPENT . "`"; $where = "log_link_visit_action.server_time >= ? - AND log_link_visit_action.server_time <= ? - AND log_link_visit_action.idsite = ? - AND log_link_visit_action.time_spent_ref_action > 0 - AND log_link_visit_action.%s > 0" + AND log_link_visit_action.server_time <= ? + AND log_link_visit_action.idsite = ? + AND log_link_visit_action.time_spent_ref_action > 0 + AND log_link_visit_action.%s > 0" . $this->getWhereClauseActionIsNotEvent(); $groupBy = "log_link_visit_action.%s, idaction"; @@ -437,10 +412,10 @@ class Archiver extends \Piwik\Plugin\Archiver $this->insertTable($dataTable, self::PAGE_URLS_RECORD_NAME); $records = array( - self::METRIC_PAGEVIEWS_RECORD_NAME => array_sum($dataTable->getColumn(Metrics::INDEX_PAGE_NB_HITS)), - self::METRIC_UNIQ_PAGEVIEWS_RECORD_NAME => array_sum($dataTable->getColumn(Metrics::INDEX_NB_VISITS)), - self::METRIC_SUM_TIME_RECORD_NAME => array_sum($dataTable->getColumn(Metrics::INDEX_PAGE_SUM_TIME_GENERATION)), - self::METRIC_HITS_TIMED_RECORD_NAME => array_sum($dataTable->getColumn(Metrics::INDEX_PAGE_NB_HITS_WITH_TIME_GENERATION)) + self::METRIC_PAGEVIEWS_RECORD_NAME => array_sum($dataTable->getColumn(PiwikMetrics::INDEX_PAGE_NB_HITS)), + self::METRIC_UNIQ_PAGEVIEWS_RECORD_NAME => array_sum($dataTable->getColumn(PiwikMetrics::INDEX_NB_VISITS)), + self::METRIC_SUM_TIME_RECORD_NAME => array_sum($dataTable->getColumn(PiwikMetrics::INDEX_PAGE_SUM_TIME_GENERATION)), + self::METRIC_HITS_TIMED_RECORD_NAME => array_sum($dataTable->getColumn(PiwikMetrics::INDEX_PAGE_NB_HITS_WITH_TIME_GENERATION)) ); $this->getProcessor()->insertNumericRecords($records); } @@ -466,8 +441,8 @@ class Archiver extends \Piwik\Plugin\Archiver $dataTable = $this->getDataTable(Action::TYPE_DOWNLOAD); $this->insertTable($dataTable, self::DOWNLOADS_RECORD_NAME); - $this->getProcessor()->insertNumericRecord(self::METRIC_DOWNLOADS_RECORD_NAME, array_sum($dataTable->getColumn(Metrics::INDEX_PAGE_NB_HITS))); - $this->getProcessor()->insertNumericRecord(self::METRIC_UNIQ_DOWNLOADS_RECORD_NAME, array_sum($dataTable->getColumn(Metrics::INDEX_NB_VISITS))); + $this->getProcessor()->insertNumericRecord(self::METRIC_DOWNLOADS_RECORD_NAME, array_sum($dataTable->getColumn(PiwikMetrics::INDEX_PAGE_NB_HITS))); + $this->getProcessor()->insertNumericRecord(self::METRIC_UNIQ_DOWNLOADS_RECORD_NAME, array_sum($dataTable->getColumn(PiwikMetrics::INDEX_NB_VISITS))); } protected function insertOutlinksReports() @@ -475,8 +450,8 @@ class Archiver extends \Piwik\Plugin\Archiver $dataTable = $this->getDataTable(Action::TYPE_OUTLINK); $this->insertTable($dataTable, self::OUTLINKS_RECORD_NAME); - $this->getProcessor()->insertNumericRecord(self::METRIC_OUTLINKS_RECORD_NAME, array_sum($dataTable->getColumn(Metrics::INDEX_PAGE_NB_HITS))); - $this->getProcessor()->insertNumericRecord(self::METRIC_UNIQ_OUTLINKS_RECORD_NAME, array_sum($dataTable->getColumn(Metrics::INDEX_NB_VISITS))); + $this->getProcessor()->insertNumericRecord(self::METRIC_OUTLINKS_RECORD_NAME, array_sum($dataTable->getColumn(PiwikMetrics::INDEX_PAGE_NB_HITS))); + $this->getProcessor()->insertNumericRecord(self::METRIC_UNIQ_OUTLINKS_RECORD_NAME, array_sum($dataTable->getColumn(PiwikMetrics::INDEX_NB_VISITS))); } protected function insertPageTitlesReports() @@ -491,21 +466,21 @@ class Archiver extends \Piwik\Plugin\Archiver $this->deleteUnusedColumnsFromKeywordsDataTable($dataTable); $this->insertTable($dataTable, self::SITE_SEARCH_RECORD_NAME); - $this->getProcessor()->insertNumericRecord(self::METRIC_SEARCHES_RECORD_NAME, array_sum($dataTable->getColumn(Metrics::INDEX_NB_VISITS))); + $this->getProcessor()->insertNumericRecord(self::METRIC_SEARCHES_RECORD_NAME, array_sum($dataTable->getColumn(PiwikMetrics::INDEX_NB_VISITS))); $this->getProcessor()->insertNumericRecord(self::METRIC_KEYWORDS_RECORD_NAME, $dataTable->getRowsCount()); } protected function deleteUnusedColumnsFromKeywordsDataTable(DataTable $dataTable) { $columnsToDelete = array( - Metrics::INDEX_NB_UNIQ_VISITORS, - Metrics::INDEX_PAGE_IS_FOLLOWING_SITE_SEARCH_NB_HITS, - Metrics::INDEX_PAGE_ENTRY_NB_UNIQ_VISITORS, - Metrics::INDEX_PAGE_ENTRY_NB_ACTIONS, - Metrics::INDEX_PAGE_ENTRY_SUM_VISIT_LENGTH, - Metrics::INDEX_PAGE_ENTRY_NB_VISITS, - Metrics::INDEX_PAGE_ENTRY_BOUNCE_COUNT, - Metrics::INDEX_PAGE_EXIT_NB_UNIQ_VISITORS, + PiwikMetrics::INDEX_NB_UNIQ_VISITORS, + PiwikMetrics::INDEX_PAGE_IS_FOLLOWING_SITE_SEARCH_NB_HITS, + PiwikMetrics::INDEX_PAGE_ENTRY_NB_UNIQ_VISITORS, + PiwikMetrics::INDEX_PAGE_ENTRY_NB_ACTIONS, + PiwikMetrics::INDEX_PAGE_ENTRY_SUM_VISIT_LENGTH, + PiwikMetrics::INDEX_PAGE_ENTRY_NB_VISITS, + PiwikMetrics::INDEX_PAGE_ENTRY_BOUNCE_COUNT, + PiwikMetrics::INDEX_PAGE_EXIT_NB_UNIQ_VISITORS, ); $dataTable->deleteColumns($columnsToDelete); } @@ -521,8 +496,8 @@ class Archiver extends \Piwik\Plugin\Archiver ArchivingHelper::$maximumRowsInDataTableLevelZero, ArchivingHelper::$maximumRowsInSubDataTable, ArchivingHelper::$columnToSortByBeforeTruncation, - self::$columnsAggregationOperation, - self::$columnsToRenameAfterAggregation + Metrics::$columnsAggregationOperation, + Metrics::$columnsToRenameAfterAggregation ); $dataTableToSum = array( @@ -536,7 +511,7 @@ class Archiver extends \Piwik\Plugin\Archiver ArchivingHelper::$maximumRowsInSubDataTable, ArchivingHelper::$columnToSortByBeforeTruncation, $aggregation, - self::$columnsToRenameAfterAggregation + Metrics::$columnsToRenameAfterAggregation ); $this->getProcessor()->aggregateNumericMetrics($this->getMetricNames()); diff --git a/plugins/Actions/ArchivingHelper.php b/plugins/Actions/ArchivingHelper.php index 34873eb194a164bd173cdbc3293efe493d8b2cc0..16a7c5f536c29370bed39d4518698ef897fb2173 100644 --- a/plugins/Actions/ArchivingHelper.php +++ b/plugins/Actions/ArchivingHelper.php @@ -14,7 +14,7 @@ use Piwik\DataTable\Row\DataTableSummaryRow; use Piwik\DataTable; use Piwik\DataTable\Manager; use Piwik\DataTable\Row; -use Piwik\Metrics; +use Piwik\Metrics as PiwikMetrics; use Piwik\Piwik; use Piwik\Tracker\Action; use Piwik\Tracker\PageUrl; @@ -38,7 +38,7 @@ class ArchivingHelper * @param array $actionsTablesByType * @return int */ - public static function updateActionsTableWithRowQuery($query, $fieldQueried, & $actionsTablesByType) + public static function updateActionsTableWithRowQuery($query, $fieldQueried, & $actionsTablesByType, $metricsConfig) { $rowsProcessed = 0; while ($row = $query->fetch()) { @@ -51,7 +51,7 @@ class ArchivingHelper } if ($row['type'] != Action::TYPE_SITE_SEARCH) { - unset($row[Metrics::INDEX_SITE_SEARCH_HAS_NO_RESULT]); + unset($row[PiwikMetrics::INDEX_SITE_SEARCH_HAS_NO_RESULT]); } if ($row['type'] == Action::TYPE_CONTENT) { @@ -111,15 +111,15 @@ class ArchivingHelper && !$actionRow->isSummaryRow() ) { if (($existingUrl = $actionRow->getMetadata('url')) !== false) { - if (!empty($row[Metrics::INDEX_PAGE_NB_HITS]) - && $row[Metrics::INDEX_PAGE_NB_HITS] > $actionRow->maxVisitsSummed + if (!empty($row[PiwikMetrics::INDEX_PAGE_NB_HITS]) + && $row[PiwikMetrics::INDEX_PAGE_NB_HITS] > $actionRow->maxVisitsSummed ) { $actionRow->setMetadata('url', $url); - $actionRow->maxVisitsSummed = $row[Metrics::INDEX_PAGE_NB_HITS]; + $actionRow->maxVisitsSummed = $row[PiwikMetrics::INDEX_PAGE_NB_HITS]; } } else { $actionRow->setMetadata('url', $url); - $actionRow->maxVisitsSummed = !empty($row[Metrics::INDEX_PAGE_NB_HITS]) ? $row[Metrics::INDEX_PAGE_NB_HITS] : 0; + $actionRow->maxVisitsSummed = !empty($row[PiwikMetrics::INDEX_PAGE_NB_HITS]) ? $row[PiwikMetrics::INDEX_PAGE_NB_HITS] : 0; } } @@ -127,17 +127,17 @@ class ArchivingHelper && $row['type'] != Action::TYPE_PAGE_TITLE ) { // only keep performance metrics when they're used (i.e. for URLs and page titles) - if (array_key_exists(Metrics::INDEX_PAGE_SUM_TIME_GENERATION, $row)) { - unset($row[Metrics::INDEX_PAGE_SUM_TIME_GENERATION]); + if (array_key_exists(PiwikMetrics::INDEX_PAGE_SUM_TIME_GENERATION, $row)) { + unset($row[PiwikMetrics::INDEX_PAGE_SUM_TIME_GENERATION]); } - if (array_key_exists(Metrics::INDEX_PAGE_NB_HITS_WITH_TIME_GENERATION, $row)) { - unset($row[Metrics::INDEX_PAGE_NB_HITS_WITH_TIME_GENERATION]); + if (array_key_exists(PiwikMetrics::INDEX_PAGE_NB_HITS_WITH_TIME_GENERATION, $row)) { + unset($row[PiwikMetrics::INDEX_PAGE_NB_HITS_WITH_TIME_GENERATION]); } - if (array_key_exists(Metrics::INDEX_PAGE_MIN_TIME_GENERATION, $row)) { - unset($row[Metrics::INDEX_PAGE_MIN_TIME_GENERATION]); + if (array_key_exists(PiwikMetrics::INDEX_PAGE_MIN_TIME_GENERATION, $row)) { + unset($row[PiwikMetrics::INDEX_PAGE_MIN_TIME_GENERATION]); } - if (array_key_exists(Metrics::INDEX_PAGE_MAX_TIME_GENERATION, $row)) { - unset($row[Metrics::INDEX_PAGE_MAX_TIME_GENERATION]); + if (array_key_exists(PiwikMetrics::INDEX_PAGE_MAX_TIME_GENERATION, $row)) { + unset($row[PiwikMetrics::INDEX_PAGE_MAX_TIME_GENERATION]); } } @@ -151,7 +151,7 @@ class ArchivingHelper // - this happens when 2 visitors visit the same new page at the same time, and 2 actions get recorded for the same name // - this could also happen when 2 URLs end up having the same label (eg. 2 subdomains get aggregated to the "/index" page name) if (($alreadyValue = $actionRow->getColumn($name)) !== false) { - $newValue = self::getColumnValuesMerged($name, $alreadyValue, $value); + $newValue = self::getColumnValuesMerged($name, $alreadyValue, $value, $metricsConfig); $actionRow->setColumn($name, $newValue); } else { $actionRow->addColumn($name, $value); @@ -161,7 +161,7 @@ class ArchivingHelper // if the exit_action was not recorded properly in the log_link_visit_action // there would be an error message when getting the nb_hits column // we must fake the record and add the columns - if ($actionRow->getColumn(Metrics::INDEX_PAGE_NB_HITS) === false) { + if ($actionRow->getColumn(PiwikMetrics::INDEX_PAGE_NB_HITS) === false) { // to test this code: delete the entries in log_link_action_visit for // a given exit_idaction_url foreach (self::getDefaultRow()->getColumns() as $name => $value) { @@ -180,7 +180,7 @@ class ArchivingHelper { // Delete all columns that have a value of zero $dataTable->filter('ColumnDelete', array( - $columnsToRemove = array(Metrics::INDEX_PAGE_IS_FOLLOWING_SITE_SEARCH_NB_HITS), + $columnsToRemove = array(PiwikMetrics::INDEX_PAGE_IS_FOLLOWING_SITE_SEARCH_NB_HITS), $columnsToKeep = array(), $deleteIfZeroOnly = true )); @@ -207,7 +207,7 @@ class ArchivingHelper $row->recalculate(); } - foreach (Archiver::$columnsToDeleteAfterAggregation as $name) { + foreach (Metrics::$columnsToDeleteAfterAggregation as $name) { $row->deleteColumn($name); } } @@ -267,21 +267,28 @@ class ArchivingHelper * @param $value * @return mixed */ - private static function getColumnValuesMerged($columnName, $alreadyValue, $value) + private static function getColumnValuesMerged($columnName, $alreadyValue, $value, $metricsConfig) { - if ($columnName == Metrics::INDEX_PAGE_MIN_TIME_GENERATION) { - if (empty($alreadyValue)) { - $newValue = $value; - } else if (empty($value)) { - $newValue = $alreadyValue; - } else { - $newValue = min($alreadyValue, $value); + if (array_key_exists($columnName, $metricsConfig)) { + $config = $metricsConfig[$columnName]; + + if (!empty($config['aggregation'])) { + + if ($config['aggregation'] == 'min') { + if (empty($alreadyValue)) { + $newValue = $value; + } else if (empty($value)) { + $newValue = $alreadyValue; + } else { + $newValue = min($alreadyValue, $value); + } + return $newValue; + } + if ($config['aggregation'] == 'max') { + $newValue = max($alreadyValue, $value); + return $newValue; + } } - return $newValue; - } - if ($columnName == Metrics::INDEX_PAGE_MAX_TIME_GENERATION) { - $newValue = max($alreadyValue, $value); - return $newValue; } $newValue = $alreadyValue + $value; @@ -310,7 +317,7 @@ class ArchivingHelper } self::$defaultActionName = Config::getInstance()->General['action_default_name']; - self::$columnToSortByBeforeTruncation = Metrics::INDEX_NB_VISITS; + self::$columnToSortByBeforeTruncation = PiwikMetrics::INDEX_NB_VISITS; self::$maximumRowsInDataTableLevelZero = Config::getInstance()->General['datatable_archiving_maximum_rows_actions']; self::$maximumRowsInSubDataTable = Config::getInstance()->General['datatable_archiving_maximum_rows_subtable_actions']; @@ -333,9 +340,9 @@ class ArchivingHelper // so we add this fake row information to make sure there is a nb_hits, etc. column for every action $row = new Row(array( Row::COLUMNS => array( - Metrics::INDEX_NB_VISITS => 1, - Metrics::INDEX_NB_UNIQ_VISITORS => 1, - Metrics::INDEX_PAGE_NB_HITS => 1, + PiwikMetrics::INDEX_NB_VISITS => 1, + PiwikMetrics::INDEX_NB_UNIQ_VISITORS => 1, + PiwikMetrics::INDEX_PAGE_NB_HITS => 1, ))); } return $row; @@ -351,13 +358,13 @@ class ArchivingHelper * @param array $actionsTablesByType * @return DataTable */ - private static function getActionRow($actionName, $actionType, $urlPrefix = null, &$actionsTablesByType) + public static function getActionRow($actionName, $actionType, $urlPrefix = null, &$actionsTablesByType) { // we work on the root table of the given TYPE (either ACTION_URL or DOWNLOAD or OUTLINK etc.) /* @var DataTable $currentTable */ $currentTable =& $actionsTablesByType[$actionType]; - if(is_null($currentTable)) { + if (is_null($currentTable)) { throw new \Exception("Action table for type '$actionType' was not found during Actions archiving."); } @@ -529,10 +536,10 @@ class ArchivingHelper */ private static function getDefaultRowColumns() { - return array(Metrics::INDEX_NB_VISITS => 0, - Metrics::INDEX_NB_UNIQ_VISITORS => 0, - Metrics::INDEX_PAGE_NB_HITS => 0, - Metrics::INDEX_PAGE_SUM_TIME_SPENT => 0); + return array(PiwikMetrics::INDEX_NB_VISITS => 0, + PiwikMetrics::INDEX_NB_UNIQ_VISITORS => 0, + PiwikMetrics::INDEX_PAGE_NB_HITS => 0, + PiwikMetrics::INDEX_PAGE_SUM_TIME_SPENT => 0); } /** diff --git a/plugins/Actions/Metrics.php b/plugins/Actions/Metrics.php new file mode 100644 index 0000000000000000000000000000000000000000..83b1c7370aeecb2270ac338f96e07ddd17282191 --- /dev/null +++ b/plugins/Actions/Metrics.php @@ -0,0 +1,85 @@ +<?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\Actions; + +use Piwik\DataTable; +use Piwik\Metrics as PiwikMetrics; +use Piwik\Piwik; +use Piwik\RankingQuery; +use Piwik\Tracker\Action; +use Piwik\Plugins\Actions\Actions\ActionSiteSearch; + +/** + * Class encapsulating logic to process Day/Period Archiving for the Actions reports + * + */ +class Metrics +{ + + public static $actionTypes = array( + Action::TYPE_PAGE_URL, + Action::TYPE_OUTLINK, + Action::TYPE_DOWNLOAD, + Action::TYPE_PAGE_TITLE, + Action::TYPE_SITE_SEARCH, + ); + + public static $columnsToRenameAfterAggregation = array( + PiwikMetrics::INDEX_NB_UNIQ_VISITORS => PiwikMetrics::INDEX_SUM_DAILY_NB_UNIQ_VISITORS, + PiwikMetrics::INDEX_PAGE_ENTRY_NB_UNIQ_VISITORS => PiwikMetrics::INDEX_PAGE_ENTRY_SUM_DAILY_NB_UNIQ_VISITORS, + PiwikMetrics::INDEX_PAGE_EXIT_NB_UNIQ_VISITORS => PiwikMetrics::INDEX_PAGE_EXIT_SUM_DAILY_NB_UNIQ_VISITORS, + ); + + public static $columnsToDeleteAfterAggregation = array( + PiwikMetrics::INDEX_NB_UNIQ_VISITORS, + PiwikMetrics::INDEX_PAGE_ENTRY_NB_UNIQ_VISITORS, + PiwikMetrics::INDEX_PAGE_EXIT_NB_UNIQ_VISITORS, + ); + + public static $columnsAggregationOperation = array( + PiwikMetrics::INDEX_PAGE_MAX_TIME_GENERATION => 'max', + PiwikMetrics::INDEX_PAGE_MIN_TIME_GENERATION => 'min' + ); + + public static function getActionMetrics() + { + $metricsConfig = array( + PiwikMetrics::INDEX_PAGE_SUM_TIME_GENERATION => array( + 'aggregation' => 'sum', + 'query' => "sum( + case when " . Action::DB_COLUMN_CUSTOM_FLOAT . " is null + then 0 + else " . Action::DB_COLUMN_CUSTOM_FLOAT . " + end + ) / 1000" + ), + PiwikMetrics::INDEX_PAGE_NB_HITS_WITH_TIME_GENERATION => array( + 'aggregation' => 'sum', + 'query' => "sum( + case when " . Action::DB_COLUMN_CUSTOM_FLOAT . " is null + then 0 + else 1 + end + )" + ), + PiwikMetrics::INDEX_PAGE_MIN_TIME_GENERATION => array( + 'aggregation' => 'min', + 'query' => "min(" . Action::DB_COLUMN_CUSTOM_FLOAT . ") / 1000" + ), + PiwikMetrics::INDEX_PAGE_MAX_TIME_GENERATION => array( + 'aggregation' => 'max', + 'query' => "max(" . Action::DB_COLUMN_CUSTOM_FLOAT . ") / 1000" + ), + ); + + Piwik::postEvent('Actions.Archiving.addActionMetrics', array(&$metricsConfig)); + + return $metricsConfig; + } +} diff --git a/plugins/VisitsSummary/templates/_sparklines.twig b/plugins/VisitsSummary/templates/_sparklines.twig index 92bc44b6a0ceccdc1deb5286c35d86a642517bac..a61a31d2300e2db73f24c9e4b68182d2bebb6aff 100644 --- a/plugins/VisitsSummary/templates/_sparklines.twig +++ b/plugins/VisitsSummary/templates/_sparklines.twig @@ -69,6 +69,8 @@ {{ sparkline(urlSparklineMaxActions)|raw }} {{ 'VisitsSummary_MaxNbActions'|translate("<strong>"~maxActions~"</strong>")|raw }} </div> + + {{ postEvent('Template.VisitsSummaryOverviewSparklines') }} </div> <div style="clear:both;"></div> diff --git a/tests/LocalTracker.php b/tests/LocalTracker.php index 98ef3e65019c37b93dbb2b50f0338c9de5dc46b2..6e251e6d21acbf2e995c8aee7c71c663002e217c 100755 --- a/tests/LocalTracker.php +++ b/tests/LocalTracker.php @@ -21,6 +21,10 @@ class Piwik_LocalTracker extends PiwikTracker { protected function sendRequest($url, $method = 'GET', $data = null, $force = false) { + if ($this->DEBUG_APPEND_URL) { + $url .= $this->DEBUG_APPEND_URL; + } + // if doing a bulk request, store the url if ($this->doBulkRequests && !$force) { $this->storedTrackingActions[] = $url; diff --git a/tests/PHPUnit/Unit/Metrics/Formatter/HtmlTest.php b/tests/PHPUnit/Unit/Metrics/Formatter/HtmlTest.php index dd0c0a106b77061f58a61ddbc41f4ab23e76219e..004e749e25e85ccd48349bb0d5ff1c9c51489f5d 100644 --- a/tests/PHPUnit/Unit/Metrics/Formatter/HtmlTest.php +++ b/tests/PHPUnit/Unit/Metrics/Formatter/HtmlTest.php @@ -61,6 +61,22 @@ class HtmlTest extends \PHPUnit_Framework_TestCase $this->assertEquals($expected, $value); } + public function test_getPrettySizeFromBytes_InFixedUnitThatIsHigherThanBestUnit() + { + $expected = '0.001465 M'; + $value = $this->formatter->getPrettySizeFromBytes(1536, 'M', 6); + + $this->assertEquals($expected, $value); + } + + public function test_getPrettySizeFromBytes_InUnitThatIsLowerThanBestUnit() + { + $expected = '1536 B'; + $value = $this->formatter->getPrettySizeFromBytes(1536, 'B'); + + $this->assertEquals($expected, $value); + } + public function test_getPrettyMoney_UsesNonBreakingSpaces() { $expected = '1 €';