diff options
Diffstat (limited to 'plugins/UserCountry/API.php')
-rw-r--r-- | plugins/UserCountry/API.php | 148 |
1 files changed, 126 insertions, 22 deletions
diff --git a/plugins/UserCountry/API.php b/plugins/UserCountry/API.php index 9fe7cfdcb1..34a00a4add 100644 --- a/plugins/UserCountry/API.php +++ b/plugins/UserCountry/API.php @@ -12,9 +12,12 @@ use Exception; use Piwik\Archive; use Piwik\Container\StaticContainer; use Piwik\DataTable; -use Piwik\Metrics; +use Piwik\Date; +use Piwik\Option; +use Piwik\Period; use Piwik\Piwik; -use Piwik\Plugins\UserCountry\LocationProvider; +use Piwik\Plugins\GeoIp2\Commands\ConvertRegionCodesToIso; +use Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2; use Piwik\Tracker\Visit; /** @@ -89,13 +92,9 @@ class API extends \Piwik\Plugin\API { $dataTable = $this->getDataTable(Archiver::REGION_RECORD_NAME, $idSite, $period, $date, $segment); - $segments = array('regionCode', 'countryCode'); - $dataTable->filter('AddSegmentByLabel', array($segments, Archiver::LOCATION_SEPARATOR)); - $separator = Archiver::LOCATION_SEPARATOR; $unk = Visit::UNKNOWN_CODE; - // show visits tracked as Tibet as region of China $dataTables = [$dataTable]; if ($dataTable instanceof DataTable\Map) { @@ -103,7 +102,33 @@ class API extends \Piwik\Plugin\API } foreach ($dataTables as $dt) { - if ($dt->getRowFromLabel('1|ti')) { + $archiveDate = $dt->getMetadata(DataTable::ARCHIVED_DATE_METADATA_NAME); + + // convert fips region codes to iso if required + if ($this->shouldRegionCodesBeConvertedToIso($archiveDate, $date, $period)) { + $dt->filter('GroupBy', array( + 'label', + function ($label) use ($separator, $unk) { + $regionCode = getElementFromStringArray($label, $separator, 0, ''); + $countryCode = getElementFromStringArray($label, $separator, 1, ''); + + list($countryCode, $regionCode) = GeoIp2::convertRegionCodeToIso($countryCode, + $regionCode, true); + + $splitLabel = explode($separator, $label); + + if (isset($splitLabel[0])) { + $splitLabel[0] = $regionCode; + } + + if (isset($splitLabel[1])) { + $splitLabel[1] = strtolower($countryCode); + } + + return implode($separator, $splitLabel); + } + )); + } else if ($dt->getRowFromLabel('1|ti')) { $dt->filter('GroupBy', array( 'label', function ($label) { @@ -116,6 +141,9 @@ class API extends \Piwik\Plugin\API } } + $segments = array('regionCode', 'countryCode'); + $dataTable->filter('AddSegmentByLabel', array($segments, Archiver::LOCATION_SEPARATOR)); + // split the label and put the elements into the 'region' and 'country' metadata fields $dataTable->filter('ColumnCallbackAddMetadata', array('label', 'region', __NAMESPACE__ . '\getElementFromStringArray', array($separator, 0, $unk))); @@ -155,13 +183,9 @@ class API extends \Piwik\Plugin\API { $dataTable = $this->getDataTable(Archiver::CITY_RECORD_NAME, $idSite, $period, $date, $segment); - $segments = array('city', 'regionCode', 'countryCode'); - $dataTable->filter('AddSegmentByLabel', array($segments, Archiver::LOCATION_SEPARATOR)); - $separator = Archiver::LOCATION_SEPARATOR; $unk = Visit::UNKNOWN_CODE; - - // show visits from "1|ti" cities to "14|cn" + $dataTables = [$dataTable]; if ($dataTable instanceof DataTable\Map) { @@ -169,17 +193,48 @@ class API extends \Piwik\Plugin\API } foreach ($dataTables as $dt) { - $dt->filter('GroupBy', array( - 'label', - function ($label) { - if (substr($label, -5) == '|1|ti') { - return substr($label, 0, -5) . '|14|cn'; + $archiveDate = $dt->getMetadata(DataTable::ARCHIVED_DATE_METADATA_NAME); + + // convert fips region codes to iso if required + if ($this->shouldRegionCodesBeConvertedToIso($archiveDate, $date, $period)) { + $dt->filter('GroupBy', array( + 'label', + function ($label) use ($separator, $unk) { + $regionCode = getElementFromStringArray($label, $separator, 1, ''); + $countryCode = getElementFromStringArray($label, $separator, 2, ''); + + list($countryCode, $regionCode) = GeoIp2::convertRegionCodeToIso($countryCode, + $regionCode, true); + + $splitLabel = explode($separator, $label); + + if (isset($splitLabel[1])) { + $splitLabel[1] = $regionCode; + } + + if (isset($splitLabel[2])) { + $splitLabel[2] = strtolower($countryCode); + } + + return implode($separator, $splitLabel); } - return $label; - } - )); + )); + } else { + $dt->filter('GroupBy', array( + 'label', + function ($label) { + if (substr($label, -5) == '|1|ti') { + return substr($label, 0, -5) . '|14|cn'; + } + return $label; + } + )); + } } + $segments = array('city', 'regionCode', 'countryCode'); + $dataTable->filter('AddSegmentByLabel', array($segments, Archiver::LOCATION_SEPARATOR)); + // split the label and put the elements into the 'city_name', 'region', 'country', // 'lat' & 'long' metadata fields $strUnknown = Piwik::translate('General_Unknown'); @@ -209,7 +264,7 @@ class API extends \Piwik\Plugin\API $dataTable->filter('MetadataCallbackAddMetadata', array('country', 'country_name', __NAMESPACE__ . '\countryTranslate', $applyToSummaryRow = false)); - $getRegionName = '\\Piwik\\Plugins\\UserCountry\\LocationProvider\\GeoIp::getRegionNameFromCodes'; + $getRegionName = '\\Piwik\\Plugins\\UserCountry\\getRegionNameFromCodes'; $dataTable->filter('MetadataCallbackAddMetadata', array( array('country', 'region'), 'region_name', $getRegionName, $applyToSummaryRow = false)); @@ -225,6 +280,55 @@ class API extends \Piwik\Plugin\API } /** + * if no switch to ISO was done --> no conversion as only FIPS codes are in use and handled correctly + * if there has been a switch to ISO, we need to check the date: + * - if the start date of the period is after the date we switched to ISO: no conversion needed + * - if not we need to convert the codes to ISO, if the code is mappable + * Note: as all old codes are mapped, not mappable codes need to be iso codes already, so we leave them + * @param $date + * @param $period + * @return bool + */ + private function shouldRegionCodesBeConvertedToIso($archiveDate, $date, $period) + { + $timeOfSwitch = Option::get(GeoIp2::SWITCH_TO_ISO_REGIONS_OPTION_NAME); + + if (empty($timeOfSwitch)) { + return false; // if option was not set, all codes are fips codes, so leave them + } + + try { + $dateOfSwitch = Date::factory((int)$timeOfSwitch); + $period = Period\Factory::build($period, $date); + $periodStart = $period->getDateStart(); + } catch (Exception $e) { + return false; + } + + // if all region codes in log tables have been converted, check if archiving date was after the date of switch to iso + // this check might not be fully correct in cases were only periods > day get recreated, but it should avoid some + // double conversion if all archives have been recreated after converting all region codes + $codesConverted = Option::get(ConvertRegionCodesToIso::OPTION_NAME); + + if ($codesConverted && $archiveDate) { + try { + $dateOfArchive = Date::factory($archiveDate); + + if ($dateOfArchive->isLater($dateOfSwitch)) { + return false; + } + } catch (Exception $e) { + } + } + + if ($dateOfSwitch->isEarlier($periodStart)) { + return false; + } + + return true; + } + + /** * Returns a simple mapping from country code to country name * * @return \string[] @@ -279,7 +383,7 @@ class API extends \Piwik\Plugin\API /** * Set the location provider * - * @param string $providerId The ID of the provider to use eg 'default', 'geoip_php', ... + * @param string $providerId The ID of the provider to use eg 'default', 'geoip2_php', ... * @throws Exception if ID is invalid */ public function setLocationProvider($providerId) |