Completed
Pull Request — master (#26)
by Damian
03:01 queued 13s
created

PostcodeService::bulkReverseGeocoding()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 4
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 6
ccs 1
cts 1
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace JustSteveKing\LaravelPostcodes\Service;
6
7
use GuzzleHttp\Client;
8
use Illuminate\Support\Collection;
9
use function GuzzleHttp\Psr7\build_query;
10
use GuzzleHttp\Exception\GuzzleException;
11
use JustSteveKing\LaravelPostcodes\Service\BulkReverseGeocoding\Geolocation;
12
13
class PostcodeService
14
{
15
    /**
16
     * @var string
17
     */
18
    protected $url;
19
20
    /**
21
     * @var Client
22
     */
23
    protected $http;
24
25
    /**
26
     * Postcode Service constructor.
27
     *
28
     * @param Client $client
29
     *
30 60
     * @return void
31
     */
32 60
    public function __construct(Client $client)
33
    {
34 60
        $this->url = config('services.postcodes.url');
35 60
36
        $this->http = $client;
37
    }
38
39
    /**
40
     * Validate a postcode against the API
41
     *
42
     * @param string $postcode
43
     *
44 9
     * @return bool
45
     */
46 9
    public function validate(string $postcode): bool
47
    {
48
        return $this->getResponse("postcodes/$postcode/validate");
49
    }
50
51
    /**
52
     * Get the address details from a postcode
53
     *
54
     * @param string $postcode
55
     *
56 3
     * @return object
57
     */
58 3
    public function getPostcode(string $postcode): object
59
    {
60
        return $this->getResponse("postcodes/$postcode");
61
    }
62
63
    /**
64
     * Get the address details from a multiple postcodes at once
65
     *
66
     * @param array $postcodes
67
     *
68
     * @param array $filter - optional array of fields to return
69
     * @return Collection
70
     *
71 3
     * @throws \GuzzleHttp\Exception\GuzzleException
72
     */
73 3
    public function getPostcodes(array $postcodes, array $filter = []): Collection
74 3
    {
75
        if (!empty($filter)) {
76
            $filter = build_query(['filter' => implode(',', $filter)]);
77 3
        }
78 3
79 3
        return collect($this->getResponse(
80 3
            'postcodes?' . $filter,
81
            'POST',
82 3
            ['postcodes' => array_values($postcodes)]
83 3
        ))->map(function ($item) {
84
            return $item->result;
85
        });
86
    }
87
88
    /**
89
     * Get information based on outward code including geo data
90
     *
91
     * @param string $outwardcode
92
     *
93 3
     * @return object
94
     */
95 3
    public function getOutwardCode(string $outwardcode): object
96
    {
97
        return $this->getResponse("outcodes/$outwardcode");
98
    }
99
100
    /**
101
     * Get the address details from a random postcode
102
     *
103 3
     * @return object
104
     */
105 3
    public function getRandomPostcode()
106
    {
107
        return $this->getResponse("random/postcodes");
108
    }
109
110
    /**
111
     * Query the API for a given string
112
     *
113
     * @param string $query
114
     *
115
     * @return Collection
116
     *
117 3
     * @throws \GuzzleHttp\Exception\GuzzleException
118
     */
119 3
    public function query(string $query): Collection
120
    {
121 3
        $queryString = http_build_query(['q' => $query]);
122
123
        return collect($this->getResponse("postcodes?$queryString"));
124
    }
125
126
    /**
127
     * Get data for the postcodes nearest to the passed postcode
128
     *
129
     * @param string $postcode
130
     *
131
     * @return Collection
132
     *
133 3
     * @throws \GuzzleHttp\Exception\GuzzleException
134
     */
135 3
    public function nearest(string $postcode): Collection
136
    {
137
        return collect($this->getResponse("postcodes/$postcode/nearest"));
138
    }
139
140
    /**
141
     * Lookup a terminated postcode. Returns the postcode, year and month of termination.
142
     *
143
     * @param string $postcode
144
     *
145 3
     * @return object
146
     */
147 3
    public function getTerminatedPostcode($postcode)
148
    {
149
        return $this->getResponse("terminated_postcodes/$postcode");
150
    }
151
152
    /**
153
     * Autocomplete a postcode partial.
154
     *
155
     * @param string $partialPostcode
156
     *
157
     * @return Collection
158
     *
159 6
     * @throws \GuzzleHttp\Exception\GuzzleException
160
     */
161 6
    public function autocomplete(string $partialPostcode): Collection
162
    {
163
        return collect($this->getResponse("postcodes/$partialPostcode/autocomplete"));
164
    }
165
166
    /**
167
     * Get nearest outward codes for a given longitude & latitude
168
     *
169
     * @param float $longitude
170
     *
171
     * @param float $latitude
172
     * @return Collection
173
     *
174 6
     * @throws \GuzzleHttp\Exception\GuzzleException
175
     */
176 6
    public function nearestOutwardCodesForGivenLngAndLat(float $longitude, float $latitude): Collection
177 6
    {
178 4
        return collect($this->getResponse(sprintf(
179 4
            'outcodes?lon=%s&lat=%s',
180
            $longitude,
181
            $latitude
182
        )));
183
    }
184
185
    /**
186
     * Get information about nearest outcodes based on outward code
187
     *
188
     * @param string $outwardcode
189
     *
190
     * @param int $limit Needs to be less than 100
191
     * @param int $radius Needs to be less than 25,000m
192
     * @return Collection
193
     *
194 3
     * @throws \GuzzleHttp\Exception\GuzzleException
195
     */
196
    public function getNearestOutwardCode(
197
        string $outwardcode,
198
        int $limit = 10,
199 3
        int $radius = 5000
200 3
    ): Collection {
201
        $limit = ($limit > 100) ? 100 : $limit;
202 3
        $radius = ($radius > 100) ? 25000 : $radius;
203 3
204
        return collect($this->getResponse(
205
            "outcodes/$outwardcode/nearest?limit=$limit&radius=$radius"
206
        ));
207
    }
208
209
    /**
210
     * Get nearest postcodes for a given longitude & latitude
211
     *
212
     * @param float $longitude
213
     * @param float $latitude
214
     *
215
     * @return Collection
216
     *
217 6
     * @throws \GuzzleHttp\Exception\GuzzleException
218
     */
219 6
    public function nearestPostcodesForGivenLngAndLat(float $longitude, float $latitude): Collection
220 6
    {
221 4
        return collect($this->getResponse(sprintf(
222 4
            'postcodes?lon=%s&lat=%s',
223
            $longitude,
224
            $latitude
225
        )));
226
    }
227
228
    /**
229
     * @param Geolocation[] $geolocations
230
     *
231
     * @return array|null
232
     * @throws GuzzleException
233
     */
234
    public function bulkReverseGeocoding(array $geolocations): ?array
235
    {
236 51
        $body = json_encode(array_map(function (Geolocation $geolocation) {
237
            return $geolocation->toArray();
238
        }, $geolocations));
239
        return $this->getResponse('postcodes', 'POST', [], ['body' => $body]);
240
    }
241
242 51
    /**
243
     * Get the response and return the result object
244 51
     *
245 3
     * @param string|null $uri
246
     * @param string $method
247
     * @param array $data - data to be sent in post/patch/put request
248 51
     * @param array $options - array of options to be passed to curl, if $data is passed 'json' will be overwritten
249 51
     * @return mixed
250 34
     * @throws \GuzzleHttp\Exception\GuzzleException
251 34
     */
252
    protected function getResponse(
253
        string $uri = null,
254 51
        string $method = 'GET',
255
        array $data = [],
256
        array $options = []
257
    ) {
258
        $url = $this->url . $uri;
259
260
        if (!empty($data)) {
261
            $options['json'] = $data;
262
        }
263
264
        $request = $this->http->request(
265
            $method,
266
            $url,
267
            $options
268
        );
269
270
        return json_decode($request->getBody()->getContents())->result;
271
    }
272
}
273