GeocodeXyz::query()   B
last analyzed

Complexity

Conditions 7
Paths 14

Size

Total Lines 76
Code Lines 50

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 50
nc 14
nop 2
dl 0
loc 76
rs 8.1575
c 1
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace LeKoala\GeoTools\Services;
4
5
use Exception;
6
use LeKoala\GeoTools\Models\Address;
7
use LeKoala\GeoTools\Models\Country;
8
use LeKoala\GeoTools\Models\Coordinates;
9
10
/**
11
 * @link https://geocode.xyz
12
 */
13
class GeocodeXyz implements Geocoder, Geolocator
14
{
15
    const API_URL = 'https://geocode.xyz/';
16
17
    /**
18
     * @link https://geocode.xyz/api
19
     * @param ?string $query
20
     * @param array<int|string,mixed> $params region, citybias
21
     * @return Address
22
     * @throws Exception when there is a problem with the api, otherwise may return an empty address
23
     */
24
    protected function query($query, $params = [])
25
    {
26
        $url = self::API_URL;
27
28
        $defaultParams = [
29
            'locate' => $query,
30
            'json' => 1
31
        ];
32
        $params = array_merge($defaultParams, $params);
33
34
        $url .= '?' . http_build_query($params);
35
36
        $headers = [
37
            "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
38
            "accept-encoding: gzip, deflate, br",
39
            "accept-language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7,nb;q=0.6",
40
            "cache-control: max-age=0",
41
            "user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36",
42
        ];
43
        $opts = array('http' =>
44
        array(
45
            'method' => 'POST',
46
            'header' => implode("\r\n", $headers),
47
        ));
48
49
        $context = stream_context_create($opts, $opts);
50
        $result = file_get_contents($url, false, $context);
51
        if (!$result) {
52
            throw new Exception("The api returned no result");
53
        }
54
55
        $data = json_decode($result, true);
56
57
        if (!$data) {
58
            throw new Exception("Failed to decode api results");
59
        }
60
61
        $location = [];
62
        $countryCode = $countryName = null;
63
        $lat = $lon = null;
64
65
        // normalize
66
        if (isset($data['standard'])) {
67
            $location = [
68
                'streetName' => $data['standard']['addresst'] ?? null,
69
                'streetNumber' => $data['standard']['stno'] ?? null,
70
                'postalCode' => $data['standard']['postal'] ?? null,
71
                'locality' => $data['standard']['city'] ?? null,
72
            ];
73
            $countryCode = $data['standard']['prov'] ?? null;
74
            $countryName = $data['standard']['countryname'] ?? null;
75
        } elseif (isset($data['staddress'])) {
76
            $location = [
77
                'streetName' => $data['staddress'] ?? null,
78
                'streetNumber' => $data['stnumber'] ?? null,
79
                'postalCode' => $data['postal'] ?? null,
80
                'locality' => $data['city'] ?? null,
81
            ];
82
            $countryCode = $data['prov'] ?? null;
83
            $countryName = $data['country'] ?? null;
84
        }
85
86
        // Make sure we have a string
87
        if (empty($location['postalCode'])) {
88
            $location['postalCode'] = '';
89
        }
90
91
        if (!empty($data['latt'])) {
92
            $lat = $data['latt'];
93
            $lon = $data['longt'];
94
        }
95
96
        $country = new Country($countryCode, $countryName);
97
        $coordinates = new Coordinates($lat, $lon);
98
99
        return new Address($location, $country, $coordinates);
100
    }
101
102
    /**
103
     * @return array<string>
104
     */
105
    public static function listRegions()
106
    {
107
        return explode(', ', 'AF, AX, AL, DZ, AS, AD, AO, AI, AQ, AG, AR, AM, AW, AU, AT, AZ, BS, BH, BD, BB, BY, BE, BZ, BJ, BM, BT, BO, BQ, BA, BW, BR, IO, VG, BN, BG, BF, BI, KH, CM, CA, CV, KY, CF, TD, CL, CN, CX, CC, CO, KM, CG, CK, CR, HR, CU, CW, CY, CZ, CI, DK, DJ, DM, DO, EC, EG, SV, GQ, ER, EE, ET, FK, FO, FJ, FI, FR, GF, PF, TF, GA, GM, GE, DE, GH, GI, GR, GL, GD, GP, GU, GT, GG, GN, GW, GY, HT, HN, HK, HU, IS, IN, ID, IR, IQ, IE, IM, IL, IT, JM, JP, JE, JO, KZ, KE, KI, KS, KW, KG, LA, LV, LB, LS, LR, LY, LI, LT, LU, MO, MK, MG, MW, MY, MV, ML, MT, MH, MQ, MR, MU, YT, MX, FM, MD, MC, MN, ME, MS, MA, MZ, MM, NA, NR, NP, NL, AN, NC, NZ, NI, NE, NG, NU, NF, KP, MP, NO, OM, PK, PW, PS, PA, PG, PY, PE, PH, PN, PL, PT, PR, QA, RO, RU, RW, RE, GS, SH, KN, LC, PM, VC, BL, SX, MF, WS, SM, ST, SA, SN, RS, SC, SL, SG, SK, SI, SB, SO, ZA, KR, SS, ES, LK, SD, SR, SJ, SZ, SE, CH, SY, TW, TJ, TZ, TH, TL, TG, TK, TO, TT, TN, TR, TM, TC, TV, UM, UG, UA, AE, UK, US, UY, UZ, VU, VA, VE, VN, VI, WF, EH, YE, CD, ZM, ZW');
108
    }
109
110
    /**
111
     * @inheritDoc
112
     */
113
    public function reverseGeocode($lat, $lon, $params = [])
114
    {
115
        return $this->query("$lat,$lon", $params);
116
    }
117
118
    /**
119
     * @inheritDoc
120
     */
121
    public function geocode($address, $params = [])
122
    {
123
        return $this->query($address, $params);
124
    }
125
126
    /**
127
     * @inheritDoc
128
     */
129
    public function geolocate($ip, $params = [])
130
    {
131
        return $this->query($ip, $params);
132
    }
133
}
134