Passed
Pull Request — master (#11)
by
unknown
01:59
created

Nominatim::newLookup()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 0
cts 0
cp 0
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * This file is part of PHP Nominatim.
7
 * (c) Maxime Hélias <[email protected]>
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace maxh\Nominatim;
13
14
use GuzzleHttp\Client;
15
use GuzzleHttp\Psr7\Request;
16
use maxh\Nominatim\Exceptions\NominatimException;
17
use Psr\Http\Message\ResponseInterface;
18
19
/**
20
 *  Wrapper to manage exchanges with OSM Nominatim API.
21
 *
22
 * @see http://wiki.openstreetmap.org/wiki/Nominatim
23
 */
24
class Nominatim
25
{
26
    /**
27
     * Contain url of the current application.
28
     *
29
     * @var string
30
     */
31
    private $application_url;
32
33
    /**
34
     * Contain default request headers.
35
     *
36
     * @var array
37
     */
38
    private $defaultHeaders;
39
40
    /**
41
     * Contain http client connection.
42
     *
43
     * @var \GuzzleHttp\Client
44
     */
45
    private $http_client;
46
47
    /**
48
     * The search object which serves as a template for new ones created
49
     * by 'newSearch()' method.
50
     *
51
     * @var \maxh\Nominatim\Search
52
     */
53
    private $baseSearch;
54
55
    /**
56
     * Template for new ones created by 'newReverser()' method.
57
     *
58
     * @var \maxh\Nominatim\Reverse
59
     */
60
    private $baseReverse;
61
62 5
    /**
63
     * Template for new ones created by 'newLookup()' method.
64
     *
65 1
     * @var \maxh\Nominatim\Lookup
66
     */
67 5
    private $baseLookup;
68
69
    /**
70
     * Template for new ones created by 'newDetails()' method.
71 5
     *
72 5
     * @var \maxh\Nominatim\Lookup
73 5
     */
74 5
    private $baseDetails;
75 5
76 5
    /**
77 5
     * Constructor.
78
     *
79
     * @param string                  $application_url Contain url of the current application
80
     * @param \GuzzleHttp\Client|null $http_client     Client object from Guzzle
81
     * @param array                   $defaultHeaders  Define default header for all request
82
     *
83
     * @throws NominatimException
84
     */
85
    public function __construct(
86
        string $application_url,
87
        array $defaultHeaders = [],
88
        Client $http_client = null
89 5
    ) {
90 5
        if (empty($application_url)) {
91
            throw new NominatimException('Application url parameter is empty');
92
        }
93 5
94 5
        if (null === $http_client) {
95 5
            $http_client = new Client([
96 5
                'base_uri'           => $application_url,
97
                'timeout'            => 30,
98
                'connection_timeout' => 5,
99
            ]);
100
        } elseif ($http_client instanceof Client) {
101
            $application_url_client = $http_client->getConfig('base_uri');
102
103 3
            if (empty($application_url_client)) {
104
                throw new NominatimException('http_client must have a configured base_uri.');
105 3
            }
106
107
            if ($application_url_client !== $application_url) {
108
                throw new NominatimException('http_client parameter hasn\'t the same url application.');
109
            }
110
        } else {
111
            throw new NominatimException('http_client parameter must be a \\GuzzleHttp\\Client object or empty');
112
        }
113 2
114
        $this->application_url = $application_url;
115 2
        $this->defaultHeaders = $defaultHeaders;
116
        $this->http_client = $http_client;
117
118
        //Create base
119
        $this->baseSearch = new Search();
120
        $this->baseReverse = new Reverse();
121
        $this->baseLookup = new Lookup();
122
        $this->baseDetails = new Details();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \maxh\Nominatim\Details() of type object<maxh\Nominatim\Details> is incompatible with the declared type object<maxh\Nominatim\Lookup> of property $baseDetails.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
123 2
    }
124
125 2
    /**
126
     * Returns a new search object based on the base search.
127
     *
128
     * @return \maxh\Nominatim\Search
129
     */
130
    public function newSearch(): Search
131
    {
132
        return clone $this->baseSearch;
133
    }
134
135
    /**
136
     * Returns a new reverse object based on the base reverse.
137
     *
138
     * @return \maxh\Nominatim\Reverse
139
     */
140
    public function newReverse(): Reverse
141
    {
142
        return clone $this->baseReverse;
143
    }
144
145
    /**
146
     * Returns a new lookup object based on the base lookup.
147
     *
148
     * @return \maxh\Nominatim\Lookup
149
     */
150
    public function newLookup(): Lookup
151
    {
152
        return clone $this->baseLookup;
153
    }
154
155
    /**
156
     * Returns a new datails object based on the base details.
157
     *
158
     * @return \maxh\Nominatim\Details
159
     */
160
    public function newDetails(): Details
161
    {
162
        return clone $this->baseDetails;
163
    }
164
165
    /**
166
     * Decode the data returned from the request.
167
     *
168
     * @param string            $format   json or xml
169
     * @param Request           $request  Request object from Guzzle
170
     * @param ResponseInterface $response Interface response object from Guzzle
171
     *
172
     * @throws \RuntimeException
173
     * @throws \maxh\Nominatim\Exceptions\NominatimException if no format for decode
174
     *
175
     * @return array|\SimpleXMLElement
176
     */
177
    private function decodeResponse(string $format, Request $request, ResponseInterface $response)
178
    {
179
        if ('json' === $format || 'jsonv2' === $format || 'geojson' === $format || 'geocodejson' === $format) {
180 1
            return \json_decode($response->getBody()->getContents(), true);
181
        }
182 1
183
        if ('xml' === $format) {
184
            return new \SimpleXMLElement($response->getBody()->getContents());
185
        }
186
187
        throw new NominatimException('Format is undefined or not supported for decode response', $request, $response);
188
    }
189
190
    /**
191
     * Runs the query and returns the result set from Nominatim.
192
     *
193
     * @param QueryInterface $nRequest The object request to send
194
     * @param array          $headers  Override the request header
195
     *
196
     * @throws NominatimException                    if no format for decode
197
     * @throws \GuzzleHttp\Exception\GuzzleException
198
     *
199
     * @return array|\SimpleXMLElement The decoded data returned from Nominatim
200
     */
201
    public function find(QueryInterface $nRequest, array $headers = [])
202
    {
203
        $url = $this->application_url . '/' . $nRequest->getPath() . '?';
204
        $request = new Request('GET', $url, \array_merge($this->defaultHeaders, $headers));
205
206
        //Convert the query array to string with space replace to +
207
        $query = \GuzzleHttp\Psr7\build_query($nRequest->getQuery(), PHP_QUERY_RFC1738);
208
209
        $url = $request->getUri()->withQuery($query);
210
        $request = $request->withUri($url);
211
212
        return $this->decodeResponse(
213
            $nRequest->getFormat(),
214
            $request,
215
            $this->http_client->send($request)
216
        );
217
    }
218
219
    /**
220
     * Return the client using by instance.
221
     */
222
    public function getClient(): Client
223
    {
224
        return $this->http_client;
225
    }
226
}
227