1
0
قرینه از https://github.com/matomo-org/matomo.git synced 2025-08-22 06:57:53 +00:00
Files
matomo/plugins/UserCountry/RecordBuilders/Locations.php
Michal Kleiner 9a3ef94df6 [Coding Style] Enable rule PSR12.Files.FileHeader + unify file headers (#22132)
* [Coding Style] Enable rule PSR12.Files.FileHeader

* Apply CS

* Replace Piwik with Matomo in file headers

* Unify file headers (position, no. of lines, https links)

* Rebuild dist files

* Apply CS

* Fix system test that relies on line numbers in a file that had the file header updated

---------

Co-authored-by: Stefan Giehl <stefan@matomo.org>
2024-04-20 20:50:47 +02:00

196 خطوط
7.2 KiB
PHP

<?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\UserCountry\RecordBuilders;
use Piwik\ArchiveProcessor;
use Piwik\ArchiveProcessor\Record;
use Piwik\ArchiveProcessor\RecordBuilder;
use Piwik\Config as PiwikConfig;
use Piwik\DataTable;
use Piwik\DataAccess\LogAggregator;
use Piwik\Metrics;
use Piwik\Plugins\UserCountry\Archiver;
use Piwik\Plugins\UserCountry\LocationProvider;
class Locations extends RecordBuilder
{
protected $dimensions = [
Archiver::COUNTRY_RECORD_NAME => Archiver::COUNTRY_FIELD,
Archiver::REGION_RECORD_NAME => Archiver::REGION_FIELD,
Archiver::CITY_RECORD_NAME => Archiver::CITY_FIELD,
];
private $latLongForCities = [];
public function __construct()
{
parent::__construct();
$this->columnToSortByBeforeTruncation = Metrics::INDEX_NB_VISITS;
}
public function getRecordMetadata(ArchiveProcessor $archiveProcessor): array
{
$maxRowsInTable = PiwikConfig::getInstance()->General['datatable_archiving_maximum_rows_standard'];
return [
Record::make(Record::TYPE_BLOB, Archiver::COUNTRY_RECORD_NAME),
Record::make(Record::TYPE_BLOB, Archiver::REGION_RECORD_NAME)
->setMaxRowsInTable($maxRowsInTable),
Record::make(Record::TYPE_BLOB, Archiver::CITY_RECORD_NAME)
->setMaxRowsInTable($maxRowsInTable),
Record::make(Record::TYPE_NUMERIC, Archiver::DISTINCT_COUNTRIES_METRIC)
->setIsCountOfBlobRecordRows(Archiver::COUNTRY_RECORD_NAME),
];
}
protected function aggregate(ArchiveProcessor $archiveProcessor): array
{
try {
/** @var DataTable[] $records */
$records = [];
foreach ($this->dimensions as $recordName => $dimension) {
$records[$recordName] = new DataTable();
}
$logAggregator = $archiveProcessor->getLogAggregator();
$this->aggregateFromVisits($records, $logAggregator);
$this->aggregateFromConversions($records, $logAggregator);
$this->setLatitudeLongitude($records[Archiver::CITY_RECORD_NAME]);
$records[Archiver::DISTINCT_COUNTRIES_METRIC] = $records[Archiver::COUNTRY_RECORD_NAME]->getRowsCount();
return $records;
} finally {
unset($this->latLongForCities);
}
}
/**
* @param DataTable[] $records
*/
protected function aggregateFromVisits(array $records, LogAggregator $logAggregator): void
{
$additionalSelects = array('MAX(log_visit.location_latitude) as location_latitude',
'MAX(log_visit.location_longitude) as location_longitude');
$query = $logAggregator->queryVisitsByDimension(array_values($this->dimensions), $where = false, $additionalSelects);
if ($query === false) {
return;
}
while ($row = $query->fetch()) {
$this->makeRegionCityLabelsUnique($row);
$this->rememberCityLatLong($row);
$columns = [
Metrics::INDEX_NB_UNIQ_VISITORS => $row[Metrics::INDEX_NB_UNIQ_VISITORS],
Metrics::INDEX_NB_VISITS => $row[Metrics::INDEX_NB_VISITS],
Metrics::INDEX_NB_ACTIONS => $row[Metrics::INDEX_NB_ACTIONS],
Metrics::INDEX_NB_USERS => $row[Metrics::INDEX_NB_USERS],
Metrics::INDEX_MAX_ACTIONS => $row[Metrics::INDEX_MAX_ACTIONS],
Metrics::INDEX_SUM_VISIT_LENGTH => $row[Metrics::INDEX_SUM_VISIT_LENGTH],
Metrics::INDEX_BOUNCE_COUNT => $row[Metrics::INDEX_BOUNCE_COUNT],
Metrics::INDEX_NB_VISITS_CONVERTED => $row[Metrics::INDEX_NB_VISITS_CONVERTED],
];
foreach ($records as $recordName => $dataTable) {
$dimension = $this->dimensions[$recordName];
$dataTable->sumRowWithLabel($row[$dimension], $columns);
}
}
}
/**
* Makes sure the region and city of a query row are unique.
*
* @param array $row
*/
private function makeRegionCityLabelsUnique(array &$row): void
{
// remove the location separator from the region/city/country we get from the query
foreach ($this->dimensions as $column) {
$row[$column] = str_replace(Archiver::LOCATION_SEPARATOR, '', $row[$column] ?? '');
}
// set city first, as containing region might be manipulated afterwards if not empty
if (!empty($row[Archiver::CITY_FIELD])) {
$row[Archiver::CITY_FIELD] = $row[Archiver::CITY_FIELD] . Archiver::LOCATION_SEPARATOR . $row[Archiver::REGION_FIELD] . Archiver::LOCATION_SEPARATOR . $row[Archiver::COUNTRY_FIELD];
}
if (!empty($row[Archiver::REGION_FIELD])) {
$row[Archiver::REGION_FIELD] = $row[Archiver::REGION_FIELD] . Archiver::LOCATION_SEPARATOR . $row[Archiver::COUNTRY_FIELD];
}
}
protected function rememberCityLatLong(array $row): void
{
if (
!empty($row[Archiver::CITY_FIELD])
&& !empty($row[Archiver::LATITUDE_FIELD])
&& !empty($row[Archiver::LONGITUDE_FIELD])
&& empty($this->latLongForCities[$row[Archiver::CITY_FIELD]])
) {
$this->latLongForCities[$row[Archiver::CITY_FIELD]] = array($row[Archiver::LATITUDE_FIELD], $row[Archiver::LONGITUDE_FIELD]);
}
}
/**
* @param DataTable[] $records
*/
protected function aggregateFromConversions(array $records, LogAggregator $logAggregator): void
{
$query = $logAggregator->queryConversionsByDimension(array_values($this->dimensions));
while ($row = $query->fetch()) {
$this->makeRegionCityLabelsUnique($row);
foreach ($records as $recordName => $table) {
$idGoal = (int) $row['idgoal'];
$columns = [
Metrics::INDEX_GOALS => [
$idGoal => Metrics::makeGoalColumnsRow($idGoal, $row),
],
];
$dimension = $this->dimensions[$recordName];
$table->sumRowWithLabel($row[$dimension], $columns);
}
}
foreach ($records as $table) {
$table->filter(DataTable\Filter\EnrichRecordWithGoalMetricSums::class);
}
}
/**
* Utility method, appends latitude/longitude pairs to city table labels, if that data
* exists for the city.
*/
private function setLatitudeLongitude(DataTable $tableCity): void
{
foreach ($tableCity->getRows() as $row) {
$label = $row->getColumn('label');
if (isset($this->latLongForCities[$label])) {
// get lat/long for city
list($lat, $long) = $this->latLongForCities[$label];
$lat = round($lat, LocationProvider::GEOGRAPHIC_COORD_PRECISION);
$long = round($long, LocationProvider::GEOGRAPHIC_COORD_PRECISION);
// set latitude + longitude metadata
$row->setMetadata('lat', $lat);
$row->setMetadata('long', $long);
}
}
}
}