zend-blog-3-backend
167 строк · 4.4 Кб
1<?php
2/**
3* Created by PhpStorm.
4* User: morontt
5* Date: 13.11.16
6* Time: 13:05
7*/
8
9namespace App\Service;
10
11use App\Entity\GeoLocation;
12use App\Entity\GeoLocationCity;
13use App\Entity\GeoLocationCountry;
14use App\Service\IpInfo\IpInfoClientInterface;
15use App\Service\IpInfo\LocationInfo;
16use Doctrine\ORM\EntityManager;
17use Doctrine\ORM\EntityManagerInterface;
18
19class IpInfo
20{
21/**
22* @var EntityManager
23*/
24private $em;
25
26private IpInfoClientInterface $ipInfoClient;
27
28/**
29* @param EntityManagerInterface $em
30* @param IpInfoClientInterface $ipInfoClient
31*/
32public function __construct(EntityManagerInterface $em, IpInfoClientInterface $ipInfoClient)
33{
34$this->em = $em;
35$this->ipInfoClient = $ipInfoClient;
36}
37
38/**
39* @param string $ip
40*
41* @return GeoLocation|null
42*/
43public function getLocationByIp(string $ip)
44{
45$location = $this->em->getRepository(GeoLocation::class)->findOrCreateByIpAddress($ip);
46if ($location && !$location->getCity()) {
47$location->increaseCountOfCheck();
48$data = $this->getCityInfo($ip);
49if ($data) {
50$location->setCity($this->getCity($data));
51}
52
53$this->em->flush();
54}
55
56return $location;
57}
58
59/**
60* Following RFC 1918, Section 3
61*
62* 10.0.0.0 - 10.255.255.255 (10/8 prefix)
63* 172.16.0.0 - 172.31.255.255 (172.16/12 prefix)
64* 192.168.0.0 - 192.168.255.255 (192.168/16 prefix)
65*
66* @param string $ip
67*
68* @return bool
69*/
70public function isPrivateIP(string $ip): bool
71{
72$ip4 = array_map(function ($b) { return (int)$b; }, explode('.', $ip));
73
74return $ip4[0] == 10
75|| ($ip4[0] == 172 && ($ip4[1] & 0xf0) == 16)
76|| ($ip4[0] == 192 && $ip4[1] == 168);
77}
78
79/**
80* @param LocationInfo $data
81*
82* @return GeoLocationCity|null
83*/
84protected function getCity(LocationInfo $data)
85{
86$city = null;
87if (!empty($data->cityName) && !empty($data->regionName)) {
88$country = $this->getCountry($data);
89if ($country) {
90$city = $this->em->getRepository(GeoLocationCity::class)->findOneBy([
91'city' => $data->cityName,
92'region' => $data->regionName,
93'country' => $country->getId(),
94]);
95
96if (!$city) {
97$city = new GeoLocationCity();
98$city
99->setCity($data->cityName)
100->setRegion($data->regionName)
101->setLatitude($data->latitude)
102->setLongitude($data->longitude)
103->setTimeZone($data->timeZone)
104->setZip($data->zipCode)
105->setCountry($country)
106;
107
108$this->em->persist($city);
109$this->em->flush();
110}
111}
112}
113
114return $city;
115}
116
117/**
118* @param LocationInfo $data
119*
120* @return GeoLocationCountry|null
121*/
122protected function getCountry(LocationInfo $data)
123{
124$country = null;
125if (!empty($data->countryCode) && !empty($data->countryName)) {
126$country = $this->em
127->getRepository(GeoLocationCountry::class)
128->findOneByCode($data->countryCode);
129
130if (!$country) {
131$country = new GeoLocationCountry();
132$country
133->setCode($data->countryCode)
134->setName($data->countryName)
135;
136
137$this->em->persist($country);
138$this->em->flush();
139}
140}
141
142return $country;
143}
144
145/**
146* @param $ip
147*
148* @return LocationInfo|null
149*/
150protected function getCityInfo($ip): ?LocationInfo
151{
152if (filter_var($ip, FILTER_VALIDATE_IP)) {
153if ($this->isPrivateIP($ip)) {
154return LocationInfo::createFromArray([
155'countryCode' => '-',
156'countryName' => '-',
157'regionName' => '-',
158'cityName' => '-',
159]);
160}
161
162return $this->ipInfoClient->getLocationInfo($ip);
163}
164
165return null;
166}
167}
168