1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
/* |
6
|
|
|
* This file is part of the Geocoder package. |
7
|
|
|
* For the full copyright and license information, please view the LICENSE |
8
|
|
|
* file that was distributed with this source code. |
9
|
|
|
* |
10
|
|
|
* @license MIT License |
11
|
|
|
*/ |
12
|
|
|
|
13
|
|
|
namespace Geocoder\Provider\HostIp; |
14
|
|
|
|
15
|
|
|
use Geocoder\Exception\UnsupportedOperation; |
16
|
|
|
use Geocoder\Collection; |
17
|
|
|
use Geocoder\Model\Address; |
18
|
|
|
use Geocoder\Model\AddressCollection; |
19
|
|
|
use Geocoder\Query\GeocodeQuery; |
20
|
|
|
use Geocoder\Query\ReverseQuery; |
21
|
|
|
use Geocoder\Http\Provider\AbstractHttpProvider; |
22
|
|
|
use Geocoder\Provider\Provider; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* @author William Durand <[email protected]> |
26
|
|
|
*/ |
27
|
|
|
final class HostIp extends AbstractHttpProvider implements Provider |
28
|
|
|
{ |
29
|
|
|
/** |
30
|
|
|
* @var string |
31
|
|
|
*/ |
32
|
|
|
const ENDPOINT_URL = 'http://api.hostip.info/get_json.php?ip=%s&position=true'; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* {@inheritdoc} |
36
|
|
|
*/ |
37
|
11 |
|
public function geocodeQuery(GeocodeQuery $query): Collection |
38
|
|
|
{ |
39
|
11 |
|
$address = $query->getText(); |
40
|
11 |
|
if (!filter_var($address, FILTER_VALIDATE_IP)) { |
41
|
1 |
|
throw new UnsupportedOperation('The HostIp provider does not support Street addresses.'); |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
// This API does not support IPv6 |
45
|
10 |
|
if (filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { |
46
|
2 |
|
throw new UnsupportedOperation('The HostIp provider does not support IPv6 addresses.'); |
47
|
|
|
} |
48
|
|
|
|
49
|
8 |
|
if ('127.0.0.1' === $address) { |
50
|
1 |
|
return new AddressCollection([$this->getLocationForLocalhost()]); |
51
|
|
|
} |
52
|
|
|
|
53
|
7 |
|
$url = sprintf(self::ENDPOINT_URL, $address); |
54
|
|
|
|
55
|
7 |
|
return $this->executeQuery($url); |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* {@inheritdoc} |
60
|
|
|
*/ |
61
|
1 |
|
public function reverseQuery(ReverseQuery $query): Collection |
62
|
|
|
{ |
63
|
1 |
|
throw new UnsupportedOperation('The HostIp provider is not able to do reverse geocoding.'); |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* {@inheritdoc} |
68
|
|
|
*/ |
69
|
4 |
|
public function getName(): string |
70
|
|
|
{ |
71
|
4 |
|
return 'host_ip'; |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* @param string $url |
76
|
|
|
* |
77
|
|
|
* @return Collection |
78
|
|
|
*/ |
79
|
7 |
|
private function executeQuery(string $url): AddressCollection |
80
|
|
|
{ |
81
|
7 |
|
$content = $this->getUrlContents($url); |
82
|
2 |
|
$data = json_decode($content, true); |
83
|
|
|
|
84
|
2 |
|
if (!$data) { |
85
|
|
|
return new AddressCollection([]); |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
// Return empty collection if address was not found |
89
|
2 |
View Code Duplication |
if (null === $data['lat'] |
|
|
|
|
90
|
2 |
|
&& null === $data['lng'] |
91
|
2 |
|
&& '(Unknown City?)' === $data['city'] |
92
|
2 |
|
&& '(Unknown Country?)' === $data['country_name'] |
93
|
2 |
|
&& 'XX' === $data['country_code']) { |
94
|
|
|
return new AddressCollection([]); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
// Return empty collection if address was not found |
98
|
2 |
View Code Duplication |
if (null === $data['lat'] |
|
|
|
|
99
|
2 |
|
&& null === $data['lng'] |
100
|
2 |
|
&& '(Private Address)' === $data['city'] |
101
|
2 |
|
&& '(Private Address)' === $data['country_name'] |
102
|
2 |
|
&& 'XX' === $data['country_code']) { |
103
|
|
|
return new AddressCollection([]); |
104
|
|
|
} |
105
|
|
|
|
106
|
2 |
|
return new AddressCollection([ |
107
|
2 |
|
Address::createFromArray([ |
108
|
2 |
|
'providedBy' => $this->getName(), |
109
|
2 |
|
'latitude' => $data['lat'], |
110
|
2 |
|
'longitude' => $data['lng'], |
111
|
2 |
|
'locality' => $data['city'], |
112
|
2 |
|
'country' => $data['country_name'], |
113
|
2 |
|
'countryCode' => $data['country_code'], |
114
|
|
|
]), |
115
|
|
|
]); |
116
|
|
|
} |
117
|
|
|
} |
118
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.