forked from div-production/yii2-geoip
-
Notifications
You must be signed in to change notification settings - Fork 0
/
IpGeoBase.php
133 lines (117 loc) · 4.88 KB
/
IpGeoBase.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<?php
namespace div\geoip;
use yii\base\Component;
class IpGeoBase extends Component
{
/**
* используемая кодировка
* @var string
*/
public $charset = 'utf-8';
public $ip;
/**
* Создаем объект с заданными настройками.
* @return void
*/
public function init()
{
if (!$this->ip) {
$this->ip = $this->getIp();
}
}
/**
* функция возвращет конкретное значение из полученного массива данных по ip
* @param string - ключ массива. Если интересует конкретное значение.
* Ключ может быть равным 'inetnum', 'country', 'city', 'region', 'district', 'lat', 'lng'
* @param boolean - устанавливаем хранить данные в куки или нет
* Если true, то в куки будут записаны данные по ip и повторные запросы на ipgeobase происходить не будут.
* Если false, то данные постоянно будут запрашиваться с ipgeobase
* @return string|null - дополнительно читайте комментарии внутри функции.
*/
public function getValue($key)
{
$key_array = array('inetnum', 'country', 'city', 'region', 'district', 'lat', 'lng');
if (!in_array($key, $key_array)) {
$key = null;
}
$data = $this->getData();
if ($key) { // если указан ключ
if (isset($data[$key])) { // и значение есть в массиве данных
return $data[$key]; // возвращаем строку с нужными данными
} else { // иначе если были включены куки
return null;
}
} else {
return null;
}
}
/**
* Получаем данные с сервера или из cookie
* @return string|array
*/
public function getData()
{
return $this->getGeobaseData();
}
/**
* функция получает данные по ip.
* @return array - возвращает массив с данными
*/
protected function getGeobaseData()
{
// получаем данные по ip
$ch = curl_init('http://ipgeobase.ru:7020/geo?ip=' . $this->ip);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 3);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
$string = curl_exec($ch);
// если указана кодировка отличная от windows-1251, изменяем кодировку
if ($this->charset != 'windows-1251' && function_exists('iconv')) {
$string = iconv('windows-1251', $this->charset, $string);
}
$data = $this->parseString($string);
return $data;
}
/**
* функция парсит полученные в XML данные в случае, если на сервере не установлено расширение Simplexml
* @param string $string
* @return array - возвращает массив с данными
*/
protected function parseString($string)
{
$params = array('inetnum', 'country', 'city', 'region', 'district', 'lat', 'lng');
$data = $out = array();
foreach ($params as $param) {
if (preg_match('#<' . $param . '>(.*)</' . $param . '>#is', $string, $out)) {
$data[$param] = trim($out[1]);
}
}
return $data;
}
/**
* функция определяет ip адрес по глобальному массиву $_SERVER
* ip адреса проверяются начиная с приоритетного, для определения возможного использования прокси
* @return string ip-адрес
*/
public function getIp()
{
$keys = array('HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'REMOTE_ADDR', 'HTTP_X_REAL_IP');
foreach ($keys as $key) {
$ip = trim(strtok(filter_input(INPUT_SERVER, $key), ','));
if ($this->isValidIp($ip)) {
return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
}
}
return null;
}
/**
* функция для проверки валидности ip адреса
* @param string $ip адрес в формате 1.2.3.4
* @return boolean : true - если ip валидный, иначе false
*/
public function isValidIp($ip)
{
return (bool)filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
}
}