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\Geoip;
14
15
use Geocoder\Collection;
16
use Geocoder\Exception\ExtensionNotLoaded;
17
use Geocoder\Exception\UnsupportedOperation;
18
use Geocoder\Model\Address;
19
use Geocoder\Model\AddressCollection;
20
use Geocoder\Query\GeocodeQuery;
21
use Geocoder\Query\ReverseQuery;
22
use Geocoder\Provider\AbstractProvider;
23
use Geocoder\Provider\Provider;
24
25
/**
26
 * @author William Durand <[email protected]>
27
 *
28
 * @see http://php.net/manual/ref.geoip.php
29
 */
30
final class Geoip extends AbstractProvider implements Provider
31
{
32 7
    public function __construct()
33
    {
34 7
        if (!function_exists('geoip_record_by_name')) {
35
            throw new ExtensionNotLoaded('You must install the GeoIP extension, see: https://php.net/manual/book.geoip.php.');
36
        }
37
    }
38
39
    /**
40
     * {@inheritdoc}
41
     */
42 5
    public function geocodeQuery(GeocodeQuery $query): Collection
43
    {
44 5
        $address = $query->getText();
45
46 5
        if (!filter_var($address, FILTER_VALIDATE_IP)) {
47 1
            throw new UnsupportedOperation('The Geoip provider does not support street addresses, only IPv4 addresses.');
48
        }
49
50
        // This API does not support IPv6
51 4
        if (filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
52 2
            throw new UnsupportedOperation('The Geoip provider does not support IPv6 addresses, only IPv4 addresses.');
53
        }
54
55 2
        if ('127.0.0.1' === $address) {
56 1
            return new AddressCollection([$this->getLocationForLocalhost()]);
57
        }
58
59 1
        $results = @geoip_record_by_name($address);
60
61 1
        if (!is_array($results)) {
62 1
            return new AddressCollection([]);
63
        }
64
65
        if (!empty($results['region']) && !empty($results['country_code'])) {
66
            $timezone = @geoip_time_zone_by_country_and_region($results['country_code'], $results['region']) ?: null;
67
            $region = @geoip_region_name_by_code($results['country_code'], $results['region']) ?: $results['region'];
68
        } else {
69
            $timezone = null;
70
            $region = $results['region'];
71
        }
72
73
        return new AddressCollection([
74
            Address::createFromArray([
75
                'providedBy' => $this->getName(),
76
                'latitude' => $results['latitude'],
77
                'longitude' => $results['longitude'],
78
                'locality' => $results['city'],
79
                'postalCode' => $results['postal_code'],
80
                'adminLevels' => $results['region'] ? [['name' => $region, 'code' => $results['region'], 'level' => 1]] : [],
81
                'country' => $results['country_name'],
82
                'countryCode' => $results['country_code'],
83
                'timezone' => $timezone,
84
            ]),
85
        ]);
86
    }
87
88
    /**
89
     * {@inheritdoc}
90
     */
91 1
    public function reverseQuery(ReverseQuery $query): Collection
92
    {
93 1
        throw new UnsupportedOperation('The Geoip provider is not able to do reverse geocoding.');
94
    }
95
96
    /**
97
     * {@inheritdoc}
98
     */
99 2
    public function getName(): string
100
    {
101 2
        return 'geoip';
102
    }
103
}
104