Your IP : 52.15.73.112


Current Path : /var/www/www-root/data/www/monolith-realty.ru/bitrix/modules/main/lib/service/geoip/
Upload File :
Current File : /var/www/www-root/data/www/monolith-realty.ru/bitrix/modules/main/lib/service/geoip/maxmind.php

<?php

namespace Bitrix\Main\Service\GeoIp;

use Bitrix\Main;
use Bitrix\Main\Error;
use Bitrix\Main\Text\Encoding;
use Bitrix\Main\Web\HttpClient;
use Bitrix\Main\Localization\Loc;

/**
 * Class MaxMind
 * @package Bitrix\Main\Service\GeoIp
 * @link https://www.maxmind.com
 */
class MaxMind extends Base
{
	/**
	 * @return string Title of handler.
	 */
	public function getTitle()
	{
		return 'MaxMind';
	}

	/**
	 * @return string Handler description.
	 */
	public function getDescription()
	{
		return Loc::getMessage('MAIN_SRV_GEOIP_MM_DESCRIPTION');
	}

	/**
	 * @param string $ipAddress Ip address
	 * @param string $userId user identifier obtained from www.maxmind.com
	 * @param string $licenseKey
	 * @return Main\Result
	 */
	protected function sendRequest($ipAddress, $userId, $licenseKey)
	{
		$result = new Main\Result();
		$httpClient = $this->getHttpClient();
		$httpClient->setAuthorization($userId, $licenseKey);

		$httpRes = $httpClient->get($this->getEndpoint() . $ipAddress . '?pretty');

		$errors = $httpClient->getError();

		if (!$httpRes && !empty($errors))
		{
			$strError = "";

			foreach($errors as $errorCode => $errMes)
				$strError .= $errorCode.": ".$errMes;

			$result->addError(new Error($strError));
		}
		else
		{
			$status = $httpClient->getStatus();

			if ($status != 200)
				$result->addError(new Error('Http status: '.$status));

			$arRes = json_decode($httpRes, true);

			if(is_array($arRes))
			{
				if ($status == 200)
				{
					$result->setData($arRes);
				}
				else
				{
					$result->addError(new Error('['.$arRes['code'].'] '.$arRes['error']));
				}
			}
			else
			{
				$result->addError(new Error('Can\'t decode json result'));
			}
		}

		return $result;
	}

	/**
	 * @return HttpClient
	 */
	protected static function getHttpClient()
	{
		return new HttpClient(array(
			"version" => "1.1",
			"socketTimeout" => 5,
			"streamTimeout" => 5,
			"redirect" => true,
			"redirectMax" => 5,
		));
	}

	/**
	 * Languages supported by handler ISO 639-1
	 * @return array
	 */
	public function getSupportedLanguages()
	{
		return array('de', 'en', 'es', 'fr', 'ja', 'pt-BR', 'ru', 'zh-CN');
	}

	/**
	 * @param string $ip Ip address
	 * @param string $lang Language identifier
	 * @return Result | null
	 */
	public function getDataResult($ip, $lang = '')
	{
		$dataResult = new Result();
		$geoData = new Data();
		
		$geoData->lang = ($lang <> '' ? $lang : 'en');

		if($this->config['USER_ID'] == '' || $this->config['LICENSE_KEY'] == '')
		{
			$dataResult->addError(new Error(Loc::getMessage('MAIN_SRV_GEOIP_MM_SETT_EMPTY')));
			return $dataResult;
		}

		$res = $this->sendRequest($ip, $this->config['USER_ID'], $this->config['LICENSE_KEY']);

		if($res->isSuccess())
		{
			$lang = $geoData->lang;

			$data = $res->getData();

			if (strtolower(SITE_CHARSET) != 'utf-8')
			{
				$data = Encoding::convertEncoding($data, 'UTF-8', SITE_CHARSET);
			}

			$geoData->ipNetwork = $data['traits']['network'] ?? null;

			$geoData->continentCode = $data['continent']['code'] ?? null;
			$geoData->continentName = $data['continent']['names'][$lang] ?? $data['continent']['name'] ?? null;

			$geoData->countryCode = $data['country']['iso_code'] ?? null;
			$geoData->countryName = $data['country']['names'][$lang] ?? $data['country']['name'] ?? null;

			$geoData->regionCode = $data['subdivisions'][0]['iso_code'] ?? null;
			$geoData->regionGeonameId = $data['subdivisions'][0]['geoname_id'] ?? null;
			$geoData->regionName = $data['subdivisions'][0]['names'][$lang] ?? $data['subdivisions'][0]['name'] ?? null;

			if ($geoData->regionGeonameId)
			{
				$geoData->geonames[$geoData->regionGeonameId] = $res->getData()['subdivisions'][0]['names'] ?? [];
			}

			$geoData->subRegionCode = $data['subdivisions'][1]['iso_code'] ?? null;
			$geoData->subRegionGeonameId = $data['subdivisions'][1]['geoname_id'] ?? null;
			$geoData->subRegionName = $data['subdivisions'][1]['names'][$lang] ?? $data['subdivisions'][1]['name'] ?? null;

			if ($geoData->subRegionGeonameId)
			{
				$geoData->geonames[$geoData->subRegionGeonameId] = $res->getData()['subdivisions'][1]['names'] ?? [];
			}

			$geoData->cityName = $data['city']['names'][$lang] ?? $data['city']['name'] ?? null;
			$geoData->cityGeonameId = $data['city']['geoname_id'] ?? null;

			if ($geoData->cityGeonameId)
			{
				$geoData->geonames[$geoData->cityGeonameId] = $res->getData()['city']['names'] ?? [];
			}

			$geoData->latitude = $data['location']['latitude'] ?? null;
			$geoData->longitude = $data['location']['longitude'] ?? null;
			$geoData->timezone = $data['location']['time_zone'] ?? null;

			$geoData->zipCode = $data['postal']['code'] ?? null;

			$geoData->ispName = $data['traits']['isp'] ?? null;
			$geoData->organizationName = $data['traits']['organization'] ?? null;
			$geoData->asn = $data['traits']['autonomous_system_number'] ?? null;
			$geoData->asnOrganizationName = $data['traits']['autonomous_system_organization'] ?? null;
		}
		else
		{
			$dataResult->addErrors($res->getErrors());
		}

		$dataResult->setGeoData($geoData);
		return $dataResult;
	}

	/**
	 * Is this handler installed and ready for using.
	 * @return bool
	 */
	public function isInstalled()
	{
		return !empty($this->config['USER_ID']) && !empty($this->config['LICENSE_KEY']);
	}

	/**
	 * @param array $postFields  Admin form posted fields during saving process.
	 * @return array Field CONFIG for saving to DB in admin edit form.
	 */
	public function createConfigField(array $postFields)
	{
		return array(
			'SERVICE' => $postFields['SERVICE'] ?? 'GeoIP2City',
			'USER_ID' => $postFields['USER_ID'] ?? '',
			'LICENSE_KEY' => $postFields['LICENSE_KEY'] ?? '',
		);
	}

	/**
	 * @return array Set of fields description for administration purposes.
	 */
	public function getConfigForAdmin()
	{
		return [
			[
				'NAME' => 'SERVICE',
				'TITLE' => Loc::getMessage("main_geoip_mm_service"),
				'TYPE' => 'LIST',
				'VALUE' => ($this->config['SERVICE'] ?? 'GeoIP2City'),
				'OPTIONS' => [
					'GeoLite2Country' => 'GeoLite2 Country',
					'GeoLite2City' => 'GeoLite2 City',
					'GeoIP2Country' => 'GeoIP2 Country',
					'GeoIP2City' => 'GeoIP2 City',
					'GeoIP2Insights' => 'GeoIP2 Insights',
				],
				'REQUIRED' => true,
			],
			[
				'NAME' => 'USER_ID',
				'TITLE' => Loc::getMessage('MAIN_SRV_GEOIP_MM_F_USER_ID'),
				'TYPE' => 'TEXT',
				'VALUE' => htmlspecialcharsbx($this->config['USER_ID']),
				'REQUIRED' => true,
			],
			[
				'NAME' => 'LICENSE_KEY',
				'TITLE' => Loc::getMessage('MAIN_SRV_GEOIP_MM_F_LICENSE_KEY'),
				'TYPE' => 'TEXT',
				'VALUE' => htmlspecialcharsbx($this->config['LICENSE_KEY']),
				'REQUIRED' => true,
			]
		];
	}

	/**
	 * @return ProvidingData Geolocation information witch handler can return.
	 */
	public function getProvidingData()
	{
		$service = $this->config['SERVICE'] ?? 'GeoIP2City';

		if ($service == 'GeoLite2Country' || $service == 'GeoIP2Country')
		{
			return ProvidingData::createForCountry();
		}

		return ProvidingData::createForCity();
	}

	protected function getEndpoint(): string
	{
		static $endpoints = [
			'GeoLite2Country' => 'https://geolite.info/geoip/v2.1/country/',
			'GeoLite2City' => 'https://geolite.info/geoip/v2.1/city/',
			'GeoIP2Country' => 'https://geoip.maxmind.com/geoip/v2.1/country/',
			'GeoIP2City' => 'https://geoip.maxmind.com/geoip/v2.1/city/',
			'GeoIP2Insights' => 'https://geoip.maxmind.com/geoip/v2.1/insights/',
		];

		$service = $this->config['SERVICE'] ?? 'GeoIP2City';
		if (isset($endpoints[$service]))
		{
			return $endpoints[$service];
		}
		return $endpoints['GeoIP2City'];
	}
}