PageRenderTime 54ms CodeModel.GetById 3ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/UserCountry/Archiver.php

https://github.com/CodeYellowBV/piwik
PHP | 179 lines | 125 code | 31 blank | 23 comment | 11 complexity | 8a647883219e572f035b777cd9a474e1 MD5 | raw file
Possible License(s): LGPL-3.0, JSON, MIT, GPL-3.0, LGPL-2.1, GPL-2.0, AGPL-1.0, BSD-2-Clause, BSD-3-Clause
  1. <?php
  2. /**
  3. * Piwik - free/libre analytics platform
  4. *
  5. * @link http://piwik.org
  6. * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  7. *
  8. */
  9. namespace Piwik\Plugins\UserCountry;
  10. use Piwik\ArchiveProcessor;
  11. use Piwik\DataArray;
  12. use Piwik\DataTable;
  13. use Piwik\Metrics;
  14. use Piwik\Plugins\UserCountry\LocationProvider;
  15. class Archiver extends \Piwik\Plugin\Archiver
  16. {
  17. const COUNTRY_RECORD_NAME = 'UserCountry_country';
  18. const REGION_RECORD_NAME = 'UserCountry_region';
  19. const CITY_RECORD_NAME = 'UserCountry_city';
  20. const DISTINCT_COUNTRIES_METRIC = 'UserCountry_distinctCountries';
  21. // separate region, city & country info in stored report labels
  22. const LOCATION_SEPARATOR = '|';
  23. private $latLongForCities = array();
  24. protected $maximumRows;
  25. const COUNTRY_FIELD = 'location_country';
  26. const REGION_FIELD = 'location_region';
  27. const CITY_FIELD = 'location_city';
  28. protected $dimensions = array(self::COUNTRY_FIELD, self::REGION_FIELD, self::CITY_FIELD);
  29. /**
  30. * @var DataArray[] $arrays
  31. */
  32. protected $arrays;
  33. const LATITUDE_FIELD = 'location_latitude';
  34. const LONGITUDE_FIELD = 'location_longitude';
  35. public function aggregateDayReport()
  36. {
  37. foreach ($this->dimensions as $dimension) {
  38. $this->arrays[$dimension] = new DataArray();
  39. }
  40. $this->aggregateFromVisits();
  41. $this->aggregateFromConversions();
  42. $this->insertDayReports();
  43. }
  44. public function aggregateMultipleReports()
  45. {
  46. $dataTableToSum = array(
  47. self::COUNTRY_RECORD_NAME,
  48. self::REGION_RECORD_NAME,
  49. self::CITY_RECORD_NAME,
  50. );
  51. $nameToCount = $this->getProcessor()->aggregateDataTableRecords($dataTableToSum);
  52. $this->getProcessor()->insertNumericRecord(self::DISTINCT_COUNTRIES_METRIC,
  53. $nameToCount[self::COUNTRY_RECORD_NAME]['level0']);
  54. }
  55. protected function aggregateFromVisits()
  56. {
  57. $additionalSelects = array('MAX(log_visit.location_latitude) as location_latitude',
  58. 'MAX(log_visit.location_longitude) as location_longitude');
  59. $query = $this->getLogAggregator()->queryVisitsByDimension($this->dimensions, $where = false, $additionalSelects);
  60. if ($query === false) {
  61. return;
  62. }
  63. while ($row = $query->fetch()) {
  64. $this->makeRegionCityLabelsUnique($row);
  65. $this->rememberCityLatLong($row);
  66. foreach ($this->arrays as $dimension => $dataArray) {
  67. $dataArray->sumMetricsVisits($row[$dimension], $row);
  68. }
  69. }
  70. }
  71. /**
  72. * Makes sure the region and city of a query row are unique.
  73. *
  74. * @param array $row
  75. */
  76. private function makeRegionCityLabelsUnique(&$row)
  77. {
  78. // remove the location separator from the region/city/country we get from the query
  79. foreach ($this->dimensions as $column) {
  80. $row[$column] = str_replace(self::LOCATION_SEPARATOR, '', $row[$column]);
  81. }
  82. if (!empty($row[self::REGION_FIELD])) {
  83. $row[self::REGION_FIELD] = $row[self::REGION_FIELD] . self::LOCATION_SEPARATOR . $row[self::COUNTRY_FIELD];
  84. }
  85. if (!empty($row[self::CITY_FIELD])) {
  86. $row[self::CITY_FIELD] = $row[self::CITY_FIELD] . self::LOCATION_SEPARATOR . $row[self::REGION_FIELD];
  87. }
  88. }
  89. protected function rememberCityLatLong($row)
  90. {
  91. if (!empty($row[self::CITY_FIELD])
  92. && !empty($row[self::LATITUDE_FIELD])
  93. && !empty($row[self::LONGITUDE_FIELD])
  94. && empty($this->latLongForCities[$row[self::CITY_FIELD]])
  95. ) {
  96. $this->latLongForCities[$row[self::CITY_FIELD]] = array($row[self::LATITUDE_FIELD], $row[self::LONGITUDE_FIELD]);
  97. }
  98. }
  99. protected function aggregateFromConversions()
  100. {
  101. $query = $this->getLogAggregator()->queryConversionsByDimension($this->dimensions);
  102. if ($query === false) {
  103. return;
  104. }
  105. while ($row = $query->fetch()) {
  106. $this->makeRegionCityLabelsUnique($row);
  107. foreach ($this->arrays as $dimension => $dataArray) {
  108. $dataArray->sumMetricsGoals($row[$dimension], $row);
  109. }
  110. }
  111. foreach ($this->arrays as $dataArray) {
  112. $dataArray->enrichMetricsWithConversions();
  113. }
  114. }
  115. protected function insertDayReports()
  116. {
  117. $tableCountry = $this->arrays[self::COUNTRY_FIELD]->asDataTable();
  118. $this->getProcessor()->insertNumericRecord(self::DISTINCT_COUNTRIES_METRIC, $tableCountry->getRowsCount());
  119. $report = $tableCountry->getSerialized();
  120. $this->getProcessor()->insertBlobRecord(self::COUNTRY_RECORD_NAME, $report);
  121. $tableRegion = $this->arrays[self::REGION_FIELD]->asDataTable();
  122. $report = $tableRegion->getSerialized($this->maximumRows, $this->maximumRows, Metrics::INDEX_NB_VISITS);
  123. $this->getProcessor()->insertBlobRecord(self::REGION_RECORD_NAME, $report);
  124. $tableCity = $this->arrays[self::CITY_FIELD]->asDataTable();
  125. $this->setLatitudeLongitude($tableCity);
  126. $report = $tableCity->getSerialized($this->maximumRows, $this->maximumRows, Metrics::INDEX_NB_VISITS);
  127. $this->getProcessor()->insertBlobRecord(self::CITY_RECORD_NAME, $report);
  128. }
  129. /**
  130. * Utility method, appends latitude/longitude pairs to city table labels, if that data
  131. * exists for the city.
  132. */
  133. private function setLatitudeLongitude(DataTable $tableCity)
  134. {
  135. foreach ($tableCity->getRows() as $row) {
  136. $label = $row->getColumn('label');
  137. if (isset($this->latLongForCities[$label])) {
  138. // get lat/long for city
  139. list($lat, $long) = $this->latLongForCities[$label];
  140. $lat = round($lat, LocationProvider::GEOGRAPHIC_COORD_PRECISION);
  141. $long = round($long, LocationProvider::GEOGRAPHIC_COORD_PRECISION);
  142. // set latitude + longitude metadata
  143. $row->setMetadata('lat', $lat);
  144. $row->setMetadata('long', $long);
  145. }
  146. }
  147. }
  148. }