| 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\GeoIPs; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  | use Geocoder\Collection; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  | use Geocoder\Exception\InvalidArgument; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  | use Geocoder\Exception\InvalidCredentials; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  | use Geocoder\Exception\InvalidServerResponse; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  | use Geocoder\Exception\QuotaExceeded; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  | use Geocoder\Exception\UnsupportedOperation; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  | use Geocoder\Model\Address; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  | use Geocoder\Model\AddressCollection; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  | use Geocoder\Query\GeocodeQuery; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  | use Geocoder\Query\ReverseQuery; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  | use Geocoder\Http\Provider\AbstractHttpProvider; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  | use Geocoder\Provider\Provider; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  | use Http\Client\HttpClient; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  | /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |  * @author Andrea Cristaudo <[email protected]> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |  * @author Arthur Bodera <[email protected]> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  |  * @deprecated The GeoIPs provider has shut down | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  |  * @see https://github.com/geocoder-php/Geocoder/issues/965 | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 35 |  |  |  */ | 
            
                                                                        
                            
            
                                    
            
            
                | 36 |  |  | final class GeoIPs extends AbstractHttpProvider implements Provider | 
            
                                                                        
                            
            
                                    
            
            
                | 37 |  |  | { | 
            
                                                                        
                            
            
                                    
            
            
                | 38 |  |  |     /** | 
            
                                                                        
                            
            
                                    
            
            
                | 39 |  |  |      * @var string | 
            
                                                                        
                            
            
                                    
            
            
                | 40 |  |  |      */ | 
            
                                                                        
                            
            
                                    
            
            
                | 41 |  |  |     const GEOCODE_ENDPOINT_URL = 'https://api.geoips.com/ip/%s/key/%s/output/json/timezone/true/'; | 
            
                                                                        
                            
            
                                    
            
            
                | 42 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 43 |  |  |     const CODE_SUCCESS = '200_1'; // The following results has been returned. | 
            
                                                                        
                            
            
                                    
            
            
                | 44 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 45 |  |  |     const CODE_NOT_FOUND = '200_2'; // No result set has been returned. | 
            
                                                                        
                            
            
                                    
            
            
                | 46 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 47 |  |  |     const CODE_BAD_KEY = '400_1'; // Error in the URI - The API call should include a API key parameter. | 
            
                                                                        
                            
            
                                    
            
            
                | 48 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 49 |  |  |     const CODE_BAD_IP = '400_2'; // Error in the URI - The API call should include a valid IP address. | 
            
                                                                        
                            
            
                                    
            
            
                | 50 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 51 |  |  |     const CODE_NOT_AUTHORIZED = '403_1'; // The API key associated with your request was not recognized. | 
            
                                                                        
                            
            
                                    
            
            
                | 52 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 53 |  |  |     const CODE_ACCOUNT_INACTIVE = '403_2'; // The API key has not been approved or has been disabled. | 
            
                                                                        
                            
            
                                    
            
            
                | 54 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 55 |  |  |     const CODE_LIMIT_EXCEEDED = '403_3'; // The service you have requested is over capacity. | 
            
                                                                        
                            
            
                                    
            
            
                | 56 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 57 |  |  |     /** | 
            
                                                                        
                            
            
                                    
            
            
                | 58 |  |  |      * @var string | 
            
                                                                        
                            
            
                                    
            
            
                | 59 |  |  |      */ | 
            
                                                                        
                            
            
                                    
            
            
                | 60 |  |  |     private $apiKey; | 
            
                                                                        
                            
            
                                    
            
            
                | 61 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 62 |  |  |     /** | 
            
                                                                        
                            
            
                                    
            
            
                | 63 |  |  |      * @deprecated The GeoIPs provider has shut down | 
            
                                                                        
                            
            
                                    
            
            
                | 64 |  |  |      * | 
            
                                                                        
                            
            
                                    
            
            
                | 65 |  |  |      * @param HttpClient $client An HTTP adapter | 
            
                                                                        
                            
            
                                    
            
            
                | 66 |  |  |      * @param string     $apiKey An API key | 
            
                                                                        
                            
            
                                    
            
            
                | 67 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 | 22 |  |     public function __construct(HttpClient $client, string $apiKey) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 | 22 |  |         if (empty($apiKey)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  |             throw new InvalidCredentials('No API key provided.'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 | 22 |  |         $this->apiKey = $apiKey; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 | 22 |  |         parent::__construct($client); | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 76 | 22 |  |     } | 
            
                                                                        
                            
            
                                    
            
            
                | 77 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 78 |  |  |     /** | 
            
                                                                        
                            
            
                                    
            
            
                | 79 |  |  |      * {@inheritdoc} | 
            
                                                                        
                            
            
                                    
            
            
                | 80 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 | 20 |  |     public function geocodeQuery(GeocodeQuery $query): Collection | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 | 20 |  |         $address = $query->getText(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 | 20 |  |         if (!filter_var($address, FILTER_VALIDATE_IP)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 | 1 |  |             throw new UnsupportedOperation('The GeoIPs provider does not support street addresses, only IPv4 addresses.'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 | 19 |  |         if (filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 | 1 |  |             throw new UnsupportedOperation('The GeoIPs provider does not support IPv6 addresses, only IPv4 addresses.'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 | 18 |  |         if ('127.0.0.1' === $address) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 | 1 |  |             return new AddressCollection([$this->getLocationForLocalhost()]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 | 17 |  |         $query = sprintf(self::GEOCODE_ENDPOINT_URL, $address, $this->apiKey); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 | 17 |  |         return $this->executeQuery($query); | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 99 |  |  |     } | 
            
                                                                        
                            
            
                                    
            
            
                | 100 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 101 |  |  |     /** | 
            
                                                                        
                            
            
                                    
            
            
                | 102 |  |  |      * {@inheritdoc} | 
            
                                                                        
                            
            
                                    
            
            
                | 103 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 | 1 |  |     public function reverseQuery(ReverseQuery $query): Collection | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 | 1 |  |         throw new UnsupportedOperation('The GeoIPs provider is not able to do reverse geocoding.'); | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 107 |  |  |     } | 
            
                                                                        
                            
            
                                    
            
            
                | 108 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 109 |  |  |     /** | 
            
                                                                        
                            
            
                                    
            
            
                | 110 |  |  |      * {@inheritdoc} | 
            
                                                                        
                            
            
                                    
            
            
                | 111 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 | 6 |  |     public function getName(): string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 | 6 |  |         return 'geo_ips'; | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 115 |  |  |     } | 
            
                                                                        
                            
            
                                    
            
            
                | 116 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 117 |  |  |     /** | 
            
                                                                        
                            
            
                                    
            
            
                | 118 |  |  |      * @param string $url | 
            
                                                                        
                            
            
                                    
            
            
                | 119 |  |  |      * | 
            
                                                                        
                            
            
                                    
            
            
                | 120 |  |  |      * @return AddressCollection | 
            
                                                                        
                            
            
                                    
            
            
                | 121 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 | 17 |  |     private function executeQuery(string $url): AddressCollection | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 | 17 |  |         $content = $this->getUrlContents($url); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 | 10 |  |         $json = json_decode($content, true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 | 10 |  |         if (isset($json['error'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 | 5 |  |             switch ($json['error']['code']) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 | 5 |  |                 case static::CODE_BAD_IP: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 | 1 |  |                     throw new InvalidArgument('The API call should include a valid IP address.'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 | 4 |  |                 case static::CODE_BAD_KEY: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 | 1 |  |                     throw new InvalidCredentials('The API call should include a API key parameter.'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 | 3 |  |                 case static::CODE_NOT_AUTHORIZED: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 | 1 |  |                     throw new InvalidCredentials('The API key associated with your request was not recognized.'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 | 2 |  |                 case static::CODE_ACCOUNT_INACTIVE: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 | 1 |  |                     throw new InvalidCredentials('The API key has not been approved or has been disabled.'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 | 1 |  |                 case static::CODE_LIMIT_EXCEEDED: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 | 1 |  |                     throw new QuotaExceeded('The service you have requested is over capacity.'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  |                 default: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  |                     throw new InvalidServerResponse(sprintf('GeoIPs error %s%s%s%s - query: %s', $json['error']['code'], isset($json['error']['status']) ? ', '.$json['error']['status'] : '', isset($json['error']['message']) ? ', '.$json['error']['message'] : '', isset($json['error']['notes']) ? ', '.$json['error']['notes'] : '', $url)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 | 5 |  |         if (!is_array($json) || empty($json) || empty($json['response']) || empty($json['response']['code'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  |             throw InvalidServerResponse::create($url); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 | 5 |  |         $response = $json['response']; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  |         // Check response code | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 | 5 |  |         switch ($response['code']) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 | 5 |  |             case static::CODE_SUCCESS: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 |  |  |                 // everything is ok | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 | 4 |  |                 break; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 | 1 |  |             case static::CODE_NOT_FOUND: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 | 1 |  |                 return new AddressCollection([]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 |  |  |             default: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 |  |  |                 throw new InvalidServerResponse(sprintf('The GeoIPs API returned unknown result code "%s" for query: "%s".', $response['code'], $url)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 161 |  |  |         // Make sure that we do have proper result array | 
            
                                                                                                            
                            
            
                                    
            
            
                | 162 | 4 |  |         if (empty($response['location']) || !is_array($response['location'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 163 |  |  |             return new AddressCollection([]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 164 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 165 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 166 |  |  |         $location = array_map(function ($value) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 167 | 4 |  |             return '' === $value ? null : $value; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 168 | 4 |  |         }, $response['location']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 169 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 170 | 4 |  |         $adminLevels = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 171 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 172 | 4 |  |         if (null !== $location['region_name'] || null !== $location['region_code']) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 173 | 2 |  |             $adminLevels[] = [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 174 | 2 |  |                 'name' => $location['region_name'], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 175 | 2 |  |                 'code' => $location['region_code'], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 176 | 2 |  |                 'level' => 1, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 177 |  |  |             ]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 178 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 179 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 180 | 4 |  |         if (null !== $location['county_name']) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 181 | 2 |  |             $adminLevels[] = [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 182 | 2 |  |                 'name' => $location['county_name'], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 183 | 2 |  |                 'level' => 2, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 184 |  |  |             ]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 185 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 186 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 187 | 4 |  |         $results = Address::createFromArray([ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 188 | 4 |  |             'providedBy' => $this->getName(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 189 | 4 |  |             'country' => $location['country_name'], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 190 | 4 |  |             'countryCode' => $location['country_code'], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 191 | 4 |  |             'adminLevels' => $adminLevels, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 192 | 4 |  |             'locality' => $location['city_name'], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 193 | 4 |  |             'latitude' => $location['latitude'], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 194 | 4 |  |             'longitude' => $location['longitude'], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 195 | 4 |  |             'timezone' => $location['timezone'], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 196 |  |  |         ]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 197 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 198 | 4 |  |         return new AddressCollection([$results]); | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 199 |  |  |     } | 
            
                                                        
            
                                    
            
            
                | 200 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 201 |  |  |  |