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\TomTom;
14
15
use Geocoder\Collection;
16
use Geocoder\Exception\InvalidCredentials;
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\Http\Provider\AbstractHttpProvider;
23
use Geocoder\Provider\Provider;
24
use Psr\Http\Client\ClientInterface;
25
26
/**
27
 * @author Antoine Corcy <[email protected]>
28
 */
29
final class TomTom extends AbstractHttpProvider implements Provider
30
{
31
    /**
32
     * @var string
33
     */
34
    const GEOCODE_ENDPOINT_URL = 'https://api.tomtom.com/search/2/geocode/%s.json?key=%s&limit=%d';
35
36
    /**
37
     * @var string
38
     */
39
    const REVERSE_ENDPOINT_URL = 'https://api.tomtom.com/search/2/reverseGeocode/%F,%F.json?key=%s';
40
41
    /**
42
     * @var string
43
     */
44
    private $apiKey;
45
46
    /**
47
     * @param ClientInterface $client an HTTP adapter
48
     * @param string          $apiKey an API key
49
     */
50 26
    public function __construct(ClientInterface $client, string $apiKey)
51
    {
52 26
        if (empty($apiKey)) {
53 1
            throw new InvalidCredentials('No API key provided.');
54
        }
55
56 25
        $this->apiKey = $apiKey;
57 25
        parent::__construct($client);
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63 14
    public function geocodeQuery(GeocodeQuery $query): Collection
64
    {
65 14
        $address = $query->getText();
66
67
        // This API doesn't handle IPs
68 14
        if (filter_var($address, FILTER_VALIDATE_IP)) {
69 4
            throw new UnsupportedOperation('The TomTom provider does not support IP addresses, only street addresses.');
70
        }
71
72 10
        $url = sprintf(self::GEOCODE_ENDPOINT_URL, rawurlencode($address), $this->apiKey, $query->getLimit());
73
74 10
        if (null !== $query->getLocale()) {
75 4
            $url = sprintf('%s&language=%s', $url, $query->getLocale());
76
        }
77
78 10
        if (null !== $query->getData('countrySet')) {
79
            $url = sprintf('%s&countrySet=%s', $url, $query->getData('countrySet'));
80
        }
81
82 10
        $content = $this->getUrlContents($url);
83 4
        if (false !== stripos($content, 'Developer Inactive')) {
84
            throw new InvalidCredentials('Map API Key provided is not valid.');
85
        }
86
87 4
        $json = json_decode($content, true);
88 4
        if (!isset($json['results']) || empty($json['results'])) {
89 1
            return new AddressCollection([]);
90
        }
91
92 3
        $locations = [];
93 3
        foreach ($json['results'] as $item) {
94 3
            $locations[] = Address::createFromArray([
95 3
                'providedBy' => $this->getName(),
96 3
                'latitude' => $item['position']['lat'] ?? null,
97 3
                'longitude' => $item['position']['lon'] ?? null,
98 3
                'streetName' => $item['address']['streetName'] ?? null,
99 3
                'streetNumber' => $item['address']['streetNumber'] ?? null,
100 3
                'locality' => $item['address']['municipality'] ?? null,
101 3
                'subLocality' => $item['address']['municipalitySubdivision'] ?? null,
102 3
                'postalCode' => $item['address']['postalCode'] ?? null,
103 3
                'country' => $item['address']['country'] ?? null,
104 3
                'countryCode' => $item['address']['countryCode'] ?? null,
105
            ]);
106
        }
107
108 3
        return new AddressCollection($locations);
109
    }
110
111
    /**
112
     * {@inheritdoc}
113
     */
114 10
    public function reverseQuery(ReverseQuery $query): Collection
115
    {
116 10
        $coordinates = $query->getCoordinates();
117 10
        $longitude = $coordinates->getLongitude();
118 10
        $latitude = $coordinates->getLatitude();
119
120 10
        $url = sprintf(self::REVERSE_ENDPOINT_URL, $latitude, $longitude, $this->apiKey);
121
122 10
        $content = $this->getUrlContents($url);
123 4
        if (false !== stripos($content, 'Developer Inactive')) {
124
            throw new InvalidCredentials('Map API Key provided is not valid.');
125
        }
126
127 4
        $json = json_decode($content, true);
128
129 4
        if (!isset($json['addresses']) || [] === $json['addresses']) {
130 1
            return new AddressCollection([]);
131
        }
132
133 3
        $results = $json['addresses'];
134
135 3
        $locations = [];
136 3
        foreach ($results as $item) {
137 3
            list($lat, $lon) = explode(',', $item['position']);
138 3
            $locations[] = Address::createFromArray([
139 3
                'providedBy' => $this->getName(),
140
                'latitude' => $lat,
141
                'longitude' => $lon,
142 3
                'streetName' => $item['address']['streetName'] ?? null,
143 3
                'streetNumber' => $item['address']['streetNumber'] ?? null,
144 3
                'locality' => $item['address']['municipality'] ?? null,
145 3
                'subLocality' => $item['address']['municipalitySubdivision'] ?? null,
146 3
                'postalCode' => $item['address']['postalCode'] ?? null,
147 3
                'country' => $item['address']['country'] ?? null,
148 3
                'countryCode' => $item['address']['countryCode'] ?? null,
149
            ]);
150
        }
151
152 3
        return new AddressCollection($locations);
153
    }
154
155
    /**
156
     * {@inheritdoc}
157
     */
158 7
    public function getName(): string
159
    {
160 7
        return 'tomtom';
161
    }
162
}
163