Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 48 additions & 40 deletions plugins/DevicePlugins/API.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,56 +46,64 @@ public function getPlugin($idSite, $period, $date, $segment = false)
$archive = Archive::build($idSite, $period, $date, $segment);
$visitsSums = $archive->getDataTableFromNumeric('nb_visits');

// check whether given tables are arrays
if ($dataTable instanceof DataTable\Map) {
$dataTableMap = $dataTable->getDataTables();
$browserVersionsArray = $browserVersions->getDataTables();
$visitSumsArray = $visitsSums->getDataTables();
$dataTable->multiFilter(
[
$browserVersions instanceof DataTable\Map ? $browserVersions : null,
$visitsSums instanceof DataTable\Map ? $visitsSums : null,
],
function (DataTable $pluginTable, ?DataTable $browserVersionsTable, ?DataTable $visitsTable): void {
$this->addVisitsPercentProcessedMetric($pluginTable, $browserVersionsTable, $visitsTable);
}
);
} else {
$dataTableMap = array($dataTable);
$browserVersionsArray = array($browserVersions);
$visitSumsArray = array($visitsSums);
$this->addVisitsPercentProcessedMetric(
$dataTable,
$browserVersions instanceof DataTable ? $browserVersions : null,
$visitsSums instanceof DataTable ? $visitsSums : null
);
}

// walk through the results and calculate the percentage
foreach ($dataTableMap as $key => $table) {
// Calculate percentage, but ignore IE users because plugin detection doesn't work on IE
$ieVisits = 0;
$dataTable->queueFilter('ColumnCallbackAddMetadata', ['label', 'logo', __NAMESPACE__ . '\getPluginsLogo']);
$dataTable->queueFilter('ColumnCallbackReplace', ['label', 'ucfirst']);
$dataTable->queueFilter('RangeCheck', ['nb_visits_percentage', 0, 1]);

$browserVersionsToExclude = array(
'IE;10.0',
'IE;9.0',
'IE;8.0',
'IE;7.0',
'IE;6.0',
);
foreach ($browserVersionsToExclude as $browserVersionToExclude) {
$ieStats = $browserVersionsArray[$key]->getRowFromLabel($browserVersionToExclude);
if ($ieStats !== false) {
$ieVisits += $ieStats->getColumn(Metrics::INDEX_NB_VISITS);
}
}
return $dataTable;
}

// get according visitsSum
$visits = $visitSumsArray[$key];
if ($visits->getRowsCount() == 0) {
$visitsSumTotal = 0;
} else {
$visitsSumTotal = (float) $visits->getFirstRow()->getColumn('nb_visits');
}
private function addVisitsPercentProcessedMetric(
DataTable $table,
?DataTable $browserVersions,
?DataTable $visits
): void {
// Calculate percentage, but ignore IE users because plugin detection doesn't work on IE
$ieVisits = 0;

$visitsSum = $visitsSumTotal - $ieVisits;
$browserVersionsToExclude = [
'IE;10.0',
'IE;9.0',
'IE;8.0',
'IE;7.0',
'IE;6.0',
];
foreach ($browserVersionsToExclude as $browserVersionToExclude) {
$ieStats = $browserVersions ? $browserVersions->getRowFromLabel($browserVersionToExclude) : false;
if ($ieStats !== false) {
$ieVisits += $ieStats->getColumn(Metrics::INDEX_NB_VISITS);
}
}

$extraProcessedMetrics = $table->getMetadata(DataTable::EXTRA_PROCESSED_METRICS_METADATA_NAME);
$extraProcessedMetrics = is_array($extraProcessedMetrics) ? $extraProcessedMetrics : [];
$extraProcessedMetrics[] = new VisitsPercent($visitsSum);
$table->setMetadata(DataTable::EXTRA_PROCESSED_METRICS_METADATA_NAME, $extraProcessedMetrics);
if (!$visits || $visits->getRowsCount() == 0) {
$visitsSumTotal = 0;
} else {
$visitsSumTotal = (float)$visits->getFirstRow()->getColumn('nb_visits');
}

$dataTable->queueFilter('ColumnCallbackAddMetadata', array('label', 'logo', __NAMESPACE__ . '\getPluginsLogo'));
$dataTable->queueFilter('ColumnCallbackReplace', array('label', 'ucfirst'));
$dataTable->queueFilter('RangeCheck', array('nb_visits_percentage', 0, 1));
$visitsSum = $visitsSumTotal - $ieVisits;

return $dataTable;
$extraProcessedMetrics = $table->getMetadata(DataTable::EXTRA_PROCESSED_METRICS_METADATA_NAME);
$extraProcessedMetrics = is_array($extraProcessedMetrics) ? $extraProcessedMetrics : [];
$extraProcessedMetrics[] = new VisitsPercent($visitsSum);
$table->setMetadata(DataTable::EXTRA_PROCESSED_METRICS_METADATA_NAME, $extraProcessedMetrics);
}
}
72 changes: 72 additions & 0 deletions plugins/DevicePlugins/tests/Integration/GetPluginApiTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

/**
* Matomo - free/libre analytics platform
*
* @link https://matomo.org
* @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/

namespace Piwik\Plugins\DevicePlugins\tests\Integration;

use Piwik\DataTable;
use Piwik\Plugins\CoreHome\Columns\Metrics\VisitsPercent;
use Piwik\Plugins\DevicePlugins\API;
use Piwik\Tests\Framework\Fixture;
use Piwik\Tests\Framework\TestCase\IntegrationTestCase;

/**
* @group DevicePlugins
* @group Plugins
*/
class GetPluginApiTest extends IntegrationTestCase
{
public function setUp(): void
{
parent::setUp();

Fixture::createWebsite('2024-01-01 00:00:00');
Fixture::createWebsite('2024-01-01 00:00:00');
Fixture::createSuperUser();

$this->trackVisit(1, '2024-01-16 10:00:00');
$this->trackVisit(1, '2024-01-17 10:00:00');
$this->trackVisit(2, '2024-01-16 11:00:00');
$this->trackVisit(2, '2024-01-17 11:00:00');
}

public function testGetPluginShouldSupportMultiSiteAndMultiPeriodRequests(): void
{
$result = API::getInstance()->getPlugin('1,2', 'day', '2024-01-16,2024-01-17');

self::assertInstanceOf(DataTable\Map::class, $result);

$result->applyQueuedFilters();

foreach ($result->getDataTables() as $siteTable) {
self::assertInstanceOf(DataTable\Map::class, $siteTable);

foreach ($siteTable->getDataTables() as $periodTable) {
self::assertInstanceOf(DataTable::class, $periodTable);
self::assertNotEmpty(
array_filter(
$periodTable->getMetadata(DataTable::EXTRA_PROCESSED_METRICS_METADATA_NAME) ?: [],
function ($metric) {
return $metric instanceof VisitsPercent;
}
)
);
self::assertGreaterThan(0, $periodTable->getRowsCount());
}
}
}

private function trackVisit(int $idSite, string $dateTime): void
{
$tracker = Fixture::getTracker($idSite, $dateTime, true, true);
$tracker->setIp(sprintf('10.0.0.%d', $idSite));
$tracker->setPlugins(true, false, true, false, true);
$tracker->setUrl(sprintf('https://example.org/site-%d', $idSite));
Fixture::checkResponse($tracker->doTrackPageView('Plugin Report Visit'));
}
}
Loading