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