forked from rebillar/site-accueil-insa
309 lines
12 KiB
PHP
309 lines
12 KiB
PHP
<?php
|
|
/**
|
|
* Matomo - free/libre analytics platform
|
|
*
|
|
* @link https://matomo.org
|
|
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
|
*
|
|
*/
|
|
namespace Piwik\Plugins\CoreVisualizations\Visualizations;
|
|
|
|
use Piwik\API\Request as ApiRequest;
|
|
use Piwik\Columns\Dimension;
|
|
use Piwik\Common;
|
|
use Piwik\DataTable\Row;
|
|
use Piwik\Metrics;
|
|
use Piwik\DataTable;
|
|
use Piwik\NumberFormatter;
|
|
use Piwik\Period;
|
|
use Piwik\Piwik;
|
|
use Piwik\Plugin\Visualization;
|
|
|
|
/**
|
|
* DataTable visualization that shows DataTable data in an HTML table.
|
|
*
|
|
* @property HtmlTable\Config $config
|
|
*/
|
|
class HtmlTable extends Visualization
|
|
{
|
|
const ID = 'table';
|
|
const TEMPLATE_FILE = "@CoreVisualizations/_dataTableViz_htmlTable.twig";
|
|
const FOOTER_ICON = 'icon-table';
|
|
const FOOTER_ICON_TITLE = 'General_DisplaySimpleTable';
|
|
|
|
public static function getDefaultConfig()
|
|
{
|
|
return new HtmlTable\Config();
|
|
}
|
|
|
|
public static function getDefaultRequestConfig()
|
|
{
|
|
return new HtmlTable\RequestConfig();
|
|
}
|
|
|
|
public function beforeLoadDataTable()
|
|
{
|
|
$this->checkRequestIsNotForMultiplePeriods();
|
|
|
|
if ($this->isComparing()) {
|
|
$request = $this->getRequestArray();
|
|
if (!empty($request['comparePeriods'])
|
|
&& count($request['comparePeriods']) == 1
|
|
) {
|
|
$this->requestConfig->request_parameters_to_modify['invert_compare_change_compute'] = 1;
|
|
}
|
|
|
|
// forward the comparisonIdSubtables var if present so it will be used when next/prev links are clicked
|
|
$comparisonIdSubtables = Common::getRequestVar('comparisonIdSubtables', false, 'string');
|
|
if (!empty($comparisonIdSubtables)) {
|
|
$comparisonIdSubtables = Common::unsanitizeInputValue($comparisonIdSubtables);
|
|
$this->config->custom_parameters['comparisonIdSubtables'] = $comparisonIdSubtables;
|
|
}
|
|
}
|
|
}
|
|
|
|
public function beforeRender()
|
|
{
|
|
if ($this->requestConfig->idSubtable
|
|
&& $this->config->show_embedded_subtable) {
|
|
|
|
$this->config->show_visualization_only = true;
|
|
}
|
|
|
|
if ($this->requestConfig->idSubtable) {
|
|
$this->config->show_totals_row = false;
|
|
}
|
|
|
|
foreach (Metrics::getMetricIdsToProcessReportTotal() as $metricId) {
|
|
$this->config->report_ratio_columns[] = Metrics::getReadableColumnName($metricId);
|
|
}
|
|
if (!empty($this->report)) {
|
|
foreach ($this->report->getMetricNamesToProcessReportTotals() as $metricName) {
|
|
$this->config->report_ratio_columns[] = $metricName;
|
|
}
|
|
}
|
|
|
|
if ($this->dataTable->getRowsCount()) {
|
|
$siteTotalRow = $this->getSiteSummary() ? $this->getSiteSummary()->getFirstRow() : null;
|
|
$this->assignTemplateVar('siteTotalRow', $siteTotalRow);
|
|
}
|
|
|
|
if ($this->isPivoted()) {
|
|
$this->config->columns_to_display = $this->dataTable->getColumns();
|
|
}
|
|
|
|
if ($this->isComparing()
|
|
&& !empty($this->dataTable)
|
|
) {
|
|
$this->assignTemplateVar('comparisonTotals', $this->dataTable->getMetadata('comparisonTotals'));
|
|
}
|
|
|
|
// Note: This needs to be done right before rendering, as otherwise some plugins might change the columns to display again
|
|
if ($this->isFlattened()) {
|
|
$dimensions = $this->dataTable->getMetadata('dimensions');
|
|
|
|
$hasMultipleDimensions = is_array($dimensions) && count($dimensions) > 1;
|
|
$this->assignTemplateVar('hasMultipleDimensions', $hasMultipleDimensions);
|
|
|
|
if ($hasMultipleDimensions) {
|
|
if ($this->config->show_dimensions) {
|
|
// ensure first metric translation is used as label if other dimensions are in separate columns
|
|
$this->config->addTranslation('label', $this->config->translations[reset($dimensions)]);
|
|
} else {
|
|
// concatenate dimensions if table is shown flattened
|
|
foreach ($dimensions as $dimension) {
|
|
$labels[] = $this->config->translations[$dimension];
|
|
}
|
|
$this->config->addTranslation('label', implode(' - ', $labels));
|
|
}
|
|
}
|
|
|
|
if ($this->config->show_dimensions && $hasMultipleDimensions) {
|
|
|
|
|
|
$properties = $this->config;
|
|
array_shift($dimensions); // shift away first dimension, as that will be shown as label
|
|
|
|
$this->dataTable->filter(function (DataTable $dataTable) use ($properties, $dimensions) {
|
|
if (empty($properties->columns_to_display)) {
|
|
$columns = $dataTable->getColumns();
|
|
$hasNbVisits = in_array('nb_visits', $columns);
|
|
$hasNbUniqVisitors = in_array('nb_uniq_visitors', $columns);
|
|
|
|
$properties->setDefaultColumnsToDisplay($columns, $hasNbVisits, $hasNbUniqVisitors);
|
|
}
|
|
|
|
$label = array_search('label', $properties->columns_to_display);
|
|
if ($label !== false) {
|
|
unset($properties->columns_to_display[$label]);
|
|
}
|
|
|
|
foreach (array_reverse($dimensions) as $dimension) {
|
|
array_unshift($properties->columns_to_display, $dimension);
|
|
}
|
|
|
|
array_unshift($properties->columns_to_display, 'label');
|
|
});
|
|
}
|
|
}
|
|
|
|
$this->assignTemplateVar('segmentTitlePretty', $this->dataTable->getMetadata('segmentPretty'));
|
|
|
|
$period = $this->dataTable->getMetadata('period');
|
|
$this->assignTemplateVar('periodTitlePretty', $period ? $period->getLocalizedShortString() : '');
|
|
}
|
|
|
|
public function beforeGenericFiltersAreAppliedToLoadedDataTable()
|
|
{
|
|
if ($this->isPivoted()) {
|
|
$this->config->columns_to_display = $this->dataTable->getColumns();
|
|
|
|
$this->dataTable->applyQueuedFilters();
|
|
}
|
|
|
|
parent::beforeGenericFiltersAreAppliedToLoadedDataTable();
|
|
|
|
// Note: This needs to be done right before generic filter are applied, to make sorting such columns possible
|
|
if ($this->isFlattened()) {
|
|
$dimensions = $this->dataTable->getMetadata('dimensions');
|
|
|
|
$hasMultipleDimensions = is_array($dimensions) && count($dimensions) > 1;
|
|
|
|
if ($hasMultipleDimensions) {
|
|
foreach (Dimension::getAllDimensions() as $dimension) {
|
|
$dimensionId = str_replace('.', '_', $dimension->getId());
|
|
$dimensionName = $dimension->getName();
|
|
|
|
if (!empty($dimensionId) && !empty($dimensionName) && in_array($dimensionId, $dimensions)) {
|
|
$this->config->translations[$dimensionId] = $dimensionName;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if ($this->config->show_dimensions && $hasMultipleDimensions) {
|
|
|
|
$this->dataTable->filter(function($dataTable) use ($dimensions) {
|
|
/** @var DataTable $dataTable */
|
|
$rows = $dataTable->getRows();
|
|
foreach ($rows as $row) {
|
|
foreach ($dimensions as $dimension) {
|
|
$row->setColumn($dimension, $row->getMetadata($dimension));
|
|
}
|
|
}
|
|
});
|
|
|
|
# replace original label column with first dimension
|
|
$firstDimension = array_shift($dimensions);
|
|
$this->dataTable->filter('ColumnCallbackAddMetadata', array('label', 'combinedLabel', function ($label) { return $label; }));
|
|
$this->dataTable->filter('ColumnDelete', array('label'));
|
|
$this->dataTable->filter('ReplaceColumnNames', array(array($firstDimension => 'label')));
|
|
}
|
|
}
|
|
}
|
|
|
|
public function afterGenericFiltersAreAppliedToLoadedDataTable()
|
|
{
|
|
parent::afterGenericFiltersAreAppliedToLoadedDataTable();
|
|
|
|
$this->calculateTotalPercentages(); // this must be done before metrics are formatted
|
|
}
|
|
|
|
private function calculateTotalPercentages()
|
|
{
|
|
if (empty($this->report)) {
|
|
return;
|
|
}
|
|
|
|
$columnNamesToIndices = Metrics::getMappingFromNameToId();
|
|
$formatter = NumberFormatter::getInstance();
|
|
|
|
$totals = $this->dataTable->getMetadata('totalsUnformatted');
|
|
|
|
$siteSummary = $this->getSiteSummary();
|
|
$siteTotalRow = $siteSummary ? $siteSummary->getFirstRow() : null;
|
|
|
|
foreach ($this->dataTable->getRows() as $row) {
|
|
foreach ($this->report->getMetrics() as $column => $translation) {
|
|
// Try to check the column by it's index (not possible for all metrics, like custom columns)
|
|
$indexColumn = !empty($columnNamesToIndices[$column]) ? $columnNamesToIndices[$column] : null;
|
|
|
|
$value = (($indexColumn && $row->getColumn($indexColumn)) ? $row->getColumn($indexColumn) : $row->getColumn($column)) ?: 0;
|
|
if ($column == 'label') {
|
|
continue;
|
|
}
|
|
|
|
$reportTotal = isset($totals[$column]) ? $totals[$column] : 0;
|
|
|
|
if (is_numeric($value)) {
|
|
$percentageColumnName = $column . '_row_percentage';
|
|
$rowPercentage = $formatter->formatPercent(Piwik::getPercentageSafe($value, $reportTotal, $precision = 1), $precision);
|
|
$row->setMetadata($percentageColumnName, $rowPercentage);
|
|
}
|
|
|
|
if ($siteTotalRow) {
|
|
$siteTotal = $siteTotalRow->getColumn($column) ?: 0;
|
|
|
|
$siteTotalPercentage = $column . '_site_total_percentage';
|
|
if ($siteTotal && $siteTotal > $reportTotal) {
|
|
$rowPercentage = $formatter->formatPercent(Piwik::getPercentageSafe($value, $siteTotal, $precision = 1), $precision);
|
|
$row->setMetadata($siteTotalPercentage, $rowPercentage);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected function isPivoted()
|
|
{
|
|
return $this->requestConfig->pivotBy || Common::getRequestVar('pivotBy', '');
|
|
}
|
|
|
|
/**
|
|
* Override to compute a custom cell HTML attributes (such as style).
|
|
*
|
|
* @param Row $row
|
|
* @param $column
|
|
* @return array Array of name => value pairs.
|
|
*/
|
|
public function getCellHtmlAttributes(Row $row, $column)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
public function supportsComparison()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
protected function isFlattened()
|
|
{
|
|
return $this->requestConfig->flat || Common::getRequestVar('flat', '');
|
|
}
|
|
|
|
private function getSiteSummary()
|
|
{
|
|
if (empty($this->siteSummary)) {
|
|
// we do not want to get a datatable\map
|
|
$period = Common::getRequestVar('period', 'day', 'string');
|
|
if (Period\Range::parseDateRange($period)) {
|
|
$period = 'range';
|
|
}
|
|
|
|
$this->siteSummary = ApiRequest::processRequest('API.get', [
|
|
'module' => 'API',
|
|
'action' => 'get',
|
|
'filter_limit' => '-1',
|
|
'disable_generic_filters' => 1,
|
|
'filter_offset' => 0,
|
|
'date' => Common::getRequestVar('date', null, 'string'),
|
|
'idSite' => Common::getRequestVar('idSite', null, 'int'),
|
|
'period' => $period,
|
|
'showColumns' => implode(',', $this->config->columns_to_display),
|
|
'columns' => implode(',', $this->config->columns_to_display),
|
|
], $default = []);
|
|
}
|
|
|
|
return $this->siteSummary;
|
|
}
|
|
}
|