Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/UserCountry/LocationProvider.php')
-rwxr-xr-xplugins/UserCountry/LocationProvider.php883
1 files changed, 422 insertions, 461 deletions
diff --git a/plugins/UserCountry/LocationProvider.php b/plugins/UserCountry/LocationProvider.php
index 3f6b8821ed..34dfac6dfc 100755
--- a/plugins/UserCountry/LocationProvider.php
+++ b/plugins/UserCountry/LocationProvider.php
@@ -1,10 +1,10 @@
<?php
/**
* Piwik - Open source web analytics
- *
+ *
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
+ *
* @category Piwik_Plugins
* @package Piwik_UserCountry
*/
@@ -21,470 +21,431 @@ require_once PIWIK_INCLUDE_PATH . '/plugins/UserCountry/LocationProvider/GeoIp.p
/**
* The base class of all LocationProviders.
- *
+ *
* LocationProviders attempt to determine a visitor's location using other
* visitor info. All LocationProviders require a visitor's IP address, some
* require more, such as the browser language.
*/
abstract class Piwik_UserCountry_LocationProvider
{
- const NOT_INSTALLED = 0;
- const INSTALLED = 1;
- const BROKEN = 2;
-
- const CURRENT_PROVIDER_OPTION_NAME = 'usercountry.location_provider';
-
- const GEOGRAPHIC_COORD_PRECISION = 3;
-
- const CONTINENT_CODE_KEY = 'continent_code';
- const CONTINENT_NAME_KEY = 'continent_name';
- const COUNTRY_CODE_KEY = 'country_code';
- const COUNTRY_NAME_KEY = 'country_name';
- const REGION_CODE_KEY = 'region_code';
- const REGION_NAME_KEY = 'region_name';
- const CITY_NAME_KEY = 'city_name';
- const AREA_CODE_KEY = 'area_code';
- const LATITUDE_KEY = 'lat';
- const LONGITUDE_KEY = 'long';
- const POSTAL_CODE_KEY = 'postal_code';
- const ISP_KEY = 'isp';
- const ORG_KEY = 'org';
-
- /**
- * An array of all provider instances. Access it through static methods.
- *
- * @var array
- */
- public static $providers = null;
-
- /**
- * Returns location information based on visitor information.
- *
- * The result of this function will be an array. The array can store some or all of
- * the following information:
- *
- * - Continent Code: The code of the visitor's continent.
- * (array key is self::CONTINENT_CODE_KEY)
- * - Continent Name: The name of the visitor's continent.
- * (array key is self::CONTINENT_NAME_KEY)
- * - Country Code: The code of the visitor's country.
- * (array key is self::COUNTRY_CODE_KEY)
- * - Country Name: The name of the visitor's country.
- * (array key is self::COUNTRY_NAME_KEY)
- * - Region Code: The code of the visitor's region.
- * (array key is self::REGION_CODE_KEY)
- * - Region Name: The name of the visitor's region.
- * (array key is self::REGION_NAME_KEY)
- * - City Name: The name of the visitor's city.
- * (array key is self::CITY_NAME_KEY)
- * - Area Code: The visitor's area code.
- * (array key is self::AREA_CODE_KEY)
- * - Latitude: The visitor's latitude.
- * (array key is self::LATITUDE_KEY)
- * - Longitude: The visitor's longitude.
- * (array key is self::LONGITUDE_KEY)
- * - Postal Code: The visitor's postal code.
- * (array key is self::POSTAL_CODE_KEY)
- * - ISP: The visitor's ISP.
- * (array key is self::ISP_KEY)
- * - Org: The company/organization of the visitor's IP.
- * (array key is self::ORG_KEY)
- *
- * All LocationProviders will attempt to return the country of the visitor.
- *
- * @param array $info What this must contain depends on the specific provider
- * implementation. All providers require an 'ip' key mapped
- * to the visitor's IP address.
- * @return array|false
- */
- abstract public function getLocation( $info );
-
- /**
- * Returns true if this provider is available for use, false if otherwise.
- *
- * @return bool
- */
- abstract public function isAvailable();
-
- /**
- * Returns true if this provider is working, false if otherwise.
- *
- * @return bool
- */
- abstract public function isWorking();
-
- /**
- * Returns an array mapping location result keys w/ bool values indicating whether
- * that information is supported by this provider. If it is not supported, that means
- * this provider either cannot get this information, or is not configured to get it.
- *
- * @return array eg. array(self::CONTINENT_CODE_KEY => true,
- * self::CONTINENT_NAME_KEY => true,
- * self::ORG_KEY => false)
- * The result is not guaranteed to have keys for every type of location
- * info.
- */
- abstract public function getSupportedLocationInfo();
-
- /**
- * Returns every available provider instance.
- *
- * @return array
- */
- public static function getAllProviders()
- {
- if (is_null(self::$providers))
- {
- self::$providers = array();
- foreach (get_declared_classes() as $klass)
- {
- if (is_subclass_of($klass, 'Piwik_UserCountry_LocationProvider'))
- {
- $klassInfo = new ReflectionClass($klass);
- if ($klassInfo->isAbstract())
- {
- continue;
- }
-
- self::$providers[] = new $klass;
- }
- }
- }
-
- return self::$providers;
- }
-
- /**
- * Returns all provider instances that are 'available'. An 'available' provider
- * is one that is available for use. They may not necessarily be working.
- *
- * @return array
- */
- public static function getAvailableProviders()
- {
- $result = array();
- foreach (self::getAllProviders() as $provider)
- {
- if ($provider->isAvailable())
- {
- $result[] = $provider;
- }
- }
- return $result;
- }
-
- /**
- * Returns an array mapping provider IDs w/ information about the provider,
- * for each location provider.
- *
- * The following information is provided for each provider:
- * 'id' - The provider's unique string ID.
- * 'title' - The provider's title.
- * 'description' - A description of how the location provider works.
- * 'status' - Either self::NOT_INSTALLED, self::INSTALLED or self::BROKEN.
- * 'statusMessage' - If the status is self::BROKEN, then the message describes why.
- * 'location' - A pretty formatted location of the current IP address
- * (Piwik_IP::getIpFromHeader()).
- *
- * An example result:
- * array(
- * 'geoip_php' => array('id' => 'geoip_php',
- * 'title' => '...',
- * 'desc' => '...',
- * 'status' => Piwik_UserCountry_LocationProvider_GeoIp::BROKEN,
- * 'statusMessage' => '...',
- * 'location' => '...')
- * 'geoip_serverbased' => array(...)
- * )
- *
- * @param string $newline What to separate lines with in the pretty locations.
- * @param bool $includeExtra Whether to include ISP/Org info in formatted location.
- * @return array
- */
- public static function getAllProviderInfo( $newline = "\n", $includeExtra = false )
- {
- $allInfo = array();
- foreach (self::getAllProviders() as $provider)
- {
- $info = $provider->getInfo();
-
- $status = self::INSTALLED;
- $location = false;
- $statusMessage = false;
-
- $availableOrMessage = $provider->isAvailable();
- if ($availableOrMessage !== true)
- {
- $status = self::NOT_INSTALLED;
- if (is_string($availableOrMessage))
- {
- $statusMessage = $availableOrMessage;
- }
- }
- else
- {
- $workingOrError = $provider->isWorking();
- if ($workingOrError === true) // if the implementation is configured correctly, get the location
- {
- $locInfo = array('ip' => Piwik_IP::getIpFromHeader(),
- 'lang' => Piwik_Common::getBrowserLanguage(),
- 'disable_fallbacks' => true);
-
- $location = $provider->getLocation($locInfo);
- $location = self::prettyFormatLocation($location, $newline, $includeExtra);
- }
- else // otherwise set an error message describing why
- {
- $status = self::BROKEN;
- $statusMessage = $workingOrError;
- }
- }
-
- $info['status'] = $status;
- $info['statusMessage'] = $statusMessage;
- $info['location'] = $location;
-
- $allInfo[$info['order']] = $info;
- }
-
- ksort($allInfo);
-
- $result = array();
- foreach ($allInfo as $info)
- {
- $result[$info['id']] = $info;
- }
- return $result;
- }
-
- /**
- * Returns the ID of the currently used location provider.
- *
- * The used provider is stored in the 'usercountry.location_provider' option.
- *
- * This function should not be called by the Tracker.
- *
- * @return string
- */
- public static function getCurrentProviderId()
- {
- $optionValue = Piwik_GetOption(self::CURRENT_PROVIDER_OPTION_NAME);
- return $optionValue === false ? Piwik_UserCountry_LocationProvider_Default::ID : $optionValue;
- }
-
- /**
- * Returns the provider instance of the current location provider.
- *
- * This function should not be called by the Tracker.
- *
- * @return Piwik_UserCountry_LocationProvider
- */
- public static function getCurrentProvider()
- {
- return self::getProviderById(self::getCurrentProviderId());
- }
-
- /**
- * Sets the provider to use when tracking.
- *
- * @param string $providerId The ID of the provider to use.
- * @return Piwik_UserCountry_LocationProvider The new current provider.
- * @throws Exception If the provider ID is invalid.
- */
- public static function setCurrentProvider( $providerId )
- {
- $provider = self::getProviderById($providerId);
- if ($provider === false)
- {
- throw new Exception(
- "Invalid provider ID '$providerId'. The provider either does not exist or is not available");
- }
- Piwik_SetOption(self::CURRENT_PROVIDER_OPTION_NAME, $providerId);
- Piwik_Tracker_Cache::clearCacheGeneral();
- return $provider;
- }
-
- /**
- * Returns a provider instance by ID or false if the ID is invalid or unavailable.
- *
- * @param string $providerId
- * @return Piwik_UserCountry_LocationProvider|false
- */
- public static function getProviderById( $providerId )
- {
- foreach (self::getAvailableProviders() as $provider)
- {
- $info = $provider->getInfo();
- if ($info['id'] == $providerId)
- {
- return $provider;
- }
- }
- return false;
- }
-
- /**
- * Tries to fill in any missing information in a location result.
- *
- * This method will try to set the continent code, continent name and country code
- * using other information.
- *
- * Note: This function must always be called by location providers in getLocation.
- *
- * @param array $location The location information to modify.
- */
- public function completeLocationResult( &$location )
- {
- // fill in continent code if country code is present
- if (empty($location[self::CONTINENT_CODE_KEY])
- && !empty($location[self::COUNTRY_CODE_KEY]))
- {
- $countryCode = strtolower($location[self::COUNTRY_CODE_KEY]);
- $location[self::CONTINENT_CODE_KEY] = Piwik_Common::getContinent($countryCode);
- }
-
- // fill in continent name if continent code is present
- if (empty($location[self::CONTINENT_NAME_KEY])
- && !empty($location[self::CONTINENT_CODE_KEY]))
- {
- $continentCode = strtolower($location[self::CONTINENT_CODE_KEY]);
- $location[self::CONTINENT_NAME_KEY] = Piwik_Translate('UserCountry_continent_'.$continentCode);
- }
-
- // fill in country name if country code is present
- if (empty($location[self::COUNTRY_NAME_KEY])
- && !empty($location[self::COUNTRY_CODE_KEY]))
- {
- $countryCode = strtolower($location[self::COUNTRY_CODE_KEY]);
- $location[self::COUNTRY_NAME_KEY] = Piwik_Translate('UserCountry_country_'.$countryCode);
- }
-
- // deal w/ improper latitude/longitude & round proper values
- if (!empty($location[self::LATITUDE_KEY]))
- {
- if (is_numeric($location[self::LATITUDE_KEY]))
- {
- $location[self::LATITUDE_KEY] = round($location[self::LATITUDE_KEY], self::GEOGRAPHIC_COORD_PRECISION);
- }
- else
- {
- unset($location[self::LATITUDE_KEY]);
- }
- }
-
- if (!empty($location[self::LONGITUDE_KEY]))
- {
- if (is_numeric($location[self::LONGITUDE_KEY]))
- {
- $location[self::LONGITUDE_KEY] = round($location[self::LONGITUDE_KEY], self::GEOGRAPHIC_COORD_PRECISION);
- }
- else
- {
- unset($location[self::LONGITUDE_KEY]);
- }
- }
- }
-
- /**
- * Returns a prettified location result.
- *
- * @param array|false $locationInfo
- * @param string $newline The line separator (ie, \n or <br/>).
- * @param bool $includeExtra Whether to include ISP/Organization info.
- * @return string
- */
- public static function prettyFormatLocation( $locationInfo, $newline = "\n", $includeExtra = false )
- {
- if ($locationInfo === false)
- {
- return Piwik_Translate('General_Unknown');
- }
-
- // add latitude/longitude line
- $lines = array();
- if (!empty($locationInfo[self::LATITUDE_KEY])
- && !empty($locationInfo[self::LONGITUDE_KEY]))
- {
- $lines[] = '('.$locationInfo[self::LATITUDE_KEY].', '.$locationInfo[self::LONGITUDE_KEY].')';
- }
-
- // add city/state line
- $cityState = array();
- if (!empty($locationInfo[self::CITY_NAME_KEY]))
- {
- $cityState[] = $locationInfo[self::CITY_NAME_KEY];
- }
-
- if (!empty($locationInfo[self::REGION_CODE_KEY]))
- {
- $cityState[] = $locationInfo[self::REGION_CODE_KEY];
- }
- else if (!empty($locationInfo[self::REGION_NAME_KEY]))
- {
- $cityState[] = $locationInfo[self::REGION_NAME_KEY];
- }
-
- if (!empty($cityState))
- {
- $lines[] = implode(', ', $cityState);
- }
-
- // add postal code line
- if (!empty($locationInfo[self::POSTAL_CODE_KEY]))
- {
- $lines[] = $locationInfo[self::POSTAL_CODE_KEY];
- }
-
- // add country line
- if (!empty($locationInfo[self::COUNTRY_NAME_KEY]))
- {
- $lines[] = $locationInfo[self::COUNTRY_NAME_KEY];
- }
- else if (!empty($locationInfo[self::COUNTRY_CODE_KEY]))
- {
- $lines[] = $locationInfo[self::COUNTRY_CODE_KEY];
- }
-
- // add extra information (ISP/Organization)
- if ($includeExtra)
- {
- $lines[] = '';
-
- $unknown = Piwik_Translate('General_Unknown');
-
- $org = !empty($locationInfo[self::ORG_KEY]) ? $locationInfo[self::ORG_KEY] : $unknown;
- $lines[] = "Org: $org";
-
- $isp = !empty($locationInfo[self::ISP_KEY]) ? $locationInfo[self::ISP_KEY] : $unknown;
- $lines[] = "ISP: $isp";
- }
-
- return implode($newline, $lines);
- }
-
- /**
- * Returns an IP address from an array that was passed into getLocation. This
- * will return an IPv4 address or false if the address is IPv6 (IPv6 is not
- * supported yet).
- *
- * @param array $ip Must have 'ip' key.
- * @return string|bool
- */
- protected function getIpFromInfo( $info )
- {
- $ip = $info['ip'];
- if (Piwik_IP::isMappedIPv4($ip))
- {
- return Piwik_IP::getIPv4FromMappedIPv6($ip);
- }
- else if (Piwik_IP::isIPv6($ip)) // IPv6 is not supported (yet)
- {
- return false;
- }
- else
- {
- return $ip;
- }
- }
+ const NOT_INSTALLED = 0;
+ const INSTALLED = 1;
+ const BROKEN = 2;
+
+ const CURRENT_PROVIDER_OPTION_NAME = 'usercountry.location_provider';
+
+ const GEOGRAPHIC_COORD_PRECISION = 3;
+
+ const CONTINENT_CODE_KEY = 'continent_code';
+ const CONTINENT_NAME_KEY = 'continent_name';
+ const COUNTRY_CODE_KEY = 'country_code';
+ const COUNTRY_NAME_KEY = 'country_name';
+ const REGION_CODE_KEY = 'region_code';
+ const REGION_NAME_KEY = 'region_name';
+ const CITY_NAME_KEY = 'city_name';
+ const AREA_CODE_KEY = 'area_code';
+ const LATITUDE_KEY = 'lat';
+ const LONGITUDE_KEY = 'long';
+ const POSTAL_CODE_KEY = 'postal_code';
+ const ISP_KEY = 'isp';
+ const ORG_KEY = 'org';
+
+ /**
+ * An array of all provider instances. Access it through static methods.
+ *
+ * @var array
+ */
+ public static $providers = null;
+
+ /**
+ * Returns location information based on visitor information.
+ *
+ * The result of this function will be an array. The array can store some or all of
+ * the following information:
+ *
+ * - Continent Code: The code of the visitor's continent.
+ * (array key is self::CONTINENT_CODE_KEY)
+ * - Continent Name: The name of the visitor's continent.
+ * (array key is self::CONTINENT_NAME_KEY)
+ * - Country Code: The code of the visitor's country.
+ * (array key is self::COUNTRY_CODE_KEY)
+ * - Country Name: The name of the visitor's country.
+ * (array key is self::COUNTRY_NAME_KEY)
+ * - Region Code: The code of the visitor's region.
+ * (array key is self::REGION_CODE_KEY)
+ * - Region Name: The name of the visitor's region.
+ * (array key is self::REGION_NAME_KEY)
+ * - City Name: The name of the visitor's city.
+ * (array key is self::CITY_NAME_KEY)
+ * - Area Code: The visitor's area code.
+ * (array key is self::AREA_CODE_KEY)
+ * - Latitude: The visitor's latitude.
+ * (array key is self::LATITUDE_KEY)
+ * - Longitude: The visitor's longitude.
+ * (array key is self::LONGITUDE_KEY)
+ * - Postal Code: The visitor's postal code.
+ * (array key is self::POSTAL_CODE_KEY)
+ * - ISP: The visitor's ISP.
+ * (array key is self::ISP_KEY)
+ * - Org: The company/organization of the visitor's IP.
+ * (array key is self::ORG_KEY)
+ *
+ * All LocationProviders will attempt to return the country of the visitor.
+ *
+ * @param array $info What this must contain depends on the specific provider
+ * implementation. All providers require an 'ip' key mapped
+ * to the visitor's IP address.
+ * @return array|false
+ */
+ abstract public function getLocation($info);
+
+ /**
+ * Returns true if this provider is available for use, false if otherwise.
+ *
+ * @return bool
+ */
+ abstract public function isAvailable();
+
+ /**
+ * Returns true if this provider is working, false if otherwise.
+ *
+ * @return bool
+ */
+ abstract public function isWorking();
+
+ /**
+ * Returns an array mapping location result keys w/ bool values indicating whether
+ * that information is supported by this provider. If it is not supported, that means
+ * this provider either cannot get this information, or is not configured to get it.
+ *
+ * @return array eg. array(self::CONTINENT_CODE_KEY => true,
+ * self::CONTINENT_NAME_KEY => true,
+ * self::ORG_KEY => false)
+ * The result is not guaranteed to have keys for every type of location
+ * info.
+ */
+ abstract public function getSupportedLocationInfo();
+
+ /**
+ * Returns every available provider instance.
+ *
+ * @return array
+ */
+ public static function getAllProviders()
+ {
+ if (is_null(self::$providers)) {
+ self::$providers = array();
+ foreach (get_declared_classes() as $klass) {
+ if (is_subclass_of($klass, 'Piwik_UserCountry_LocationProvider')) {
+ $klassInfo = new ReflectionClass($klass);
+ if ($klassInfo->isAbstract()) {
+ continue;
+ }
+
+ self::$providers[] = new $klass;
+ }
+ }
+ }
+
+ return self::$providers;
+ }
+
+ /**
+ * Returns all provider instances that are 'available'. An 'available' provider
+ * is one that is available for use. They may not necessarily be working.
+ *
+ * @return array
+ */
+ public static function getAvailableProviders()
+ {
+ $result = array();
+ foreach (self::getAllProviders() as $provider) {
+ if ($provider->isAvailable()) {
+ $result[] = $provider;
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * Returns an array mapping provider IDs w/ information about the provider,
+ * for each location provider.
+ *
+ * The following information is provided for each provider:
+ * 'id' - The provider's unique string ID.
+ * 'title' - The provider's title.
+ * 'description' - A description of how the location provider works.
+ * 'status' - Either self::NOT_INSTALLED, self::INSTALLED or self::BROKEN.
+ * 'statusMessage' - If the status is self::BROKEN, then the message describes why.
+ * 'location' - A pretty formatted location of the current IP address
+ * (Piwik_IP::getIpFromHeader()).
+ *
+ * An example result:
+ * array(
+ * 'geoip_php' => array('id' => 'geoip_php',
+ * 'title' => '...',
+ * 'desc' => '...',
+ * 'status' => Piwik_UserCountry_LocationProvider_GeoIp::BROKEN,
+ * 'statusMessage' => '...',
+ * 'location' => '...')
+ * 'geoip_serverbased' => array(...)
+ * )
+ *
+ * @param string $newline What to separate lines with in the pretty locations.
+ * @param bool $includeExtra Whether to include ISP/Org info in formatted location.
+ * @return array
+ */
+ public static function getAllProviderInfo($newline = "\n", $includeExtra = false)
+ {
+ $allInfo = array();
+ foreach (self::getAllProviders() as $provider) {
+ $info = $provider->getInfo();
+
+ $status = self::INSTALLED;
+ $location = false;
+ $statusMessage = false;
+
+ $availableOrMessage = $provider->isAvailable();
+ if ($availableOrMessage !== true) {
+ $status = self::NOT_INSTALLED;
+ if (is_string($availableOrMessage)) {
+ $statusMessage = $availableOrMessage;
+ }
+ } else {
+ $workingOrError = $provider->isWorking();
+ if ($workingOrError === true) // if the implementation is configured correctly, get the location
+ {
+ $locInfo = array('ip' => Piwik_IP::getIpFromHeader(),
+ 'lang' => Piwik_Common::getBrowserLanguage(),
+ 'disable_fallbacks' => true);
+
+ $location = $provider->getLocation($locInfo);
+ $location = self::prettyFormatLocation($location, $newline, $includeExtra);
+ } else // otherwise set an error message describing why
+ {
+ $status = self::BROKEN;
+ $statusMessage = $workingOrError;
+ }
+ }
+
+ $info['status'] = $status;
+ $info['statusMessage'] = $statusMessage;
+ $info['location'] = $location;
+
+ $allInfo[$info['order']] = $info;
+ }
+
+ ksort($allInfo);
+
+ $result = array();
+ foreach ($allInfo as $info) {
+ $result[$info['id']] = $info;
+ }
+ return $result;
+ }
+
+ /**
+ * Returns the ID of the currently used location provider.
+ *
+ * The used provider is stored in the 'usercountry.location_provider' option.
+ *
+ * This function should not be called by the Tracker.
+ *
+ * @return string
+ */
+ public static function getCurrentProviderId()
+ {
+ $optionValue = Piwik_GetOption(self::CURRENT_PROVIDER_OPTION_NAME);
+ return $optionValue === false ? Piwik_UserCountry_LocationProvider_Default::ID : $optionValue;
+ }
+
+ /**
+ * Returns the provider instance of the current location provider.
+ *
+ * This function should not be called by the Tracker.
+ *
+ * @return Piwik_UserCountry_LocationProvider
+ */
+ public static function getCurrentProvider()
+ {
+ return self::getProviderById(self::getCurrentProviderId());
+ }
+
+ /**
+ * Sets the provider to use when tracking.
+ *
+ * @param string $providerId The ID of the provider to use.
+ * @return Piwik_UserCountry_LocationProvider The new current provider.
+ * @throws Exception If the provider ID is invalid.
+ */
+ public static function setCurrentProvider($providerId)
+ {
+ $provider = self::getProviderById($providerId);
+ if ($provider === false) {
+ throw new Exception(
+ "Invalid provider ID '$providerId'. The provider either does not exist or is not available");
+ }
+ Piwik_SetOption(self::CURRENT_PROVIDER_OPTION_NAME, $providerId);
+ Piwik_Tracker_Cache::clearCacheGeneral();
+ return $provider;
+ }
+
+ /**
+ * Returns a provider instance by ID or false if the ID is invalid or unavailable.
+ *
+ * @param string $providerId
+ * @return Piwik_UserCountry_LocationProvider|false
+ */
+ public static function getProviderById($providerId)
+ {
+ foreach (self::getAvailableProviders() as $provider) {
+ $info = $provider->getInfo();
+ if ($info['id'] == $providerId) {
+ return $provider;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Tries to fill in any missing information in a location result.
+ *
+ * This method will try to set the continent code, continent name and country code
+ * using other information.
+ *
+ * Note: This function must always be called by location providers in getLocation.
+ *
+ * @param array $location The location information to modify.
+ */
+ public function completeLocationResult(&$location)
+ {
+ // fill in continent code if country code is present
+ if (empty($location[self::CONTINENT_CODE_KEY])
+ && !empty($location[self::COUNTRY_CODE_KEY])
+ ) {
+ $countryCode = strtolower($location[self::COUNTRY_CODE_KEY]);
+ $location[self::CONTINENT_CODE_KEY] = Piwik_Common::getContinent($countryCode);
+ }
+
+ // fill in continent name if continent code is present
+ if (empty($location[self::CONTINENT_NAME_KEY])
+ && !empty($location[self::CONTINENT_CODE_KEY])
+ ) {
+ $continentCode = strtolower($location[self::CONTINENT_CODE_KEY]);
+ $location[self::CONTINENT_NAME_KEY] = Piwik_Translate('UserCountry_continent_' . $continentCode);
+ }
+
+ // fill in country name if country code is present
+ if (empty($location[self::COUNTRY_NAME_KEY])
+ && !empty($location[self::COUNTRY_CODE_KEY])
+ ) {
+ $countryCode = strtolower($location[self::COUNTRY_CODE_KEY]);
+ $location[self::COUNTRY_NAME_KEY] = Piwik_Translate('UserCountry_country_' . $countryCode);
+ }
+
+ // deal w/ improper latitude/longitude & round proper values
+ if (!empty($location[self::LATITUDE_KEY])) {
+ if (is_numeric($location[self::LATITUDE_KEY])) {
+ $location[self::LATITUDE_KEY] = round($location[self::LATITUDE_KEY], self::GEOGRAPHIC_COORD_PRECISION);
+ } else {
+ unset($location[self::LATITUDE_KEY]);
+ }
+ }
+
+ if (!empty($location[self::LONGITUDE_KEY])) {
+ if (is_numeric($location[self::LONGITUDE_KEY])) {
+ $location[self::LONGITUDE_KEY] = round($location[self::LONGITUDE_KEY], self::GEOGRAPHIC_COORD_PRECISION);
+ } else {
+ unset($location[self::LONGITUDE_KEY]);
+ }
+ }
+ }
+
+ /**
+ * Returns a prettified location result.
+ *
+ * @param array|false $locationInfo
+ * @param string $newline The line separator (ie, \n or <br/>).
+ * @param bool $includeExtra Whether to include ISP/Organization info.
+ * @return string
+ */
+ public static function prettyFormatLocation($locationInfo, $newline = "\n", $includeExtra = false)
+ {
+ if ($locationInfo === false) {
+ return Piwik_Translate('General_Unknown');
+ }
+
+ // add latitude/longitude line
+ $lines = array();
+ if (!empty($locationInfo[self::LATITUDE_KEY])
+ && !empty($locationInfo[self::LONGITUDE_KEY])
+ ) {
+ $lines[] = '(' . $locationInfo[self::LATITUDE_KEY] . ', ' . $locationInfo[self::LONGITUDE_KEY] . ')';
+ }
+
+ // add city/state line
+ $cityState = array();
+ if (!empty($locationInfo[self::CITY_NAME_KEY])) {
+ $cityState[] = $locationInfo[self::CITY_NAME_KEY];
+ }
+
+ if (!empty($locationInfo[self::REGION_CODE_KEY])) {
+ $cityState[] = $locationInfo[self::REGION_CODE_KEY];
+ } else if (!empty($locationInfo[self::REGION_NAME_KEY])) {
+ $cityState[] = $locationInfo[self::REGION_NAME_KEY];
+ }
+
+ if (!empty($cityState)) {
+ $lines[] = implode(', ', $cityState);
+ }
+
+ // add postal code line
+ if (!empty($locationInfo[self::POSTAL_CODE_KEY])) {
+ $lines[] = $locationInfo[self::POSTAL_CODE_KEY];
+ }
+
+ // add country line
+ if (!empty($locationInfo[self::COUNTRY_NAME_KEY])) {
+ $lines[] = $locationInfo[self::COUNTRY_NAME_KEY];
+ } else if (!empty($locationInfo[self::COUNTRY_CODE_KEY])) {
+ $lines[] = $locationInfo[self::COUNTRY_CODE_KEY];
+ }
+
+ // add extra information (ISP/Organization)
+ if ($includeExtra) {
+ $lines[] = '';
+
+ $unknown = Piwik_Translate('General_Unknown');
+
+ $org = !empty($locationInfo[self::ORG_KEY]) ? $locationInfo[self::ORG_KEY] : $unknown;
+ $lines[] = "Org: $org";
+
+ $isp = !empty($locationInfo[self::ISP_KEY]) ? $locationInfo[self::ISP_KEY] : $unknown;
+ $lines[] = "ISP: $isp";
+ }
+
+ return implode($newline, $lines);
+ }
+
+ /**
+ * Returns an IP address from an array that was passed into getLocation. This
+ * will return an IPv4 address or false if the address is IPv6 (IPv6 is not
+ * supported yet).
+ *
+ * @param array $ip Must have 'ip' key.
+ * @return string|bool
+ */
+ protected function getIpFromInfo($info)
+ {
+ $ip = $info['ip'];
+ if (Piwik_IP::isMappedIPv4($ip)) {
+ return Piwik_IP::getIPv4FromMappedIPv6($ip);
+ } else if (Piwik_IP::isIPv6($ip)) // IPv6 is not supported (yet)
+ {
+ return false;
+ } else {
+ return $ip;
+ }
+ }
}