Completed
Push — master ( 7f5504...29257e )
by Tobias
03:07
created

TomTom::reverseQuery()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 39

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 25
CRAP Score 5.0014

Importance

Changes 0
Metric Value
dl 0
loc 39
ccs 25
cts 26
cp 0.9615
rs 8.9848
c 0
b 0
f 0
cc 5
nc 4
nop 1
crap 5.0014
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 Http\Client\HttpClient;
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 HttpClient $client an HTTP adapter
48
     * @param string     $apiKey an API key
49
     */
50 26
    public function __construct(HttpClient $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 25
    }
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']) || 0 === count($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 3
                'latitude' => $lat,
141 3
                '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
                'country' => $item['address']['country'] ?? null,
147 3
                'countryCode' => $item['address']['countryCode'] ?? null,
148
            ]);
149
        }
150
151 3
        return new AddressCollection($locations);
152
    }
153
154
    /**
155
     * {@inheritdoc}
156
     */
157 7
    public function getName(): string
158
    {
159 7
        return 'tomtom';
160
    }
161
}
162