Code

< 40 %
40-60 %
> 60 %
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\FreeGeoIp;
14
15
use Geocoder\Collection;
16
use Geocoder\Exception\UnsupportedOperation;
17
use Geocoder\Http\Provider\AbstractHttpProvider;
18
use Geocoder\Model\AddressBuilder;
19
use Geocoder\Model\AddressCollection;
20
use Geocoder\Provider\Provider;
21
use Geocoder\Query\GeocodeQuery;
22
use Geocoder\Query\ReverseQuery;
23
use Psr\Http\Client\ClientInterface;
24
use Psr\Http\Message\RequestInterface;
25
26
/**
27
 * @author William Durand <[email protected]>
28
 */
29
final class FreeGeoIp extends AbstractHttpProvider implements Provider
30
{
31
    /**
32
     * @var string|null
33
     */
34
    private $baseUrl;
35
36 27
    public function __construct(ClientInterface $client, string $baseUrl = 'https://freegeoip.app/json/%s')
37
    {
38 27
        parent::__construct($client);
39
40 27
        $this->baseUrl = $baseUrl;
41
    }
42
43 25
    public function geocodeQuery(GeocodeQuery $query): Collection
44
    {
45 25
        $address = $query->getText();
46
47 25
        if (!filter_var($address, FILTER_VALIDATE_IP)) {
48 1
            throw new UnsupportedOperation('The FreeGeoIp provider does not support street addresses.');
49
        }
50
51 24
        if (in_array($address, ['127.0.0.1', '::1'])) {
52 2
            return new AddressCollection([$this->getLocationForLocalhost()]);
53
        }
54
55 22
        $request = $this->getRequest(sprintf($this->baseUrl, $address));
56
57 22
        if (null !== $query->getLocale()) {
58
            /** @var RequestInterface $request */
59 5
            $request = $request->withHeader('Accept-Language', $query->getLocale());
60
        }
61
62 22
        $body = $this->getParsedResponse($request);
63 11
        $data = json_decode($body, true);
64
65
        // Return empty collection if address was not found
66 11
        if ('' === $data['region_name']
67 11
        && '' === $data['region_code']
68 11
        && 0 === $data['latitude']
69 11
        && 0 === $data['longitude']
70 11
        && '' === $data['city']
71 11
        && '' === $data['zip_code']
72 11
        && '' === $data['country_name']
73 11
        && '' === $data['country_code']
74 11
        && '' === $data['time_zone']) {
75 1
            return new AddressCollection([]);
76
        }
77
78 10
        $builder = new AddressBuilder($this->getName());
79
80 10
        if (!empty($data['region_name'])) {
81 7
            $builder->addAdminLevel(1, $data['region_name'], $data['region_code'] ?? null);
82
        }
83
84 10
        if (0 !== $data['latitude'] || 0 !== $data['longitude']) {
85 10
            $builder->setCoordinates($data['latitude'] ?? null, $data['longitude'] ?? null);
86
        }
87 10
        $builder->setLocality(empty($data['city']) ? null : $data['city']);
88 10
        $builder->setPostalCode(empty($data['zip_code']) ? null : $data['zip_code']);
89 10
        $builder->setCountry(empty($data['country_name']) ? null : $data['country_name']);
90 10
        $builder->setCountryCode(empty($data['country_code']) ? null : $data['country_code']);
91 10
        $builder->setTimezone(empty($data['time_zone']) ? null : $data['time_zone']);
92
93 10
        return new AddressCollection([$builder->build()]);
94
    }
95
96 1
    public function reverseQuery(ReverseQuery $query): Collection
97
    {
98 1
        throw new UnsupportedOperation('The FreeGeoIp provider is not able to do reverse geocoding.');
99
    }
100
101 13
    public function getName(): string
102
    {
103 13
        return 'free_geo_ip';
104
    }
105
}
106