update Piwik to version 2.16 (fixes #91)

This commit is contained in:
oliver 2016-04-10 18:55:57 +02:00
commit 47263617c5
108 changed files with 418860 additions and 226988 deletions

View file

@ -1,6 +1,6 @@
<?php
/**
* Piwik - Open source web analytics
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
@ -9,23 +9,27 @@
namespace Piwik\Plugins\Actions;
use Exception;
use Piwik\API\Request;
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;
use Piwik\Plugins\Actions\Columns\Metrics\AverageTimeOnPage;
use Piwik\Plugins\Actions\Columns\Metrics\BounceRate;
use Piwik\Plugins\Actions\Columns\Metrics\ExitRate;
use Piwik\Plugins\CustomVariables\API as APICustomVariables;
use Piwik\Plugins\Actions\Actions\ActionSiteSearch;
use Piwik\Tracker\Action;
use Piwik\Tracker\ActionSiteSearch;
use Piwik\Tracker\PageUrl;
/**
* The Actions API lets you request reports for all your Visitor Actions: Page URLs, Page titles (Piwik Events),
* File Downloads and Clicks on external websites.
*
* For example, "getPageTitles" will return all your page titles along with standard <a href='http://piwik.org/docs/analytics-api/reference/#toc-metric-definitions' target='_blank'>Actions metrics</a> for each row.
* For example, "getPageTitles" will return all your page titles along with standard <a href='http://piwik.org/docs/analytics-api/reference/#toc-metric-definitions' rel='noreferrer' target='_blank'>Actions metrics</a> for each row.
*
* It is also possible to request data for a specific Page Title with "getPageTitle"
* and setting the parameter pageName to the page title you wish to request.
@ -50,58 +54,25 @@ class API extends \Piwik\Plugin\API
public function get($idSite, $period, $date, $segment = false, $columns = false)
{
Piwik::checkUserHasViewAccess($idSite);
$report = Report::factory("Actions", "get");
$archive = Archive::build($idSite, $period, $date, $segment);
$metrics = Archiver::$actionsAggregateMetrics;
$metrics['Actions_avg_time_generation'] = 'avg_time_generation';
$requestedColumns = Piwik::getArrayFromApiParameter($columns);
$columns = $report->getMetricsRequiredForReport($allColumns = null, $requestedColumns);
// get requested columns
$columns = Piwik::getArrayFromApiParameter($columns);
if (!empty($columns)) {
// get the columns that are available and requested
$columns = array_intersect($columns, array_values($metrics));
$columns = array_values($columns); // make sure indexes are right
$nameReplace = array();
foreach ($columns as $i => $column) {
$fullColumn = array_search($column, $metrics);
$columns[$i] = $fullColumn;
$nameReplace[$fullColumn] = $column;
}
$inDbColumnNames = array_map(function ($value) { return 'Actions_' . $value; }, $columns);
$dataTable = $archive->getDataTableFromNumeric($inDbColumnNames);
if (false !== ($avgGenerationTimeRequested = array_search('Actions_avg_time_generation', $columns))) {
unset($columns[$avgGenerationTimeRequested]);
$avgGenerationTimeRequested = true;
}
} else {
// get all columns
unset($metrics['Actions_avg_time_generation']);
$columns = array_keys($metrics);
$nameReplace = & $metrics;
$avgGenerationTimeRequested = true;
}
$dataTable->deleteColumns(array_diff($requestedColumns, $columns));
if ($avgGenerationTimeRequested) {
$tempColumns[] = Archiver::METRIC_SUM_TIME_RECORD_NAME;
$tempColumns[] = Archiver::METRIC_HITS_TIMED_RECORD_NAME;
$columns = array_merge($columns, $tempColumns);
$columns = array_unique($columns);
$newNameMapping = array_combine($inDbColumnNames, $columns);
$dataTable->filter('ReplaceColumnNames', array($newNameMapping));
$nameReplace[Archiver::METRIC_SUM_TIME_RECORD_NAME] = 'sum_time_generation';
$nameReplace[Archiver::METRIC_HITS_TIMED_RECORD_NAME] = 'nb_hits_with_time_generation';
}
$columnsToShow = $requestedColumns ?: $report->getAllMetrics();
$dataTable->queueFilter('ColumnDelete', array($columnsToRemove = array(), $columnsToShow));
$table = $archive->getDataTableFromNumeric($columns);
// replace labels (remove Actions_)
$table->filter('ReplaceColumnNames', array($nameReplace));
// compute avg generation time
if ($avgGenerationTimeRequested) {
$table->filter('ColumnCallbackAddColumnQuotient', array('avg_time_generation', 'sum_time_generation', 'nb_hits_with_time_generation', 3));
$table->deleteColumns(array('sum_time_generation', 'nb_hits_with_time_generation'));
}
return $table;
return $dataTable;
}
/**
@ -112,15 +83,17 @@ class API extends \Piwik\Plugin\API
* @param bool $expanded
* @param bool|int $idSubtable
* @param bool|int $depth
* @param bool|int $flat
*
* @return DataTable|DataTable\Map
*/
public function getPageUrls($idSite, $period, $date, $segment = false, $expanded = false, $idSubtable = false,
$depth = false)
$depth = false, $flat = false)
{
$dataTable = $this->getDataTableFromArchive('Actions_actions_url', $idSite, $period, $date, $segment, $expanded, $idSubtable, $depth);
$this->filterPageDatatable($dataTable);
$this->filterActionsDataTable($dataTable, $expanded);
$dataTable = Archive::createDataTableFromArchive('Actions_actions_url', $idSite, $period, $date, $segment, $expanded, $flat, $idSubtable, $depth);
$this->filterActionsDataTable($dataTable);
return $dataTable;
}
@ -165,7 +138,7 @@ class API extends \Piwik\Plugin\API
{
// Keep only pages which are following site search
$dataTable->filter('ColumnCallbackDeleteRow', array(
'nb_hits_following_search',
PiwikMetrics::INDEX_PAGE_IS_FOLLOWING_SITE_SEARCH_NB_HITS,
function ($value) {
return $value <= 0;
}
@ -196,18 +169,19 @@ class API extends \Piwik\Plugin\API
public function getPageUrl($pageUrl, $idSite, $period, $date, $segment = false)
{
$callBackParameters = array('Actions_actions_url', $idSite, $period, $date, $segment, $expanded = false, $idSubtable = false);
$callBackParameters = array('Actions_actions_url', $idSite, $period, $date, $segment, $expanded = false, $flat = false, $idSubtable = null);
$dataTable = $this->getFilterPageDatatableSearch($callBackParameters, $pageUrl, Action::TYPE_PAGE_URL);
$this->filterPageDatatable($dataTable);
$this->addPageProcessedMetrics($dataTable);
$this->filterActionsDataTable($dataTable);
return $dataTable;
}
public function getPageTitles($idSite, $period, $date, $segment = false, $expanded = false, $idSubtable = false)
public function getPageTitles($idSite, $period, $date, $segment = false, $expanded = false, $idSubtable = false, $flat = false)
{
$dataTable = $this->getDataTableFromArchive('Actions_actions', $idSite, $period, $date, $segment, $expanded, $idSubtable);
$this->filterPageDatatable($dataTable);
$this->filterActionsDataTable($dataTable, $expanded);
$dataTable = Archive::createDataTableFromArchive('Actions_actions', $idSite, $period, $date, $segment, $expanded, $flat, $idSubtable);
$this->filterActionsDataTable($dataTable);
return $dataTable;
}
@ -237,38 +211,38 @@ class API extends \Piwik\Plugin\API
public function getPageTitle($pageName, $idSite, $period, $date, $segment = false)
{
$callBackParameters = array('Actions_actions', $idSite, $period, $date, $segment, $expanded = false, $idSubtable = false);
$callBackParameters = array('Actions_actions', $idSite, $period, $date, $segment, $expanded = false, $flat = false, $idSubtable = null);
$dataTable = $this->getFilterPageDatatableSearch($callBackParameters, $pageName, Action::TYPE_PAGE_TITLE);
$this->filterPageDatatable($dataTable);
$this->addPageProcessedMetrics($dataTable);
$this->filterActionsDataTable($dataTable);
return $dataTable;
}
public function getDownloads($idSite, $period, $date, $segment = false, $expanded = false, $idSubtable = false)
public function getDownloads($idSite, $period, $date, $segment = false, $expanded = false, $idSubtable = false, $flat = false)
{
$dataTable = $this->getDataTableFromArchive('Actions_downloads', $idSite, $period, $date, $segment, $expanded, $idSubtable);
$dataTable = Archive::createDataTableFromArchive('Actions_downloads', $idSite, $period, $date, $segment, $expanded, $flat, $idSubtable);
$this->filterActionsDataTable($dataTable, $expanded);
return $dataTable;
}
public function getDownload($downloadUrl, $idSite, $period, $date, $segment = false)
{
$callBackParameters = array('Actions_downloads', $idSite, $period, $date, $segment, $expanded = false, $idSubtable = false);
$callBackParameters = array('Actions_downloads', $idSite, $period, $date, $segment, $expanded = false, $flat = false, $idSubtable = null);
$dataTable = $this->getFilterPageDatatableSearch($callBackParameters, $downloadUrl, Action::TYPE_DOWNLOAD);
$this->filterActionsDataTable($dataTable);
return $dataTable;
}
public function getOutlinks($idSite, $period, $date, $segment = false, $expanded = false, $idSubtable = false)
public function getOutlinks($idSite, $period, $date, $segment = false, $expanded = false, $idSubtable = false, $flat = false)
{
$dataTable = $this->getDataTableFromArchive('Actions_outlink', $idSite, $period, $date, $segment, $expanded, $idSubtable);
$dataTable = Archive::createDataTableFromArchive('Actions_outlink', $idSite, $period, $date, $segment, $expanded, $flat, $idSubtable);
$this->filterActionsDataTable($dataTable, $expanded);
return $dataTable;
}
public function getOutlink($outlinkUrl, $idSite, $period, $date, $segment = false)
{
$callBackParameters = array('Actions_outlink', $idSite, $period, $date, $segment, $expanded = false, $idSubtable = false);
$callBackParameters = array('Actions_outlink', $idSite, $period, $date, $segment, $expanded = false, $flat = false, $idSubtable = null);
$dataTable = $this->getFilterPageDatatableSearch($callBackParameters, $outlinkUrl, Action::TYPE_OUTLINK);
$this->filterActionsDataTable($dataTable);
return $dataTable;
@ -277,9 +251,9 @@ 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);
$this->filterPageDatatable($dataTable);
$dataTable->deleteColumn(PiwikMetrics::INDEX_SITE_SEARCH_HAS_NO_RESULT);
$this->filterActionsDataTable($dataTable);
$dataTable->filter('ReplaceColumnNames');
$this->addPagesPerSearchColumn($dataTable);
return $dataTable;
}
@ -297,7 +271,7 @@ class API extends \Piwik\Plugin\API
protected function getSiteSearchKeywordsRaw($idSite, $period, $date, $segment)
{
$dataTable = $this->getDataTableFromArchive('Actions_sitesearch', $idSite, $period, $date, $segment, $expanded = false);
$dataTable = Archive::createDataTableFromArchive('Actions_sitesearch', $idSite, $period, $date, $segment, $expanded = false);
return $dataTable;
}
@ -307,15 +281,15 @@ 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);
$this->filterPageDatatable($dataTable);
$dataTable->deleteColumn(PiwikMetrics::INDEX_SITE_SEARCH_HAS_NO_RESULT);
$this->filterActionsDataTable($dataTable);
$dataTable->filter('ReplaceColumnNames');
$this->addPagesPerSearchColumn($dataTable);
return $dataTable;
}
@ -342,7 +316,6 @@ class API extends \Piwik\Plugin\API
$dataTable = $customVariables->getEmptyClone();
$customVariableDatatables = $customVariables->getDataTables();
$dataTables = $dataTable->getDataTables();
foreach ($customVariableDatatables as $key => $customVariableTableForDate) {
// we do not enter the IF, in the case idSite=1,3 AND period=day&date=datefrom,dateto,
if ($customVariableTableForDate instanceof DataTable
@ -365,6 +338,7 @@ class API extends \Piwik\Plugin\API
}
}
$this->filterActionsDataTable($dataTable);
$dataTable->filter('ReplaceColumnNames');
$this->addPagesPerSearchColumn($dataTable, $columnToRead = 'nb_actions');
return $dataTable;
}
@ -394,7 +368,7 @@ class API extends \Piwik\Plugin\API
if ($table === false) {
// fetch the data table
$table = call_user_func_array(array($this, 'getDataTableFromArchive'), $callBackParameters);
$table = call_user_func_array('\Piwik\Archive::createDataTableFromArchive', $callBackParameters);
if ($table instanceof DataTable\Map) {
// search an array of tables, e.g. when using date=last30
@ -449,7 +423,7 @@ class API extends \Piwik\Plugin\API
// end of tree search reached
if (count($searchTree) == 0) {
$result = new DataTable();
$result = $table->getEmptyClone();
$result->addRow($row);
$result->setAllTableMetadata($table->getAllTableMetadata());
return $result;
@ -457,97 +431,36 @@ class API extends \Piwik\Plugin\API
// match found on this level and more levels remaining: go deeper
$idSubTable = $row->getIdSubDataTable();
$callBackParameters[6] = $idSubTable;
$table = call_user_func_array(array($this, 'getDataTableFromArchive'), $callBackParameters);
$callBackParameters[7] = $idSubTable;
/**
* @var \Piwik\Period $period
*/
$period = $table->getMetadata('period');
if (!empty($period)) {
$callBackParameters[3] = $period->getDateStart() . ',' . $period->getDateEnd();
}
$table = call_user_func_array('\Piwik\Archive::createDataTableFromArchive', $callBackParameters);
return $this->doFilterPageDatatableSearch($callBackParameters, $table, $searchTree);
}
throw new Exception("For this API function, DataTable " . get_class($table) . " is not supported");
}
/**
* Common filters for Page URLs and Page Titles
*
* @param DataTable|DataTable\Simple|DataTable\Map $dataTable
*/
protected function filterPageDatatable($dataTable)
{
$columnsToRemove = array('bounce_rate');
$dataTable->queueFilter('ColumnDelete', array($columnsToRemove));
// Average time on page = total time on page / number visits on that page
$dataTable->queueFilter('ColumnCallbackAddColumnQuotient',
array('avg_time_on_page',
'sum_time_spent',
'nb_visits',
0)
);
// Bounce rate = single page visits on this page / visits started on this page
$dataTable->queueFilter('ColumnCallbackAddColumnPercentage',
array('bounce_rate',
'entry_bounce_count',
'entry_nb_visits',
0));
// % Exit = Number of visits that finished on this page / visits on this page
$dataTable->queueFilter('ColumnCallbackAddColumnPercentage',
array('exit_rate',
'exit_nb_visits',
'nb_visits',
0)
);
// Handle performance analytics
$hasTimeGeneration = (array_sum($dataTable->getColumn(Metrics::INDEX_PAGE_SUM_TIME_GENERATION)) > 0);
if ($hasTimeGeneration) {
// Average generation time = total generation time / number of pageviews
$precisionAvgTimeGeneration = 3;
$dataTable->queueFilter('ColumnCallbackAddColumnQuotient',
array('avg_time_generation',
'sum_time_generation',
'nb_hits_with_time_generation',
$precisionAvgTimeGeneration)
);
$dataTable->queueFilter('ColumnDelete', array(array('sum_time_generation')));
} else {
// No generation time: remove it from the API output and add it to empty_columns metadata, so that
// the columns can also be removed from the view
$dataTable->filter('ColumnDelete', array(array(
Metrics::INDEX_PAGE_SUM_TIME_GENERATION,
Metrics::INDEX_PAGE_NB_HITS_WITH_TIME_GENERATION,
Metrics::INDEX_PAGE_MIN_TIME_GENERATION,
Metrics::INDEX_PAGE_MAX_TIME_GENERATION
)));
if ($dataTable instanceof DataTable) {
$emptyColumns = $dataTable->getMetadata(DataTable::EMPTY_COLUMNS_METADATA_NAME);
if (!is_array($emptyColumns)) {
$emptyColumns = array();
}
$emptyColumns[] = 'sum_time_generation';
$emptyColumns[] = 'avg_time_generation';
$emptyColumns[] = 'min_time_generation';
$emptyColumns[] = 'max_time_generation';
$dataTable->setMetadata(DataTable::EMPTY_COLUMNS_METADATA_NAME, $emptyColumns);
}
}
}
/**
* Common filters for all Actions API
*
* @param DataTable|DataTable\Simple|DataTable\Map $dataTable
* @param bool $expanded
*/
protected function filterActionsDataTable($dataTable, $expanded = false)
private function filterActionsDataTable($dataTable)
{
// Must be applied before Sort in this case, since the DataTable can contain both int and strings indexes
// (in the transition period between pre 1.2 and post 1.2 datatable structure)
$dataTable->filter('ReplaceColumnNames');
$dataTable->filter('Sort', array('nb_visits', 'desc', $naturalSort = false, $expanded));
$dataTable->queueFilter('ReplaceSummaryRowLabel');
$dataTable->filter('Piwik\Plugins\Actions\DataTable\Filter\Actions');
return $dataTable;
}
/**
@ -558,7 +471,7 @@ class API extends \Piwik\Plugin\API
private function filterNonEntryActions($dataTable)
{
$dataTable->filter('ColumnCallbackDeleteRow',
array('entry_nb_visits',
array(PiwikMetrics::INDEX_PAGE_ENTRY_NB_VISITS,
function ($visits) {
return !strlen($visits);
}
@ -574,23 +487,22 @@ class API extends \Piwik\Plugin\API
private function filterNonExitActions($dataTable)
{
$dataTable->filter('ColumnCallbackDeleteRow',
array('exit_nb_visits',
array(PiwikMetrics::INDEX_PAGE_EXIT_NB_VISITS,
function ($visits) {
return !strlen($visits);
})
);
}
protected function getDataTableFromArchive($name, $idSite, $period, $date, $segment, $expanded = false, $idSubtable = null, $depth = null)
private function addPageProcessedMetrics(DataTable\DataTableInterface $dataTable)
{
$skipAggregationOfSubTables = false;
if ($period == 'range'
&& empty($idSubtable)
&& empty($expanded)
&& !Request::shouldLoadFlatten()
) {
$skipAggregationOfSubTables = false;
}
return Archive::getDataTableFromArchive($name, $idSite, $period, $date, $segment, $expanded, $idSubtable, $skipAggregationOfSubTables, $depth);
$dataTable->filter(function (DataTable $table) {
$extraProcessedMetrics = $table->getMetadata(DataTable::EXTRA_PROCESSED_METRICS_METADATA_NAME);
$extraProcessedMetrics[] = new AverageTimeOnPage();
$extraProcessedMetrics[] = new BounceRate();
$extraProcessedMetrics[] = new ExitRate();
$extraProcessedMetrics[] = new AveragePageGenerationTime();
$table->setMetadata(DataTable::EXTRA_PROCESSED_METRICS_METADATA_NAME, $extraProcessedMetrics);
});
}
}

View file

@ -1,6 +1,6 @@
<?php
/**
* Piwik - Open source web analytics
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
@ -8,17 +8,11 @@
*/
namespace Piwik\Plugins\Actions;
use Piwik\API\Request;
use Piwik\ArchiveProcessor;
use Piwik\Common;
use Piwik\Db;
use Piwik\Menu\MenuMain;
use Piwik\MetricsFormatter;
use Piwik\Piwik;
use Piwik\Site;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable;
use Piwik\Site;
use Piwik\WidgetsList;
/**
* Actions plugin
@ -31,21 +25,68 @@ class Actions extends \Piwik\Plugin
const ACTIONS_REPORT_ROWS_DISPLAY = 100;
/**
* @see Piwik\Plugin::getListHooksRegistered
* @see Piwik\Plugin::registerEvents
*/
public function getListHooksRegistered()
public function registerEvents()
{
$hooks = array(
'WidgetsList.addWidgets' => 'addWidgets',
'Menu.Reporting.addItems' => 'addMenus',
'API.getReportMetadata' => 'getReportMetadata',
'API.getSegmentDimensionMetadata' => 'getSegmentsMetadata',
return array(
'ViewDataTable.configure' => 'configureViewDataTable',
'AssetManager.getStylesheetFiles' => 'getStylesheetFiles',
'AssetManager.getJavaScriptFiles' => 'getJsFiles',
'Insights.addReportToOverview' => 'addReportToInsightsOverview'
'Insights.addReportToOverview' => 'addReportToInsightsOverview',
'Live.getAllVisitorDetails' => 'extendVisitorDetails',
'Metrics.getDefaultMetricTranslations' => 'addMetricTranslations',
'Metrics.getDefaultMetricDocumentationTranslations' => 'addMetricDocumentationTranslations',
);
return $hooks;
}
public function extendVisitorDetails(&$visitor, $details)
{
$visitor['searches'] = $details['visit_total_searches'];
$visitor['actions'] = $details['visit_total_actions'];
}
public function addMetricTranslations(&$translations)
{
$metrics = array(
'nb_pageviews' => 'General_ColumnPageviews',
'nb_uniq_pageviews' => 'General_ColumnUniquePageviews',
'nb_downloads' => 'General_Downloads',
'nb_uniq_downloads' => 'Actions_ColumnUniqueDownloads',
'nb_outlinks' => 'General_Outlinks',
'nb_uniq_outlinks' => 'Actions_ColumnUniqueOutlinks',
'nb_searches' => 'Actions_ColumnSearches',
'nb_keywords' => 'Actions_ColumnSiteSearchKeywords',
'avg_time_generation' => 'General_ColumnAverageGenerationTime',
'exit_rate' => 'General_ColumnExitRate',
'entry_nb_visits' => 'General_ColumnEntrances',
'entry_bounce_count' => 'General_ColumnBounces',
'exit_nb_visits' => 'General_ColumnExits',
'nb_pages_per_search' => 'Actions_ColumnPagesPerSearch',
'nb_hits_following_search' => 'General_ColumnViewedAfterSearch',
);
$translations = array_merge($translations, $metrics);
}
public function addMetricDocumentationTranslations(&$translations)
{
$metrics = array(
'nb_pageviews' => 'General_ColumnPageviewsDocumentation',
'nb_uniq_pageviews' => 'General_ColumnUniquePageviewsDocumentation',
'nb_downloads' => 'Actions_ColumnClicksDocumentation',
'nb_uniq_downloads' => 'Actions_ColumnUniqueClicksDocumentation',
'nb_outlinks' => 'Actions_ColumnClicksDocumentation',
'nb_uniq_outlinks' => 'Actions_ColumnUniqueClicksDocumentation',
'nb_searches' => 'Actions_ColumnSearchesDocumentation',
'avg_time_generation' => 'General_ColumnAverageGenerationTimeDocumentation',
'entry_nb_visits' => 'General_ColumnEntrancesDocumentation',
'entry_bounce_count' => 'General_ColumnBouncesDocumentation',
'exit_nb_visits' => 'General_ColumnExitsDocumentation',
'exit_rate' => 'General_ColumnExitRateDocumentation'
);
$translations = array_merge($translations, $metrics);
}
public function addReportToInsightsOverview(&$reports)
@ -63,447 +104,11 @@ class Actions extends \Piwik\Plugin
public function getJsFiles(&$jsFiles)
{
$jsFiles[] = "plugins/Actions/javascripts/actionsDataTable.js";
$jsFiles[] = "plugins/Actions/javascripts/rowactions.js";
}
public function getSegmentsMetadata(&$segments)
public function isSiteSearchEnabled($idSites, $idSite)
{
$sqlFilter = '\\Piwik\\Tracker\\TableLogAction::getIdActionFromSegment';
// entry and exit pages of visit
$segments[] = array(
'type' => 'dimension',
'category' => 'General_Actions',
'name' => 'Actions_ColumnEntryPageURL',
'segment' => 'entryPageUrl',
'sqlSegment' => 'log_visit.visit_entry_idaction_url',
'sqlFilter' => $sqlFilter,
);
$segments[] = array(
'type' => 'dimension',
'category' => 'General_Actions',
'name' => 'Actions_ColumnEntryPageTitle',
'segment' => 'entryPageTitle',
'sqlSegment' => 'log_visit.visit_entry_idaction_name',
'sqlFilter' => $sqlFilter,
);
$segments[] = array(
'type' => 'dimension',
'category' => 'General_Actions',
'name' => 'Actions_ColumnExitPageURL',
'segment' => 'exitPageUrl',
'sqlSegment' => 'log_visit.visit_exit_idaction_url',
'sqlFilter' => $sqlFilter,
);
$segments[] = array(
'type' => 'dimension',
'category' => 'General_Actions',
'name' => 'Actions_ColumnExitPageTitle',
'segment' => 'exitPageTitle',
'sqlSegment' => 'log_visit.visit_exit_idaction_name',
'sqlFilter' => $sqlFilter,
);
// single pages
$segments[] = array(
'type' => 'dimension',
'category' => 'General_Actions',
'name' => 'Actions_ColumnPageURL',
'segment' => 'pageUrl',
'sqlSegment' => 'log_link_visit_action.idaction_url',
'sqlFilter' => $sqlFilter,
'acceptedValues' => "All these segments must be URL encoded, for example: " . urlencode('http://example.com/path/page?query'),
);
$segments[] = array(
'type' => 'dimension',
'category' => 'General_Actions',
'name' => 'Actions_ColumnPageName',
'segment' => 'pageTitle',
'sqlSegment' => 'log_link_visit_action.idaction_name',
'sqlFilter' => $sqlFilter,
);
$segments[] = array(
'type' => 'dimension',
'category' => 'General_Actions',
'name' => 'Actions_SiteSearchKeyword',
'segment' => 'siteSearchKeyword',
'sqlSegment' => 'log_link_visit_action.idaction_name',
'sqlFilter' => $sqlFilter,
);
}
public function getReportMetadata(&$reports)
{
$reports[] = array(
'category' => Piwik::translate('General_Actions'),
'name' => Piwik::translate('General_Actions') . ' - ' . Piwik::translate('General_MainMetrics'),
'module' => 'Actions',
'action' => 'get',
'metrics' => array(
'nb_pageviews' => Piwik::translate('General_ColumnPageviews'),
'nb_uniq_pageviews' => Piwik::translate('General_ColumnUniquePageviews'),
'nb_downloads' => Piwik::translate('General_Downloads'),
'nb_uniq_downloads' => Piwik::translate('Actions_ColumnUniqueDownloads'),
'nb_outlinks' => Piwik::translate('General_Outlinks'),
'nb_uniq_outlinks' => Piwik::translate('Actions_ColumnUniqueOutlinks'),
'nb_searches' => Piwik::translate('Actions_ColumnSearches'),
'nb_keywords' => Piwik::translate('Actions_ColumnSiteSearchKeywords'),
'avg_time_generation' => Piwik::translate('General_ColumnAverageGenerationTime'),
),
'metricsDocumentation' => array(
'nb_pageviews' => Piwik::translate('General_ColumnPageviewsDocumentation'),
'nb_uniq_pageviews' => Piwik::translate('General_ColumnUniquePageviewsDocumentation'),
'nb_downloads' => Piwik::translate('Actions_ColumnClicksDocumentation'),
'nb_uniq_downloads' => Piwik::translate('Actions_ColumnUniqueClicksDocumentation'),
'nb_outlinks' => Piwik::translate('Actions_ColumnClicksDocumentation'),
'nb_uniq_outlinks' => Piwik::translate('Actions_ColumnUniqueClicksDocumentation'),
'nb_searches' => Piwik::translate('Actions_ColumnSearchesDocumentation'),
'avg_time_generation' => Piwik::translate('General_ColumnAverageGenerationTimeDocumentation'),
// 'nb_keywords' => Piwik::translate('Actions_ColumnSiteSearchKeywords'),
),
'processedMetrics' => false,
'order' => 1
);
$metrics = array(
'nb_hits' => Piwik::translate('General_ColumnPageviews'),
'nb_visits' => Piwik::translate('General_ColumnUniquePageviews'),
'bounce_rate' => Piwik::translate('General_ColumnBounceRate'),
'avg_time_on_page' => Piwik::translate('General_ColumnAverageTimeOnPage'),
'exit_rate' => Piwik::translate('General_ColumnExitRate'),
'avg_time_generation' => Piwik::translate('General_ColumnAverageGenerationTime')
);
$documentation = array(
'nb_hits' => Piwik::translate('General_ColumnPageviewsDocumentation'),
'nb_visits' => Piwik::translate('General_ColumnUniquePageviewsDocumentation'),
'bounce_rate' => Piwik::translate('General_ColumnPageBounceRateDocumentation'),
'avg_time_on_page' => Piwik::translate('General_ColumnAverageTimeOnPageDocumentation'),
'exit_rate' => Piwik::translate('General_ColumnExitRateDocumentation'),
'avg_time_generation' => Piwik::translate('General_ColumnAverageGenerationTimeDocumentation'),
);
// pages report
$reports[] = array(
'category' => Piwik::translate('General_Actions'),
'name' => Piwik::translate('Actions_PageUrls'),
'module' => 'Actions',
'action' => 'getPageUrls',
'dimension' => Piwik::translate('Actions_ColumnPageURL'),
'metrics' => $metrics,
'metricsDocumentation' => $documentation,
'documentation' => Piwik::translate('Actions_PagesReportDocumentation', '<br />')
. '<br />' . Piwik::translate('General_UsePlusMinusIconsDocumentation'),
'processedMetrics' => false,
'actionToLoadSubTables' => 'getPageUrls',
'order' => 2
);
// entry pages report
$reports[] = array(
'category' => Piwik::translate('General_Actions'),
'name' => Piwik::translate('Actions_SubmenuPagesEntry'),
'module' => 'Actions',
'action' => 'getEntryPageUrls',
'dimension' => Piwik::translate('Actions_ColumnPageURL'),
'metrics' => array(
'entry_nb_visits' => Piwik::translate('General_ColumnEntrances'),
'entry_bounce_count' => Piwik::translate('General_ColumnBounces'),
'bounce_rate' => Piwik::translate('General_ColumnBounceRate'),
),
'metricsDocumentation' => array(
'entry_nb_visits' => Piwik::translate('General_ColumnEntrancesDocumentation'),
'entry_bounce_count' => Piwik::translate('General_ColumnBouncesDocumentation'),
'bounce_rate' => Piwik::translate('General_ColumnBounceRateForPageDocumentation')
),
'documentation' => Piwik::translate('Actions_EntryPagesReportDocumentation', '<br />')
. ' ' . Piwik::translate('General_UsePlusMinusIconsDocumentation'),
'processedMetrics' => false,
'actionToLoadSubTables' => 'getEntryPageUrls',
'order' => 3
);
// exit pages report
$reports[] = array(
'category' => Piwik::translate('General_Actions'),
'name' => Piwik::translate('Actions_SubmenuPagesExit'),
'module' => 'Actions',
'action' => 'getExitPageUrls',
'dimension' => Piwik::translate('Actions_ColumnPageURL'),
'metrics' => array(
'exit_nb_visits' => Piwik::translate('General_ColumnExits'),
'nb_visits' => Piwik::translate('General_ColumnUniquePageviews'),
'exit_rate' => Piwik::translate('General_ColumnExitRate')
),
'metricsDocumentation' => array(
'exit_nb_visits' => Piwik::translate('General_ColumnExitsDocumentation'),
'nb_visits' => Piwik::translate('General_ColumnUniquePageviewsDocumentation'),
'exit_rate' => Piwik::translate('General_ColumnExitRateDocumentation')
),
'documentation' => Piwik::translate('Actions_ExitPagesReportDocumentation', '<br />')
. ' ' . Piwik::translate('General_UsePlusMinusIconsDocumentation'),
'processedMetrics' => false,
'actionToLoadSubTables' => 'getExitPageUrls',
'order' => 4
);
// page titles report
$reports[] = array(
'category' => Piwik::translate('General_Actions'),
'name' => Piwik::translate('Actions_SubmenuPageTitles'),
'module' => 'Actions',
'action' => 'getPageTitles',
'dimension' => Piwik::translate('Actions_ColumnPageName'),
'metrics' => $metrics,
'metricsDocumentation' => $documentation,
'documentation' => Piwik::translate('Actions_PageTitlesReportDocumentation', array('<br />', htmlentities('<title>'))),
'processedMetrics' => false,
'actionToLoadSubTables' => 'getPageTitles',
'order' => 5,
);
// entry page titles report
$reports[] = array(
'category' => Piwik::translate('General_Actions'),
'name' => Piwik::translate('Actions_EntryPageTitles'),
'module' => 'Actions',
'action' => 'getEntryPageTitles',
'dimension' => Piwik::translate('Actions_ColumnPageName'),
'metrics' => array(
'entry_nb_visits' => Piwik::translate('General_ColumnEntrances'),
'entry_bounce_count' => Piwik::translate('General_ColumnBounces'),
'bounce_rate' => Piwik::translate('General_ColumnBounceRate'),
),
'metricsDocumentation' => array(
'entry_nb_visits' => Piwik::translate('General_ColumnEntrancesDocumentation'),
'entry_bounce_count' => Piwik::translate('General_ColumnBouncesDocumentation'),
'bounce_rate' => Piwik::translate('General_ColumnBounceRateForPageDocumentation')
),
'documentation' => Piwik::translate('Actions_ExitPageTitlesReportDocumentation', '<br />')
. ' ' . Piwik::translate('General_UsePlusMinusIconsDocumentation'),
'processedMetrics' => false,
'actionToLoadSubTables' => 'getEntryPageTitles',
'order' => 6
);
// exit page titles report
$reports[] = array(
'category' => Piwik::translate('General_Actions'),
'name' => Piwik::translate('Actions_ExitPageTitles'),
'module' => 'Actions',
'action' => 'getExitPageTitles',
'dimension' => Piwik::translate('Actions_ColumnPageName'),
'metrics' => array(
'exit_nb_visits' => Piwik::translate('General_ColumnExits'),
'nb_visits' => Piwik::translate('General_ColumnUniquePageviews'),
'exit_rate' => Piwik::translate('General_ColumnExitRate')
),
'metricsDocumentation' => array(
'exit_nb_visits' => Piwik::translate('General_ColumnExitsDocumentation'),
'nb_visits' => Piwik::translate('General_ColumnUniquePageviewsDocumentation'),
'exit_rate' => Piwik::translate('General_ColumnExitRateDocumentation')
),
'documentation' => Piwik::translate('Actions_EntryPageTitlesReportDocumentation', '<br />')
. ' ' . Piwik::translate('General_UsePlusMinusIconsDocumentation'),
'processedMetrics' => false,
'actionToLoadSubTables' => 'getExitPageTitles',
'order' => 7
);
$documentation = array(
'nb_visits' => Piwik::translate('Actions_ColumnUniqueClicksDocumentation'),
'nb_hits' => Piwik::translate('Actions_ColumnClicksDocumentation')
);
// outlinks report
$reports[] = array(
'category' => Piwik::translate('General_Actions'),
'name' => Piwik::translate('General_Outlinks'),
'module' => 'Actions',
'action' => 'getOutlinks',
'dimension' => Piwik::translate('Actions_ColumnClickedURL'),
'metrics' => array(
'nb_visits' => Piwik::translate('Actions_ColumnUniqueClicks'),
'nb_hits' => Piwik::translate('Actions_ColumnClicks')
),
'metricsDocumentation' => $documentation,
'documentation' => Piwik::translate('Actions_OutlinksReportDocumentation') . ' '
. Piwik::translate('Actions_OutlinkDocumentation') . '<br />'
. Piwik::translate('General_UsePlusMinusIconsDocumentation'),
'processedMetrics' => false,
'actionToLoadSubTables' => 'getOutlinks',
'order' => 8,
);
// downloads report
$reports[] = array(
'category' => Piwik::translate('General_Actions'),
'name' => Piwik::translate('General_Downloads'),
'module' => 'Actions',
'action' => 'getDownloads',
'dimension' => Piwik::translate('Actions_ColumnDownloadURL'),
'metrics' => array(
'nb_visits' => Piwik::translate('Actions_ColumnUniqueDownloads'),
'nb_hits' => Piwik::translate('General_Downloads')
),
'metricsDocumentation' => $documentation,
'documentation' => Piwik::translate('Actions_DownloadsReportDocumentation', '<br />'),
'processedMetrics' => false,
'actionToLoadSubTables' => 'getDownloads',
'order' => 9,
);
if ($this->isSiteSearchEnabled()) {
// Search Keywords
$reports[] = array(
'category' => Piwik::translate('Actions_SubmenuSitesearch'),
'name' => Piwik::translate('Actions_WidgetSearchKeywords'),
'module' => 'Actions',
'action' => 'getSiteSearchKeywords',
'dimension' => Piwik::translate('General_ColumnKeyword'),
'metrics' => array(
'nb_visits' => Piwik::translate('Actions_ColumnSearches'),
'nb_pages_per_search' => Piwik::translate('Actions_ColumnPagesPerSearch'),
'exit_rate' => Piwik::translate('Actions_ColumnSearchExits'),
),
'metricsDocumentation' => array(
'nb_visits' => Piwik::translate('Actions_ColumnSearchesDocumentation'),
'nb_pages_per_search' => Piwik::translate('Actions_ColumnPagesPerSearchDocumentation'),
'exit_rate' => Piwik::translate('Actions_ColumnSearchExitsDocumentation'),
),
'documentation' => Piwik::translate('Actions_SiteSearchKeywordsDocumentation') . '<br/><br/>' . Piwik::translate('Actions_SiteSearchIntro') . '<br/><br/>'
. '<a href="http://piwik.org/docs/site-search/" target="_blank">' . Piwik::translate('Actions_LearnMoreAboutSiteSearchLink') . '</a>',
'processedMetrics' => false,
'order' => 15
);
// No Result Search Keywords
$reports[] = array(
'category' => Piwik::translate('Actions_SubmenuSitesearch'),
'name' => Piwik::translate('Actions_WidgetSearchNoResultKeywords'),
'module' => 'Actions',
'action' => 'getSiteSearchNoResultKeywords',
'dimension' => Piwik::translate('Actions_ColumnNoResultKeyword'),
'metrics' => array(
'nb_visits' => Piwik::translate('Actions_ColumnSearches'),
'exit_rate' => Piwik::translate('Actions_ColumnSearchExits'),
),
'metricsDocumentation' => array(
'nb_visits' => Piwik::translate('Actions_ColumnSearchesDocumentation'),
'exit_rate' => Piwik::translate('Actions_ColumnSearchExitsDocumentation'),
),
'documentation' => Piwik::translate('Actions_SiteSearchIntro') . '<br /><br />' . Piwik::translate('Actions_SiteSearchKeywordsNoResultDocumentation'),
'processedMetrics' => false,
'order' => 16
);
if (self::isCustomVariablesPluginsEnabled()) {
// Search Categories
$reports[] = array(
'category' => Piwik::translate('Actions_SubmenuSitesearch'),
'name' => Piwik::translate('Actions_WidgetSearchCategories'),
'module' => 'Actions',
'action' => 'getSiteSearchCategories',
'dimension' => Piwik::translate('Actions_ColumnSearchCategory'),
'metrics' => array(
'nb_visits' => Piwik::translate('Actions_ColumnSearches'),
'nb_pages_per_search' => Piwik::translate('Actions_ColumnPagesPerSearch'),
'exit_rate' => Piwik::translate('Actions_ColumnSearchExits'),
),
'metricsDocumentation' => array(
'nb_visits' => Piwik::translate('Actions_ColumnSearchesDocumentation'),
'nb_pages_per_search' => Piwik::translate('Actions_ColumnPagesPerSearchDocumentation'),
'exit_rate' => Piwik::translate('Actions_ColumnSearchExitsDocumentation'),
),
'documentation' => Piwik::translate('Actions_SiteSearchCategories1') . '<br/>' . Piwik::translate('Actions_SiteSearchCategories2'),
'processedMetrics' => false,
'order' => 17
);
}
$documentation = Piwik::translate('Actions_SiteSearchFollowingPagesDoc') . '<br/>' . Piwik::translate('General_UsePlusMinusIconsDocumentation');
// Pages URLs following Search
$reports[] = array(
'category' => Piwik::translate('Actions_SubmenuSitesearch'),
'name' => Piwik::translate('Actions_WidgetPageUrlsFollowingSearch'),
'module' => 'Actions',
'action' => 'getPageUrlsFollowingSiteSearch',
'dimension' => Piwik::translate('General_ColumnDestinationPage'),
'metrics' => array(
'nb_hits_following_search' => Piwik::translate('General_ColumnViewedAfterSearch'),
'nb_hits' => Piwik::translate('General_ColumnTotalPageviews'),
),
'metricsDocumentation' => array(
'nb_hits_following_search' => Piwik::translate('General_ColumnViewedAfterSearchDocumentation'),
'nb_hits' => Piwik::translate('General_ColumnPageviewsDocumentation'),
),
'documentation' => $documentation,
'processedMetrics' => false,
'order' => 18
);
// Pages Titles following Search
$reports[] = array(
'category' => Piwik::translate('Actions_SubmenuSitesearch'),
'name' => Piwik::translate('Actions_WidgetPageTitlesFollowingSearch'),
'module' => 'Actions',
'action' => 'getPageTitlesFollowingSiteSearch',
'dimension' => Piwik::translate('General_ColumnDestinationPage'),
'metrics' => array(
'nb_hits_following_search' => Piwik::translate('General_ColumnViewedAfterSearch'),
'nb_hits' => Piwik::translate('General_ColumnTotalPageviews'),
),
'metricsDocumentation' => array(
'nb_hits_following_search' => Piwik::translate('General_ColumnViewedAfterSearchDocumentation'),
'nb_hits' => Piwik::translate('General_ColumnPageviewsDocumentation'),
),
'documentation' => $documentation,
'processedMetrics' => false,
'order' => 19
);
}
}
function addWidgets()
{
WidgetsList::add('General_Actions', 'General_Pages', 'Actions', 'getPageUrls');
WidgetsList::add('General_Actions', 'Actions_WidgetPageTitles', 'Actions', 'getPageTitles');
WidgetsList::add('General_Actions', 'General_Outlinks', 'Actions', 'getOutlinks');
WidgetsList::add('General_Actions', 'General_Downloads', 'Actions', 'getDownloads');
WidgetsList::add('General_Actions', 'Actions_WidgetPagesEntry', 'Actions', 'getEntryPageUrls');
WidgetsList::add('General_Actions', 'Actions_WidgetPagesExit', 'Actions', 'getExitPageUrls');
WidgetsList::add('General_Actions', 'Actions_WidgetEntryPageTitles', 'Actions', 'getEntryPageTitles');
WidgetsList::add('General_Actions', 'Actions_WidgetExitPageTitles', 'Actions', 'getExitPageTitles');
if ($this->isSiteSearchEnabled()) {
WidgetsList::add('Actions_SubmenuSitesearch', 'Actions_WidgetSearchKeywords', 'Actions', 'getSiteSearchKeywords');
if (self::isCustomVariablesPluginsEnabled()) {
WidgetsList::add('Actions_SubmenuSitesearch', 'Actions_WidgetSearchCategories', 'Actions', 'getSiteSearchCategories');
}
WidgetsList::add('Actions_SubmenuSitesearch', 'Actions_WidgetSearchNoResultKeywords', 'Actions', 'getSiteSearchNoResultKeywords');
WidgetsList::add('Actions_SubmenuSitesearch', 'Actions_WidgetPageUrlsFollowingSearch', 'Actions', 'getPageUrlsFollowingSiteSearch');
WidgetsList::add('Actions_SubmenuSitesearch', 'Actions_WidgetPageTitlesFollowingSearch', 'Actions', 'getPageTitlesFollowingSiteSearch');
}
}
function addMenus()
{
MenuMain::getInstance()->add('General_Actions', '', array('module' => 'Actions', 'action' => 'indexPageUrls'), true, 15);
MenuMain::getInstance()->add('General_Actions', 'General_Pages', array('module' => 'Actions', 'action' => 'indexPageUrls'), true, 1);
MenuMain::getInstance()->add('General_Actions', 'Actions_SubmenuPagesEntry', array('module' => 'Actions', 'action' => 'indexEntryPageUrls'), true, 2);
MenuMain::getInstance()->add('General_Actions', 'Actions_SubmenuPagesExit', array('module' => 'Actions', 'action' => 'indexExitPageUrls'), true, 3);
MenuMain::getInstance()->add('General_Actions', 'Actions_SubmenuPageTitles', array('module' => 'Actions', 'action' => 'indexPageTitles'), true, 4);
MenuMain::getInstance()->add('General_Actions', 'General_Outlinks', array('module' => 'Actions', 'action' => 'indexOutlinks'), true, 6);
MenuMain::getInstance()->add('General_Actions', 'General_Downloads', array('module' => 'Actions', 'action' => 'indexDownloads'), true, 7);
if ($this->isSiteSearchEnabled()) {
MenuMain::getInstance()->add('General_Actions', 'Actions_SubmenuSitesearch', array('module' => 'Actions', 'action' => 'indexSiteSearch'), true, 5);
}
}
protected function isSiteSearchEnabled()
{
$idSite = Common::getRequestVar('idSite', 0, 'int');
$idSites = Common::getRequestVar('idSites', '', 'string');
$idSites = Site::getIdSitesFromIdSitesString($idSites, true);
if (!empty($idSite)) {
@ -523,63 +128,20 @@ class Actions extends \Piwik\Plugin
return true;
}
static public function checkCustomVariablesPluginEnabled()
public static function checkCustomVariablesPluginEnabled()
{
if (!self::isCustomVariablesPluginsEnabled()) {
throw new \Exception("To Track Site Search Categories, please ask the Piwik Administrator to enable the 'Custom Variables' plugin in Settings > Plugins.");
}
}
static protected function isCustomVariablesPluginsEnabled()
public static function isCustomVariablesPluginsEnabled()
{
return \Piwik\Plugin\Manager::getInstance()->isPluginActivated('CustomVariables');
}
public function configureViewDataTable(ViewDataTable $view)
{
switch ($view->requestConfig->apiMethodToRequestDataTable) {
case 'Actions.getPageUrls':
$this->configureViewForPageUrls($view);
break;
case 'Actions.getEntryPageUrls':
$this->configureViewForEntryPageUrls($view);
break;
case 'Actions.getExitPageUrls':
$this->configureViewForExitPageUrls($view);
break;
case 'Actions.getSiteSearchKeywords':
$this->configureViewForSiteSearchKeywords($view);
break;
case 'Actions.getSiteSearchNoResultKeywords':
$this->configureViewForSiteSearchNoResultKeywords($view);
break;
case 'Actions.getSiteSearchCategories':
$this->configureViewForSiteSearchCategories($view);
break;
case 'Actions.getPageUrlsFollowingSiteSearch':
$this->configureViewForGetPageUrlsOrTitlesFollowingSiteSearch($view, false);
break;
case 'Actions.getPageTitlesFollowingSiteSearch':
$this->configureViewForGetPageUrlsOrTitlesFollowingSiteSearch($view, true);
break;
case 'Actions.getPageTitles':
$this->configureViewForGetPageTitles($view);
break;
case 'Actions.getEntryPageTitles':
$this->configureViewForGetEntryPageTitles($view);
break;
case 'Actions.getExitPageTitles':
$this->configureViewForGetExitPageTitles($view);
break;
case 'Actions.getDownloads':
$this->configureViewForGetDownloads($view);
break;
case 'Actions.getOutlinks':
$this->configureViewForGetOutlinks($view);
break;
}
if ($this->pluginName == $view->requestConfig->getApiModuleToRequest()) {
if ($view->isRequestingSingleDataTable()) {
// make sure custom visualizations are shown on actions reports
@ -591,40 +153,6 @@ class Actions extends \Piwik\Plugin
}
}
private function addBaseDisplayProperties(ViewDataTable $view)
{
$view->config->datatable_js_type = 'ActionsDataTable';
$view->config->search_recursive = true;
$view->config->show_table_all_columns = false;
$view->requestConfig->filter_limit = self::ACTIONS_REPORT_ROWS_DISPLAY;
$view->config->show_all_views_icons = false;
if ($view->isViewDataTableId(HtmlTable::ID)) {
$view->config->show_embedded_subtable = true;
}
// if the flat parameter is not provided, make sure it is set to 0 in the URL,
// so users can see that they can set it to 1 (see #3365)
$view->config->custom_parameters = array('flat' => 0);
if (Request::shouldLoadExpanded()) {
if ($view->isViewDataTableId(HtmlTable::ID)) {
$view->config->show_expanded = true;
}
$view->config->filters[] = function ($dataTable) {
Actions::setDataTableRowLevels($dataTable);
};
}
$view->config->filters[] = function ($dataTable) use ($view) {
if ($view->isViewDataTableId(HtmlTable::ID)) {
$view->config->datatable_css_class = 'dataTableActions';
}
};
}
/**
* @param \Piwik\DataTable $dataTable
* @param int $level
@ -641,297 +169,5 @@ class Actions extends \Piwik\Plugin
}
}
private function addExcludeLowPopDisplayProperties(ViewDataTable $view)
{
if (Common::getRequestVar('enable_filter_excludelowpop', '0', 'string') != '0') {
$view->requestConfig->filter_excludelowpop = 'nb_hits';
$view->requestConfig->filter_excludelowpop_value = function () {
// computing minimum value to exclude (2 percent of the total number of actions)
$visitsInfo = \Piwik\Plugins\VisitsSummary\Controller::getVisitsSummary()->getFirstRow();
$nbActions = $visitsInfo->getColumn('nb_actions');
$nbActionsLowPopulationThreshold = floor(0.02 * $nbActions);
// we remove 1 to make sure some actions/downloads are displayed in the case we have a very few of them
// and each of them has 1 or 2 hits...
return min($visitsInfo->getColumn('max_actions') - 1, $nbActionsLowPopulationThreshold - 1);
};
}
}
private function addPageDisplayProperties(ViewDataTable $view)
{
$view->config->addTranslations(array(
'nb_hits' => Piwik::translate('General_ColumnPageviews'),
'nb_visits' => Piwik::translate('General_ColumnUniquePageviews'),
'avg_time_on_page' => Piwik::translate('General_ColumnAverageTimeOnPage'),
'bounce_rate' => Piwik::translate('General_ColumnBounceRate'),
'exit_rate' => Piwik::translate('General_ColumnExitRate'),
'avg_time_generation' => Piwik::translate('General_ColumnAverageGenerationTime'),
));
// prettify avg_time_on_page column
$getPrettyTimeFromSeconds = '\Piwik\MetricsFormatter::getPrettyTimeFromSeconds';
$view->config->filters[] = array('ColumnCallbackReplace', array('avg_time_on_page', $getPrettyTimeFromSeconds));
// prettify avg_time_generation column
$avgTimeCallback = function ($time) {
return $time ? MetricsFormatter::getPrettyTimeFromSeconds($time, true, true, false) : "-";
};
$view->config->filters[] = array('ColumnCallbackReplace', array('avg_time_generation', $avgTimeCallback));
// add avg_generation_time tooltip
$tooltipCallback = function ($hits, $min, $max) {
if (!$hits) {
return false;
}
return Piwik::translate("Actions_AvgGenerationTimeTooltip", array(
$hits,
"<br />",
MetricsFormatter::getPrettyTimeFromSeconds($min),
MetricsFormatter::getPrettyTimeFromSeconds($max)
));
};
$view->config->filters[] = array('ColumnCallbackAddMetadata',
array(
array('nb_hits_with_time_generation', 'min_time_generation', 'max_time_generation'),
'avg_time_generation_tooltip',
$tooltipCallback
)
);
$this->addExcludeLowPopDisplayProperties($view);
}
public function configureViewForPageUrls(ViewDataTable $view)
{
$view->config->addTranslation('label', Piwik::translate('Actions_ColumnPageURL'));
$view->config->columns_to_display = array('label', 'nb_hits', 'nb_visits', 'bounce_rate',
'avg_time_on_page', 'exit_rate', 'avg_time_generation');
$this->addPageDisplayProperties($view);
$this->addBaseDisplayProperties($view);
}
public function configureViewForEntryPageUrls(ViewDataTable $view)
{
// link to the page, not just the report, but only if not a widget
$widget = Common::getRequestVar('widget', false);
$view->config->self_url = Request::getCurrentUrlWithoutGenericFilters(array(
'module' => 'Actions',
'action' => $widget === false ? 'indexEntryPageUrls' : 'getEntryPageUrls'
));
$view->config->addTranslations(array(
'label' => Piwik::translate('Actions_ColumnEntryPageURL'),
'entry_bounce_count' => Piwik::translate('General_ColumnBounces'),
'entry_nb_visits' => Piwik::translate('General_ColumnEntrances'))
);
$view->config->title = Piwik::translate('Actions_SubmenuPagesEntry');
$view->config->addRelatedReport('Actions.getEntryPageTitles', Piwik::translate('Actions_EntryPageTitles'));
$view->config->columns_to_display = array('label', 'entry_nb_visits', 'entry_bounce_count', 'bounce_rate');
$view->requestConfig->filter_sort_column = 'entry_nb_visits';
$view->requestConfig->filter_sort_order = 'desc';
$this->addPageDisplayProperties($view);
$this->addBaseDisplayProperties($view);
}
public function configureViewForExitPageUrls(ViewDataTable $view)
{
// link to the page, not just the report, but only if not a widget
$widget = Common::getRequestVar('widget', false);
$view->config->self_url = Request::getCurrentUrlWithoutGenericFilters(array(
'module' => 'Actions',
'action' => $widget === false ? 'indexExitPageUrls' : 'getExitPageUrls'
));
$view->config->addTranslations(array(
'label' => Piwik::translate('Actions_ColumnExitPageURL'),
'exit_nb_visits' => Piwik::translate('General_ColumnExits'))
);
$view->config->title = Piwik::translate('Actions_SubmenuPagesExit');
$view->config->addRelatedReport('Actions.getExitPageTitles', Piwik::translate('Actions_ExitPageTitles'));
$view->config->columns_to_display = array('label', 'exit_nb_visits', 'nb_visits', 'exit_rate');
$view->requestConfig->filter_sort_column = 'exit_nb_visits';
$view->requestConfig->filter_sort_order = 'desc';
$this->addPageDisplayProperties($view);
$this->addBaseDisplayProperties($view);
}
private function addSiteSearchDisplayProperties(ViewDataTable $view)
{
$view->config->addTranslations(array(
'nb_visits' => Piwik::translate('Actions_ColumnSearches'),
'exit_rate' => str_replace("% ", "%&nbsp;", Piwik::translate('Actions_ColumnSearchExits')),
'nb_pages_per_search' => Piwik::translate('Actions_ColumnPagesPerSearch')
));
$view->config->show_bar_chart = false;
$view->config->show_table_all_columns = false;
}
public function configureViewForSiteSearchKeywords(ViewDataTable $view)
{
$view->config->addTranslation('label', Piwik::translate('General_ColumnKeyword'));
$view->config->columns_to_display = array('label', 'nb_visits', 'nb_pages_per_search', 'exit_rate');
$this->addSiteSearchDisplayProperties($view);
}
public function configureViewForSiteSearchNoResultKeywords(ViewDataTable $view)
{
$view->config->addTranslation('label', Piwik::translate('Actions_ColumnNoResultKeyword'));
$view->config->columns_to_display = array('label', 'nb_visits', 'exit_rate');
$this->addSiteSearchDisplayProperties($view);
}
public function configureViewForSiteSearchCategories(ViewDataTable $view)
{
$view->config->addTranslations(array(
'label' => Piwik::translate('Actions_ColumnSearchCategory'),
'nb_visits' => Piwik::translate('Actions_ColumnSearches'),
'nb_pages_per_search' => Piwik::translate('Actions_ColumnPagesPerSearch')
));
$view->config->columns_to_display = array('label', 'nb_visits', 'nb_pages_per_search');
$view->config->show_table_all_columns = false;
$view->config->show_bar_chart = false;
if ($view->isViewDataTableId(HtmlTable::ID)) {
$view->config->disable_row_evolution = false;
}
}
public function configureViewForGetPageUrlsOrTitlesFollowingSiteSearch(ViewDataTable $view, $isTitle)
{
$title = $isTitle ? Piwik::translate('Actions_WidgetPageTitlesFollowingSearch')
: Piwik::translate('Actions_WidgetPageUrlsFollowingSearch');
$relatedReports = array(
'Actions.getPageTitlesFollowingSiteSearch' => Piwik::translate('Actions_WidgetPageTitlesFollowingSearch'),
'Actions.getPageUrlsFollowingSiteSearch' => Piwik::translate('Actions_WidgetPageUrlsFollowingSearch'),
);
$view->config->addRelatedReports($relatedReports);
$view->config->addTranslations(array(
'label' => Piwik::translate('General_ColumnDestinationPage'),
'nb_hits_following_search' => Piwik::translate('General_ColumnViewedAfterSearch'),
'nb_hits' => Piwik::translate('General_ColumnTotalPageviews')
));
$view->config->title = $title;
$view->config->columns_to_display = array('label', 'nb_hits_following_search', 'nb_hits');
$view->config->show_exclude_low_population = false;
$view->requestConfig->filter_sort_column = 'nb_hits_following_search';
$view->requestConfig->filter_sort_order = 'desc';
$this->addExcludeLowPopDisplayProperties($view);
$this->addBaseDisplayProperties($view);
}
public function configureViewForGetPageTitles(ViewDataTable $view)
{
// link to the page, not just the report, but only if not a widget
$widget = Common::getRequestVar('widget', false);
$view->config->self_url = Request::getCurrentUrlWithoutGenericFilters(array(
'module' => 'Actions',
'action' => $widget === false ? 'indexPageTitles' : 'getPageTitles'
));
$view->config->title = Piwik::translate('Actions_SubmenuPageTitles');
$view->config->addRelatedReports(array(
'Actions.getEntryPageTitles' => Piwik::translate('Actions_EntryPageTitles'),
'Actions.getExitPageTitles' => Piwik::translate('Actions_ExitPageTitles'),
));
$view->config->addTranslation('label', Piwik::translate('Actions_ColumnPageName'));
$view->config->columns_to_display = array('label', 'nb_hits', 'nb_visits', 'bounce_rate',
'avg_time_on_page', 'exit_rate', 'avg_time_generation');
$this->addPageDisplayProperties($view);
$this->addBaseDisplayProperties($view);
}
public function configureViewForGetEntryPageTitles(ViewDataTable $view)
{
$entryPageUrlAction =
Common::getRequestVar('widget', false) === false ? 'indexEntryPageUrls' : 'getEntryPageUrls';
$view->config->addTranslations(array(
'label' => Piwik::translate('Actions_ColumnEntryPageTitle'),
'entry_bounce_count' => Piwik::translate('General_ColumnBounces'),
'entry_nb_visits' => Piwik::translate('General_ColumnEntrances'),
));
$view->config->addRelatedReports(array(
'Actions.getPageTitles' => Piwik::translate('Actions_SubmenuPageTitles'),
"Actions.$entryPageUrlAction" => Piwik::translate('Actions_SubmenuPagesEntry')
));
$view->config->columns_to_display = array('label', 'entry_nb_visits', 'entry_bounce_count', 'bounce_rate');
$view->config->title = Piwik::translate('Actions_EntryPageTitles');
$view->requestConfig->filter_sort_column = 'entry_nb_visits';
$this->addPageDisplayProperties($view);
$this->addBaseDisplayProperties($view);
}
public function configureViewForGetExitPageTitles(ViewDataTable $view)
{
$exitPageUrlAction =
Common::getRequestVar('widget', false) === false ? 'indexExitPageUrls' : 'getExitPageUrls';
$view->config->addTranslations(array(
'label' => Piwik::translate('Actions_ColumnExitPageTitle'),
'exit_nb_visits' => Piwik::translate('General_ColumnExits'),
));
$view->config->addRelatedReports(array(
'Actions.getPageTitles' => Piwik::translate('Actions_SubmenuPageTitles'),
"Actions.$exitPageUrlAction" => Piwik::translate('Actions_SubmenuPagesExit'),
));
$view->config->title = Piwik::translate('Actions_ExitPageTitles');
$view->config->columns_to_display = array('label', 'exit_nb_visits', 'nb_visits', 'exit_rate');
$this->addPageDisplayProperties($view);
$this->addBaseDisplayProperties($view);
}
public function configureViewForGetDownloads(ViewDataTable $view)
{
$view->config->addTranslations(array(
'label' => Piwik::translate('Actions_ColumnDownloadURL'),
'nb_visits' => Piwik::translate('Actions_ColumnUniqueDownloads'),
'nb_hits' => Piwik::translate('General_Downloads'),
));
$view->config->columns_to_display = array('label', 'nb_visits', 'nb_hits');
$view->config->show_exclude_low_population = false;
$this->addBaseDisplayProperties($view);
}
public function configureViewForGetOutlinks(ViewDataTable $view)
{
$view->config->addTranslations(array(
'label' => Piwik::translate('Actions_ColumnClickedURL'),
'nb_visits' => Piwik::translate('Actions_ColumnUniqueClicks'),
'nb_hits' => Piwik::translate('Actions_ColumnClicks'),
));
$view->config->columns_to_display = array('label', 'nb_visits', 'nb_hits');
$view->config->show_exclude_low_population = false;
$this->addBaseDisplayProperties($view);
}
}

View file

@ -0,0 +1,71 @@
<?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\Actions;
use Piwik\Common;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visit;
/**
* This class represents an outlink.
* This is a particular type of Action: it has no 'name'
*
*/
class ActionClickUrl extends Action
{
public function __construct(Request $request)
{
parent::__construct(self::TYPE_OUTLINK, $request);
$this->setActionUrlWithoutExcludingParameters($request->getParam('link'));
}
public static function shouldHandle(Request $request)
{
$outlinkUrl = $request->getParam('link');
return !empty($outlinkUrl);
}
protected function getActionsToLookup()
{
return array(
// Note: we do not normalize outlink URL
'idaction_url' => array($this->getActionUrl(), $this->getActionType())
);
}
public function writeDebugInfo()
{
parent::writeDebugInfo();
if ($this->detectActionIsOutlinkOnAliasHost($this, $this->request->getIdSite())) {
Common::printDebug("INFO: The outlink URL host is one of the known host for this website. ");
}
}
/**
* Detect whether action is an outlink given host aliases
*
* @param Action $action
* @return bool true if the outlink the visitor clicked on points to one of the known hosts for this website
*/
protected function detectActionIsOutlinkOnAliasHost(Action $action, $idSite)
{
$decodedActionUrl = $action->getActionUrl();
$actionUrlParsed = @parse_url($decodedActionUrl);
if (!isset($actionUrlParsed['host'])) {
return false;
}
return Visit::isHostKnownAliasHost($actionUrlParsed['host'], $idSite);
}
}

View file

@ -0,0 +1,41 @@
<?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\Actions;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
/**
* This class represents a download.
* This is a particular type of Action: it has no 'name'
*/
class ActionDownloadUrl extends Action
{
public function __construct(Request $request)
{
parent::__construct(self::TYPE_DOWNLOAD, $request);
$this->setActionUrlWithoutExcludingParameters($request->getParam('download'));
}
public static function shouldHandle(Request $request)
{
$downloadUrl = $request->getParam('download');
return !empty($downloadUrl);
}
protected function getActionsToLookup()
{
return array(
// Note: we do not normalize download URL
'idaction_url' => array($this->getActionUrl(), $this->getActionType())
);
}
}

View file

@ -0,0 +1,270 @@
<?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\Actions;
use Piwik\Common;
use Piwik\Tracker\Action;
use Piwik\Tracker\PageUrl;
use Piwik\Tracker\Request;
use Piwik\Tracker\Cache;
use Piwik\UrlHelper;
/**
* This class represents a search on the site.
* - Its name is the search keyword
* - by default the URL is not recorded (since it's not used)
* - tracks site search result count and site search category as custom variables
*
*/
class ActionSiteSearch extends Action
{
private $searchCategory = false;
private $searchCount = false;
const CVAR_KEY_SEARCH_CATEGORY = '_pk_scat';
const CVAR_KEY_SEARCH_COUNT = '_pk_scount';
const CVAR_INDEX_SEARCH_CATEGORY = '4';
const CVAR_INDEX_SEARCH_COUNT = '5';
public function __construct(Request $request, $detect = true)
{
parent::__construct(Action::TYPE_SITE_SEARCH, $request);
$this->originalUrl = $request->getParam('url');
if ($detect) {
$this->isSearchDetected();
}
}
public static function shouldHandle(Request $request)
{
$search = new self($request, false);
return $search->detectSiteSearch($request->getParam('url'));
}
protected function getActionsToLookup()
{
return array(
'idaction_name' => array($this->getActionName(), Action::TYPE_SITE_SEARCH),
);
}
public function getIdActionUrl()
{
// Site Search, by default, will not track URL. We do not want URL to appear as "Page URL not defined"
// so we specifically set it to NULL in the table (the archiving query does IS NOT NULL)
return null;
}
public function getCustomFloatValue()
{
return $this->request->getPageGenerationTime();
}
protected function isSearchDetected()
{
$siteSearch = $this->detectSiteSearch($this->originalUrl);
if (empty($siteSearch)) {
return false;
}
list($actionName, $url, $category, $count) = $siteSearch;
if (!empty($category)) {
$this->searchCategory = trim($category);
}
if ($count !== false) {
$this->searchCount = $count;
}
$this->setActionName($actionName);
$this->setActionUrl($url);
return true;
}
public function getCustomVariables()
{
$customVariables = parent::getCustomVariables();
// Enrich Site Search actions with Custom Variables, overwriting existing values
if (!empty($this->searchCategory)) {
if (!empty($customVariables['custom_var_k' . self::CVAR_INDEX_SEARCH_CATEGORY])) {
Common::printDebug("WARNING: Overwriting existing Custom Variable in slot " . self::CVAR_INDEX_SEARCH_CATEGORY . " for this page view");
}
$customVariables['custom_var_k' . self::CVAR_INDEX_SEARCH_CATEGORY] = self::CVAR_KEY_SEARCH_CATEGORY;
$customVariables['custom_var_v' . self::CVAR_INDEX_SEARCH_CATEGORY] = Request::truncateCustomVariable($this->searchCategory);
}
if ($this->searchCount !== false) {
if (!empty($customVariables['custom_var_k' . self::CVAR_INDEX_SEARCH_COUNT])) {
Common::printDebug("WARNING: Overwriting existing Custom Variable in slot " . self::CVAR_INDEX_SEARCH_COUNT . " for this page view");
}
$customVariables['custom_var_k' . self::CVAR_INDEX_SEARCH_COUNT] = self::CVAR_KEY_SEARCH_COUNT;
$customVariables['custom_var_v' . self::CVAR_INDEX_SEARCH_COUNT] = (int)$this->searchCount;
}
return $customVariables;
}
protected function detectSiteSearchFromUrl($website, $parsedUrl)
{
$doRemoveSearchParametersFromUrl = true;
$separator = '&';
$count = $actionName = $categoryName = false;
$keywordParameters = isset($website['sitesearch_keyword_parameters'])
? $website['sitesearch_keyword_parameters']
: array();
$queryString = (!empty($parsedUrl['query']) ? $parsedUrl['query'] : '') . (!empty($parsedUrl['fragment']) ? $separator . $parsedUrl['fragment'] : '');
$parametersRaw = UrlHelper::getArrayFromQueryString($queryString);
// strtolower the parameter names for smooth site search detection
$parameters = array();
foreach ($parametersRaw as $k => $v) {
$parameters[Common::mb_strtolower($k)] = $v;
}
// decode values if they were sent from a client using another charset
$pageEncoding = $this->request->getParam('cs');
PageUrl::reencodeParameters($parameters, $pageEncoding);
// Detect Site Search keyword
foreach ($keywordParameters as $keywordParameterRaw) {
$keywordParameter = Common::mb_strtolower($keywordParameterRaw);
if (!empty($parameters[$keywordParameter])) {
$actionName = $parameters[$keywordParameter];
break;
}
}
if (empty($actionName)) {
return false;
}
$categoryParameters = isset($website['sitesearch_category_parameters'])
? $website['sitesearch_category_parameters']
: array();
foreach ($categoryParameters as $categoryParameterRaw) {
$categoryParameter = Common::mb_strtolower($categoryParameterRaw);
if (!empty($parameters[$categoryParameter])) {
$categoryName = $parameters[$categoryParameter];
break;
}
}
if (isset($parameters['search_count'])
&& $this->isValidSearchCount($parameters['search_count'])
) {
$count = $parameters['search_count'];
}
// Remove search kwd from URL
if ($doRemoveSearchParametersFromUrl) {
// @see excludeQueryParametersFromUrl()
// Excluded the detected parameters from the URL
$parametersToExclude = array($categoryParameterRaw, $keywordParameterRaw);
if (isset($parsedUrl['query'])) {
$parsedUrl['query'] = UrlHelper::getQueryStringWithExcludedParameters(UrlHelper::getArrayFromQueryString($parsedUrl['query']), $parametersToExclude);
}
if (isset($parsedUrl['fragment'])) {
$parsedUrl['fragment'] = UrlHelper::getQueryStringWithExcludedParameters(UrlHelper::getArrayFromQueryString($parsedUrl['fragment']), $parametersToExclude);
}
}
$url = UrlHelper::getParseUrlReverse($parsedUrl);
if (is_array($actionName)) {
$actionName = reset($actionName);
}
$actionName = PageUrl::urldecodeValidUtf8($actionName);
$actionName = trim($actionName);
if (empty($actionName)) {
return false;
}
if (is_array($categoryName)) {
$categoryName = reset($categoryName);
}
$categoryName = PageUrl::urldecodeValidUtf8($categoryName);
$categoryName = trim($categoryName);
return array($url, $actionName, $categoryName, $count);
}
protected function isValidSearchCount($count)
{
return is_numeric($count) && $count >= 0;
}
public function detectSiteSearch($originalUrl)
{
$website = Cache::getCacheWebsiteAttributes($this->request->getIdSite());
if (empty($website['sitesearch'])) {
Common::printDebug("Internal 'Site Search' tracking is not enabled for this site. ");
return false;
}
$actionName = $url = $categoryName = $count = false;
$originalUrl = PageUrl::cleanupUrl($originalUrl);
// Detect Site search from Tracking API parameters rather than URL
$searchKwd = $this->request->getParam('search');
if (!empty($searchKwd)) {
$actionName = $searchKwd;
$isCategoryName = $this->request->getParam('search_cat');
if (!empty($isCategoryName)) {
$categoryName = $isCategoryName;
}
$isCount = $this->request->getParam('search_count');
if ($this->isValidSearchCount($isCount)) {
$count = $isCount;
}
}
if (empty($actionName)) {
$parsedUrl = @parse_url($originalUrl);
// Detect Site Search from URL query parameters
if (!empty($parsedUrl['query']) || !empty($parsedUrl['fragment'])) {
// array($url, $actionName, $categoryName, $count);
$searchInfo = $this->detectSiteSearchFromUrl($website, $parsedUrl);
if (!empty($searchInfo)) {
list ($url, $actionName, $categoryName, $count) = $searchInfo;
}
}
}
$actionName = trim($actionName);
$categoryName = trim($categoryName);
if (empty($actionName)) {
Common::printDebug("(this is not a Site Search request)");
return false;
}
Common::printDebug("Detected Site Search keyword '$actionName'. ");
if (!empty($categoryName)) {
Common::printDebug("- Detected Site Search Category '$categoryName'. ");
}
if ($count !== false) {
Common::printDebug("- Search Results Count was '$count'. ");
}
if ($url != $originalUrl) {
Common::printDebug("NOTE: The Page URL was changed / removed, during the Site Search detection, was '$originalUrl', now is '$url'");
}
return array(
$actionName,
$url,
$categoryName,
$count
);
}
}

View file

@ -1,6 +1,6 @@
<?php
/**
* Piwik - Open source web analytics
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
@ -9,10 +9,10 @@
namespace Piwik\Plugins\Actions;
use Piwik\DataTable;
use Piwik\Metrics;
use Piwik\Metrics as PiwikMetrics;
use Piwik\RankingQuery;
use Piwik\Tracker\Action;
use Piwik\Tracker\ActionSiteSearch;
use Piwik\Plugins\Actions\Actions\ActionSiteSearch;
/**
* Class encapsulating logic to process Day/Period Archiving for the Actions reports
@ -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,
);
static protected $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,
);
static public $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;
@ -121,7 +88,7 @@ class Archiver extends \Piwik\Plugin\Archiver
/**
* @return string
*/
static public function getWhereClauseActionIsNotEvent()
public static function getWhereClauseActionIsNotEvent()
{
return " AND log_link_visit_action.idaction_event_category IS NULL";
}
@ -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,14 @@ 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";
$select = $this->addMetricsToSelect($select, $metricsConfig);
$from = array(
"log_link_visit_action",
@ -211,29 +162,28 @@ 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('url_prefix');
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));
}
@ -241,12 +191,33 @@ class Archiver extends \Piwik\Plugin\Archiver
// 1) No result Keywords
// 2) For each page view, count number of times the referrer page was a Site Search
if ($this->isSiteSearchEnabled()) {
$this->updateQuerySelectFromForSiteSearch($select, $from);
$this->updateQuerySelectFromForSiteSearch($select, $from);
}
$this->archiveDayQueryProcess($select, $from, $where, $orderBy, $groupBy, "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, $orderBy, $groupBy, "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 +225,7 @@ class Archiver extends \Piwik\Plugin\Archiver
return $this->isSiteSearchEnabled;
}
protected function archiveDayQueryProcess($select, $from, $where, $orderBy, $groupBy, $sprintfField, $rankingQuery = false)
protected function archiveDayQueryProcess($select, $from, $where, $groupBy, $orderBy, $sprintfField, RankingQuery $rankingQuery = null, $metricsConfig = array())
{
$select = sprintf($select, $sprintfField);
@ -266,12 +237,12 @@ class Archiver extends \Piwik\Plugin\Archiver
// apply ranking query
if ($rankingQuery) {
$querySql = $rankingQuery->generateQuery($querySql);
$querySql = $rankingQuery->generateRankingQuery($querySql);
}
// 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 +256,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 +271,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,22 +279,22 @@ 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";
$this->archiveDayQueryProcess($select, $from, $where, $orderBy, $groupBy, "visit_entry_idaction_url", $rankingQuery);
$this->archiveDayQueryProcess($select, $from, $where, $groupBy, $orderBy, "visit_entry_idaction_url", $rankingQuery);
$this->archiveDayQueryProcess($select, $from, $where, $orderBy, $groupBy, "visit_entry_idaction_name", $rankingQuery);
$this->archiveDayQueryProcess($select, $from, $where, $groupBy, $orderBy, "visit_entry_idaction_name", $rankingQuery);
}
/**
@ -336,8 +307,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 +319,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,19 +327,19 @@ 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";
$this->archiveDayQueryProcess($select, $from, $where, $orderBy, $groupBy, "visit_exit_idaction_url", $rankingQuery);
$this->archiveDayQueryProcess($select, $from, $where, $groupBy, $orderBy, "visit_exit_idaction_url", $rankingQuery);
$this->archiveDayQueryProcess($select, $from, $where, $orderBy, $groupBy, "visit_exit_idaction_name", $rankingQuery);
$this->archiveDayQueryProcess($select, $from, $where, $groupBy, $orderBy, "visit_exit_idaction_name", $rankingQuery);
return array($rankingQuery, $extraSelects, $from, $orderBy, $select, $where, $groupBy);
}
@ -382,10 +353,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 +364,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,20 +372,20 @@ 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";
$this->archiveDayQueryProcess($select, $from, $where, $orderBy, $groupBy, "idaction_url_ref", $rankingQuery);
$this->archiveDayQueryProcess($select, $from, $where, $groupBy, $orderBy, "idaction_url_ref", $rankingQuery);
$this->archiveDayQueryProcess($select, $from, $where, $orderBy, $groupBy, "idaction_name_ref", $rankingQuery);
$this->archiveDayQueryProcess($select, $from, $where, $groupBy, $orderBy, "idaction_name_ref", $rankingQuery);
}
/**
@ -437,10 +408,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);
}
@ -461,14 +432,13 @@ class Archiver extends \Piwik\Plugin\Archiver
$this->getProcessor()->insertBlobRecord($recordName, $report);
}
protected function insertDownloadsReports()
{
$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()
@ -476,8 +446,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()
@ -492,21 +462,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_PAGE_NB_HITS)));
$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);
}
@ -522,8 +492,9 @@ class Archiver extends \Piwik\Plugin\Archiver
ArchivingHelper::$maximumRowsInDataTableLevelZero,
ArchivingHelper::$maximumRowsInSubDataTable,
ArchivingHelper::$columnToSortByBeforeTruncation,
self::$columnsAggregationOperation,
self::$columnsToRenameAfterAggregation
Metrics::$columnsAggregationOperation,
Metrics::$columnsToRenameAfterAggregation,
$countRowsRecursive = array()
);
$dataTableToSum = array(
@ -537,7 +508,8 @@ class Archiver extends \Piwik\Plugin\Archiver
ArchivingHelper::$maximumRowsInSubDataTable,
ArchivingHelper::$columnToSortByBeforeTruncation,
$aggregation,
self::$columnsToRenameAfterAggregation
Metrics::$columnsToRenameAfterAggregation,
$countRowsRecursive = array()
);
$this->getProcessor()->aggregateNumericMetrics($this->getMetricNames());

View file

@ -1,6 +1,6 @@
<?php
/**
* Piwik - Open source web analytics
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
@ -10,11 +10,10 @@ namespace Piwik\Plugins\Actions;
use PDOStatement;
use Piwik\Config;
use Piwik\DataTable\Manager;
use Piwik\DataTable\Row;
use Piwik\DataTable;
use Piwik\DataTable\Row\DataTableSummaryRow;
use Piwik\Metrics;
use Piwik\DataTable;
use Piwik\DataTable\Row;
use Piwik\Metrics as PiwikMetrics;
use Piwik\Piwik;
use Piwik\Tracker\Action;
use Piwik\Tracker\PageUrl;
@ -38,7 +37,7 @@ class ArchivingHelper
* @param array $actionsTablesByType
* @return int
*/
static public function updateActionsTableWithRowQuery($query, $fieldQueried, & $actionsTablesByType)
public static function updateActionsTableWithRowQuery($query, $fieldQueried, & $actionsTablesByType, $metricsConfig)
{
$rowsProcessed = 0;
while ($row = $query->fetch()) {
@ -51,7 +50,11 @@ 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 (in_array($row['type'], array(Action::TYPE_CONTENT, Action::TYPE_EVENT))) {
continue;
}
// This will appear as <url /> in the API, which is actually very important to keep
@ -107,15 +110,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;
}
}
@ -123,17 +126,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]);
}
}
@ -147,7 +150,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);
@ -157,7 +160,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) {
@ -176,7 +179,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
));
@ -194,16 +197,16 @@ class ArchivingHelper
if (($idSubtable = $row->getIdSubDataTable()) !== null
|| $id === DataTable::ID_SUMMARY_ROW
) {
if ($idSubtable !== null) {
$subtable = Manager::getInstance()->getTable($idSubtable);
self::deleteInvalidSummedColumnsFromDataTable($subtable);
$subTable = $row->getSubtable();
if ($subTable) {
self::deleteInvalidSummedColumnsFromDataTable($subTable);
}
if ($row instanceof DataTableSummaryRow) {
$row->recalculate();
}
foreach (Archiver::$columnsToDeleteAfterAggregation as $name) {
foreach (Metrics::$columnsToDeleteAfterAggregation as $name) {
$row->deleteColumn($name);
}
}
@ -263,38 +266,45 @@ 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;
return $newValue;
}
static public $maximumRowsInDataTableLevelZero;
static public $maximumRowsInSubDataTable;
static public $columnToSortByBeforeTruncation;
public static $maximumRowsInDataTableLevelZero;
public static $maximumRowsInSubDataTable;
public static $columnToSortByBeforeTruncation;
static protected $actionUrlCategoryDelimiter = null;
static protected $actionTitleCategoryDelimiter = null;
static protected $defaultActionName = null;
static protected $defaultActionNameWhenNotDefined = null;
static protected $defaultActionUrlWhenNotDefined = null;
protected static $actionUrlCategoryDelimiter = null;
protected static $actionTitleCategoryDelimiter = null;
protected static $defaultActionName = null;
protected static $defaultActionNameWhenNotDefined = null;
protected static $defaultActionUrlWhenNotDefined = null;
static public function reloadConfig()
public static function reloadConfig()
{
// for BC, we read the old style delimiter first (see #1067)Row
$actionDelimiter = @Config::getInstance()->General['action_category_delimiter'];
@ -306,7 +316,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'];
@ -320,7 +330,7 @@ class ArchivingHelper
*
* @return Row
*/
static private function getDefaultRow()
private static function getDefaultRow()
{
static $row = false;
if ($row === false) {
@ -329,9 +339,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;
@ -347,13 +357,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.");
}
@ -390,7 +400,7 @@ class ArchivingHelper
* @param $type
* @return string
*/
static public function getUnknownActionName($type)
public static function getUnknownActionName($type)
{
if (empty(self::$defaultActionNameWhenNotDefined)) {
self::$defaultActionNameWhenNotDefined = Piwik::translate('General_NotDefined', Piwik::translate('Actions_ColumnPageName'));
@ -402,7 +412,6 @@ class ArchivingHelper
return self::$defaultActionUrlWhenNotDefined;
}
/**
* Explodes action name into an array of elements.
*
@ -425,7 +434,7 @@ class ArchivingHelper
* @param int $urlPrefix url prefix (only used for TYPE_PAGE_URL)
* @return array of exploded elements from $name
*/
static public function getActionExplodedNames($name, $type, $urlPrefix = null)
public static function getActionExplodedNames($name, $type, $urlPrefix = null)
{
// Site Search does not split Search keywords
if ($type == Action::TYPE_SITE_SEARCH) {
@ -477,7 +486,7 @@ class ArchivingHelper
/**
* Static cache to store Rows during processing
*/
static protected $cacheParsedAction = array();
protected static $cacheParsedAction = array();
public static function clearActionsCache()
{
@ -526,10 +535,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);
}
/**
@ -594,7 +603,12 @@ class ArchivingHelper
$urlFragment = $matches[3];
if (in_array($type, array(Action::TYPE_DOWNLOAD, Action::TYPE_OUTLINK))) {
return array(trim($urlHost), '/' . trim($urlPath));
$path = '/' . trim($urlPath);
if (!empty($urlFragment)) {
$path .= '#' . $urlFragment;
}
return array(trim($urlHost), $path);
}
$name = $urlPath;

View file

@ -0,0 +1,70 @@
<?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\Columns;
use Piwik\Piwik;
use Piwik\Plugin\Dimension\ActionDimension;
use Piwik\Plugins\Actions\Segment;
use Piwik\Tracker\Action;
use Exception;
/**
* This example dimension only defines a name and does not track any data. It's supposed to be only used in reports.
*
* See {@link http://developer.piwik.org/api-reference/Piwik/Columns\Dimension} for more information.
*/
class ActionType extends ActionDimension
{
private $types = array(
Action::TYPE_PAGE_URL => 'pageviews',
Action::TYPE_CONTENT => 'contents',
Action::TYPE_SITE_SEARCH => 'sitesearches',
Action::TYPE_EVENT => 'events',
Action::TYPE_OUTLINK => 'outlinks',
Action::TYPE_DOWNLOAD => 'downloads'
);
/**
* The name of the dimension which will be visible for instance in the UI of a related report and in the mobile app.
* @return string
*/
public function getName()
{
return Piwik::translate('Actions_ActionType');
}
protected function configureSegments()
{
$types = $this->types;
$segment = new Segment();
$segment->setSegment('actionType');
$segment->setName('Actions_ActionType');
$segment->setSqlSegment('log_action.type');
$segment->setType(Segment::TYPE_DIMENSION);
$segment->setAcceptedValues(sprintf('A type of action, such as: %s', implode(', ', $types)));
$segment->setSqlFilter(function ($type) use ($types) {
if (array_key_exists($type, $types)) {
return $type;
}
$index = array_search(strtolower(trim(urldecode($type))), $types);
if ($index === false) {
throw new Exception("actionType must be one of: " . implode(', ', $types));
}
return $index;
});
$segment->setSuggestedValuesCallback(function ($idSite, $maxSuggestionsToReturn) use ($types) {
return array_slice(array_values($types), 0, $maxSuggestionsToReturn);
});
$this->addSegment($segment);
}
}

View file

@ -0,0 +1,32 @@
<?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\Columns;
use Piwik\Piwik;
use Piwik\Plugin\Dimension\ActionDimension;
use Piwik\Plugins\Actions\Segment;
class ActionUrl extends ActionDimension
{
public function getName()
{
return Piwik::translate('Actions_ColumnActionURL');
}
protected function configureSegments()
{
$segment = new Segment();
$segment->setSegment('actionUrl');
$segment->setName('Actions_ColumnActionURL');
$segment->setUnionOfSegments(array('pageUrl', 'downloadUrl', 'outlinkUrl'));
$this->addSegment($segment);
}
}

View file

@ -0,0 +1,31 @@
<?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\Columns;
use Piwik\Piwik;
use Piwik\Plugin\Dimension\ActionDimension;
use Piwik\Plugins\Actions\Segment;
class ClickedUrl extends ActionDimension
{
public function getName()
{
return Piwik::translate('Actions_ColumnClickedURL');
}
protected function configureSegments()
{
$segment = new Segment();
$segment->setSegment('outlinkUrl');
$segment->setName('Actions_ColumnClickedURL');
$segment->setSqlSegment('log_link_visit_action.idaction_url');
$this->addSegment($segment);
}
}

View file

@ -0,0 +1,20 @@
<?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\Columns;
use Piwik\Columns\Dimension;
use Piwik\Piwik;
class DestinationPage extends Dimension
{
public function getName()
{
return Piwik::translate('General_ColumnDestinationPage');
}
}

View file

@ -0,0 +1,31 @@
<?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\Columns;
use Piwik\Piwik;
use Piwik\Plugin\Dimension\ActionDimension;
use Piwik\Plugins\Actions\Segment;
class DownloadUrl extends ActionDimension
{
public function getName()
{
return Piwik::translate('Actions_ColumnDownloadURL');
}
protected function configureSegments()
{
$segment = new Segment();
$segment->setSegment('downloadUrl');
$segment->setName('Actions_ColumnDownloadURL');
$segment->setSqlSegment('log_link_visit_action.idaction_url');
$this->addSegment($segment);
}
}

View file

@ -0,0 +1,52 @@
<?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\Columns;
use Piwik\Piwik;
use Piwik\Plugins\Actions\Segment;
use Piwik\Plugin\Dimension\VisitDimension;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
class EntryPageTitle extends VisitDimension
{
protected $columnName = 'visit_entry_idaction_name';
protected $columnType = 'INTEGER(11) UNSIGNED NOT NULL';
protected function configureSegments()
{
$segment = new Segment();
$segment->setSegment('entryPageTitle');
$segment->setName('Actions_ColumnEntryPageTitle');
$this->addSegment($segment);
}
/**
* @param Request $request
* @param Visitor $visitor
* @param Action|null $action
* @return mixed
*/
public function onNewVisit(Request $request, Visitor $visitor, $action)
{
$idActionName = false;
if (!empty($action)) {
$idActionName = $action->getIdActionNameForEntryAndExitIds();
}
return (int) $idActionName;
}
public function getName()
{
return Piwik::translate('Actions_ColumnEntryPageTitle');
}
}

View file

@ -0,0 +1,53 @@
<?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\Columns;
use Piwik\Piwik;
use Piwik\Plugins\Actions\Segment;
use Piwik\Plugin\Dimension\VisitDimension;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
class EntryPageUrl extends VisitDimension
{
protected $columnName = 'visit_entry_idaction_url';
protected $columnType = 'INTEGER(11) UNSIGNED NOT NULL';
protected function configureSegments()
{
$segment = new Segment();
$segment->setSegment('entryPageUrl');
$segment->setName('Actions_ColumnEntryPageURL');
$this->addSegment($segment);
}
/**
* @param Request $request
* @param Visitor $visitor
* @param Action|null $action
* @return mixed
*/
public function onNewVisit(Request $request, Visitor $visitor, $action)
{
$idActionUrl = false;
if (!empty($action)) {
$idActionUrl = $action->getIdActionUrlForEntryAndExitIds();
}
return (int) $idActionUrl;
}
public function getName()
{
return Piwik::translate('Actions_ColumnEntryPageURL');
}
}

View file

@ -0,0 +1,67 @@
<?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\Columns;
use Piwik\Piwik;
use Piwik\Plugins\Actions\Segment;
use Piwik\Plugin\Dimension\VisitDimension;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
class ExitPageTitle extends VisitDimension
{
protected $columnName = 'visit_exit_idaction_name';
protected $columnType = 'INTEGER(11) UNSIGNED NOT NULL';
protected function configureSegments()
{
$segment = new Segment();
$segment->setSegment('exitPageTitle');
$segment->setName('Actions_ColumnExitPageTitle');
$this->addSegment($segment);
}
/**
* @param Request $request
* @param Visitor $visitor
* @param Action|null $action
* @return int|bool
*/
public function onNewVisit(Request $request, Visitor $visitor, $action)
{
$idActionName = false;
if (!empty($action)) {
$idActionName = $action->getIdActionNameForEntryAndExitIds();
}
return (int) $idActionName;
}
/**
* @param Request $request
* @param Visitor $visitor
* @param Action|null $action
* @return int|bool
*/
public function onExistingVisit(Request $request, Visitor $visitor, $action)
{
if (empty($action)) {
return false;
}
return $action->getIdActionNameForEntryAndExitIds();
}
public function getName()
{
return Piwik::translate('Actions_ColumnExitPageTitle');
}
}

View file

@ -0,0 +1,73 @@
<?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\Columns;
use Piwik\Piwik;
use Piwik\Plugins\Actions\Segment;
use Piwik\Plugin\Dimension\VisitDimension;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
class ExitPageUrl extends VisitDimension
{
protected $columnName = 'visit_exit_idaction_url';
protected $columnType = 'INTEGER(11) UNSIGNED NULL DEFAULT 0';
protected function configureSegments()
{
$segment = new Segment();
$segment->setSegment('exitPageUrl');
$segment->setName('Actions_ColumnExitPageURL');
$this->addSegment($segment);
}
/**
* @param Request $request
* @param Visitor $visitor
* @param Action|null $action
* @return int|bool
*/
public function onNewVisit(Request $request, Visitor $visitor, $action)
{
$idActionUrl = false;
if (!empty($action)) {
$idActionUrl = $action->getIdActionUrlForEntryAndExitIds();
}
return (int) $idActionUrl;
}
/**
* @param Request $request
* @param Visitor $visitor
* @param Action|null $action
* @return int
*/
public function onExistingVisit(Request $request, Visitor $visitor, $action)
{
if (empty($action)) {
return false;
}
$id = $action->getIdActionUrlForEntryAndExitIds();
if (!empty($id)) {
$id = (int) $id;
}
return $id;
}
public function getName()
{
return Piwik::translate('Actions_ColumnExitPageURL');
}
}

View file

@ -0,0 +1,20 @@
<?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\Columns;
use Piwik\Columns\Dimension;
use Piwik\Piwik;
class Keyword extends Dimension
{
public function getName()
{
return Piwik::translate('General_ColumnKeyword');
}
}

View file

@ -0,0 +1,20 @@
<?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\Columns;
use Piwik\Columns\Dimension;
use Piwik\Piwik;
class KeywordwithNoSearchResult extends Dimension
{
public function getName()
{
return Piwik::translate('Actions_ColumnNoResultKeyword');
}
}

View file

@ -0,0 +1,108 @@
<?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\Columns\Metrics;
use Piwik\DataTable;
use Piwik\DataTable\Row;
use Piwik\Metrics;
use Piwik\Metrics\Formatter;
use Piwik\Piwik;
use Piwik\Plugin\ProcessedMetric;
use Piwik\Plugin\Report;
/**
* The average amount of time it takes to generate a page. Calculated as
*
* sum_time_generation / nb_hits_with_time_generation
*
* The above metrics are calculated during archiving. This metric is calculated before
* serving a report.
*/
class AveragePageGenerationTime extends ProcessedMetric
{
public function getName()
{
return 'avg_time_generation';
}
public function getTranslatedName()
{
return Piwik::translate('General_ColumnAverageGenerationTime');
}
public function getDependentMetrics()
{
return array('sum_time_generation', 'nb_hits_with_time_generation');
}
public function getTemporaryMetrics()
{
return array('sum_time_generation');
}
public function compute(Row $row)
{
$sumGenerationTime = $this->getMetric($row, 'sum_time_generation');
$hitsWithTimeGeneration = $this->getMetric($row, 'nb_hits_with_time_generation');
return Piwik::getQuotientSafe($sumGenerationTime, $hitsWithTimeGeneration, $precision = 3);
}
public function format($value, Formatter $formatter)
{
if ($formatter instanceof Formatter\Html
&& !$value
) {
return '-';
} else {
return $formatter->getPrettyTimeFromSeconds($value, $displayAsSentence = true);
}
}
public function beforeCompute($report, DataTable $table)
{
$hasTimeGeneration = array_sum($this->getMetricValues($table, 'sum_time_generation')) > 0;
if (!$hasTimeGeneration
&& $table->getRowsCount() != 0
&& !$this->hasAverageTimeGeneration($table)
) {
// No generation time: remove it from the API output and add it to empty_columns metadata, so that
// the columns can also be removed from the view
$table->filter('ColumnDelete', array(array(
Metrics::INDEX_PAGE_SUM_TIME_GENERATION,
Metrics::INDEX_PAGE_NB_HITS_WITH_TIME_GENERATION,
Metrics::INDEX_PAGE_MIN_TIME_GENERATION,
Metrics::INDEX_PAGE_MAX_TIME_GENERATION,
'sum_time_generation',
'nb_hits_with_time_generation',
'min_time_generation',
'max_time_generation'
)));
if ($table instanceof DataTable) {
$emptyColumns = $table->getMetadata(DataTable::EMPTY_COLUMNS_METADATA_NAME);
if (!is_array($emptyColumns)) {
$emptyColumns = array();
}
$emptyColumns[] = 'sum_time_generation';
$emptyColumns[] = 'avg_time_generation';
$emptyColumns[] = 'min_time_generation';
$emptyColumns[] = 'max_time_generation';
$table->setMetadata(DataTable::EMPTY_COLUMNS_METADATA_NAME, $emptyColumns);
}
}
return $hasTimeGeneration;
}
private function hasAverageTimeGeneration(DataTable $table)
{
return $table->getFirstRow()->getColumn('avg_time_generation') !== false;
}
}

View file

@ -0,0 +1,51 @@
<?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\Columns\Metrics;
use Piwik\DataTable\Row;
use Piwik\Metrics\Formatter;
use Piwik\Piwik;
use Piwik\Plugin\ProcessedMetric;
/**
* The average amount of time spent on a page. Calculated as:
*
* sum_time_spent / nb_visits
*
* sum_time_spent and nb_visits are calculated by Archiver classes.
*/
class AverageTimeOnPage extends ProcessedMetric
{
public function getName()
{
return 'avg_time_on_page';
}
public function getTranslatedName()
{
return Piwik::translate('General_ColumnAverageTimeOnPage');
}
public function compute(Row $row)
{
$sumTimeSpent = $this->getMetric($row, 'sum_time_spent');
$visits = $this->getMetric($row, 'nb_hits');
return Piwik::getQuotientSafe($sumTimeSpent, $visits, $precision = 0);
}
public function format($value, Formatter $formatter)
{
return $formatter->getPrettyTimeFromSeconds($value, $timeAsSentence = false);
}
public function getDependentMetrics()
{
return array('sum_time_spent', 'nb_hits');
}
}

Some files were not shown because too many files have changed in this diff Show more