| Server IP : 213.186.33.4 / Your IP : 216.73.216.193 Web Server : Apache System : Linux webm006.cluster103.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64 User : awebpaca ( 35430) PHP Version : 8.5.0 Disable Function : _dyuweyrj4,_dyuweyrj4r,dl MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /home/awebpaca/piwik/plugins/CoreVisualizations/Visualizations/ |
Upload File : |
<?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;
use Piwik\Common;
use Piwik\DataTable;
use Piwik\Metrics;
use Piwik\Period\Factory;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\API\Filter\DataComparisonFilter;
use Piwik\SettingsPiwik;
use Piwik\Url;
use Piwik\View;
/**
* Reads the requested DataTable from the API and prepares data for the Sparklines view. It can display any amount
* of sparklines. Within a reporting page sparklines are shown in 2 columns, in a dashboard or when exported as a widget
* the sparklines are shown in one column.
*
* The sparklines view currently only supports requesting columns from the same API (the API method of the defining
* report) via {Sparklines\Config::addSparklineMetric($columns = array('nb_visits', 'nb_unique_visitors'))}.
*
* Example:
* $view->config->addSparklineMetric('nb_visits'); // if an array of metrics given, they will be displayed comma separated
* $view->config->addTranslation('nb_visits', 'Visits');
* Results in: [sparkline image] X visits
* Data is fetched from the configured $view->requestConfig->apiMethodToRequestDataTable.
*
* In case you want to add any custom sparklines from any other API method you can call
* {@link Sparklines\Config::addSparkline()}.
*
* Example:
* $sparklineUrlParams = array('columns' => array('nb_visits));
* $evolution = array('currentValue' => 5, 'pastValue' => 10, 'tooltip' => 'Foo bar');
* $view->config->addSparkline($sparklineUrlParams, $value = 5, $description = 'Visits', $evolution);
*
* @property Sparklines\Config $config
*/
class Sparklines extends ViewDataTable
{
const ID = 'sparklines';
public static function getDefaultConfig()
{
return new Sparklines\Config();
}
public function supportsComparison()
{
return true;
}
/**
* @see ViewDataTable::main()
* @return mixed
*/
public function render()
{
$view = new View('@CoreVisualizations/_dataTableViz_sparklines.twig');
$columnsList = array();
if ($this->config->hasSparklineMetrics()) {
foreach ($this->config->getSparklineMetrics() as $cols) {
$columns = $cols['columns'];
if (!is_array($columns)) {
$columns = array($columns);
}
$columnsList = array_merge($columns, $columnsList);
}
}
$view->allMetricsDocumentation = array_merge(Metrics::getDefaultMetricsDocumentation(), $this->config->metrics_documentation);
$this->requestConfig->request_parameters_to_modify['columns'] = $columnsList;
$this->requestConfig->request_parameters_to_modify['format_metrics'] = '1';
$request = $this->getRequestArray();
if ($this->isComparing()
&& !empty($request['comparePeriods'])
&& count($request['comparePeriods']) == 1
) {
$this->requestConfig->request_parameters_to_modify['invert_compare_change_compute'] = 1;
}
if (!empty($this->requestConfig->apiMethodToRequestDataTable)) {
$this->fetchConfiguredSparklines();
}
$view->sparklines = $this->config->getSortedSparklines();
$view->isWidget = Common::getRequestVar('widget', 0, 'int');
$view->titleAttributes = $this->config->title_attributes;
$view->footerMessage = $this->config->show_footer_message;
$view->areSparklinesLinkable = $this->config->areSparklinesLinkable();
$view->isComparing = $this->isComparing();
$view->title = '';
if ($this->config->show_title) {
$view->title = $this->config->title;
}
return $view->render();
}
private function fetchConfiguredSparklines()
{
$data = $this->loadDataTableFromAPI();
$this->applyFilters($data);
if (!$this->config->hasSparklineMetrics()) {
foreach ($data->getColumns() as $column) {
$this->config->addSparklineMetric($column);
}
}
$firstRow = $data->getFirstRow();
$comparisons = $firstRow->getComparisons();
$originalDate = Common::getRequestVar('date');
$originalPeriod = Common::getRequestVar('period');
if ($this->isComparing() && !empty($comparisons)) {
$comparisonRows = [];
foreach ($comparisons->getRows() as $comparisonRow) {
$segment = $comparisonRow->getMetadata('compareSegment');
if ($segment === false) {
$segment = Request::getRawSegmentFromRequest() ?: '';
}
$date = $comparisonRow->getMetadata('compareDate');
$period = $comparisonRow->getMetadata('comparePeriod');
$comparisonRows[$segment][$period][$date] = $comparisonRow;
}
}
foreach ($this->config->getSparklineMetrics() as $sparklineMetricIndex => $sparklineMetric) {
$column = $sparklineMetric['columns'];
$order = $sparklineMetric['order'];
$graphParams = $sparklineMetric['graphParams'];
if (!isset($order)) {
$order = 1000;
}
if ($column === 'label') {
continue;
}
if (empty($column)) {
$this->config->addPlaceholder($order);
continue;
}
$sparklineUrlParams = array(
'columns' => $column,
'module' => $this->requestConfig->getApiModuleToRequest(),
'action' => $this->requestConfig->getApiMethodToRequest()
);
if ($this->isComparing() && !empty($comparisons)) {
$periodObj = Factory::build($originalPeriod, $originalDate);
$sparklineUrlParams['compareSegments'] = [];
$comparePeriods = $data->getMetadata('comparePeriods');
$compareDates = $data->getMetadata('compareDates');
$compareSegments = $data->getMetadata('compareSegments');
foreach ($compareSegments as $segmentIndex => $segment) {
$metrics = [];
$seriesIndices = [];
foreach ($comparePeriods as $periodIndex => $period) {
$date = $compareDates[$periodIndex];
$compareRow = $comparisonRows[$segment][$period][$date];
$segmentPretty = $compareRow->getMetadata('compareSegmentPretty');
$periodPretty = $compareRow->getMetadata('comparePeriodPretty');
$columnToUse = $this->removeUniqueVisitorsIfNotEnabledForPeriod($column, $period);
list($compareValues, $compareDescriptions, $evolutions) = $this->getValuesAndDescriptions($compareRow, $columnToUse, '_change');
foreach ($compareValues as $i => $value) {
$metricInfo = [
'value' => $value,
'description' => $compareDescriptions[$i],
'group' => $periodPretty,
];
if (isset($evolutions[$i])) {
$metricInfo['evolution'] = $evolutions[$i];
}
$metrics[] = $metricInfo;
}
$seriesIndices[] = DataComparisonFilter::getComparisonSeriesIndex($data, $periodIndex, $segmentIndex);
}
// only set the title (which is the segment) if comparing more than one segment
$title = count($compareSegments) > 1 ? $segmentPretty : null;
$params = array_merge($sparklineUrlParams, [
'segment' => $segment,
'period' => $periodObj->getLabel(),
'date' => $periodObj->getRangeString(),
]);
$this->config->addSparkline($params, $metrics, $desc = null, null, ($order * 100) + $segmentIndex, $title, $sparklineMetricIndex, $seriesIndices, $graphParams);
}
} else {
list($values, $descriptions) = $this->getValuesAndDescriptions($firstRow, $column);
$metrics = [];
foreach ($values as $i => $value) {
$newMetric = [
'value' => $value,
'description' => $descriptions[$i],
];
$metrics[] = $newMetric;
}
$evolution = null;
$computeEvolution = $this->config->compute_evolution;
if ($computeEvolution) {
$evolution = $computeEvolution(array_combine($column, $values));
$newMetric['evolution'] = $evolution;
}
$this->config->addSparkline($sparklineUrlParams, $metrics, $desc = null, $evolution, $order, $title = null, $group = $sparklineMetricIndex, $seriesIndices = null, $graphParams);
}
}
}
private function applyFilters(DataTable\DataTableInterface $table)
{
foreach ($this->config->getPriorityFilters() as $filter) {
$table->filter($filter[0], $filter[1]);
}
// queue other filters so they can be applied later if queued filters are disabled
foreach ($this->config->getPresentationFilters() as $filter) {
$table->queueFilter($filter[0], $filter[1]);
}
$table->applyQueuedFilters();
}
private function getValuesAndDescriptions(DataTable\Row $firstRow, $columns, $evolutionColumnNameSuffix = null)
{
if (!is_array($columns)) {
$columns = array($columns);
}
$translations = $this->config->translations;
$values = array();
$descriptions = array();
$evolutions = [];
foreach ($columns as $col) {
$value = $firstRow->getColumn($col);
if ($value === false) {
$value = 0;
}
if ($evolutionColumnNameSuffix !== null) {
$evolution = $firstRow->getColumn($col . $evolutionColumnNameSuffix);
if ($evolution !== false) {
$evolutions[] = ['percent' => ltrim($evolution, '+'), 'tooltip' => ''];
}
}
$values[] = $value;
$descriptions[] = isset($translations[$col]) ? $translations[$col] : $col;
}
return [$values, $descriptions, $evolutions];
}
private function removeUniqueVisitorsIfNotEnabledForPeriod($columns, $period)
{
if (SettingsPiwik::isUniqueVisitorsEnabled($period)) {
return $columns;
}
return array_diff($columns, ['nb_users', 'nb_uniq_visitors']);
}
}