GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

ArcGISOnline::reverseQuery()   C
last analyzed

Complexity

Conditions 8
Paths 65

Size

Total Lines 36
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 36
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 26
nc 65
nop 1
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\ArcGISOnline;
14
15
use Geocoder\Collection;
16
use Geocoder\Exception\InvalidArgument;
17
use Geocoder\Exception\InvalidServerResponse;
18
use Geocoder\Exception\UnsupportedOperation;
19
use Geocoder\Model\Address;
20
use Geocoder\Model\AddressCollection;
21
use Geocoder\Query\GeocodeQuery;
22
use Geocoder\Query\ReverseQuery;
23
use Geocoder\Http\Provider\AbstractHttpProvider;
24
use Geocoder\Provider\Provider;
25
use Http\Client\HttpClient;
26
27
/**
28
 * @author ALKOUM Dorian <[email protected]>
29
 */
30
final class ArcGISOnline extends AbstractHttpProvider implements Provider
31
{
32
    /**
33
     * @var string
34
     */
35
    const ENDPOINT_URL = 'https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/find?text=%s';
36
37
    /**
38
     * @var string
39
     */
40
    const REVERSE_ENDPOINT_URL = 'https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode?location=%F,%F';
41
42
    /**
43
     * @var string
44
     */
45
    private $sourceCountry;
46
47
    /**
48
     * @param HttpClient $client        An HTTP adapter
49
     * @param string     $sourceCountry Country biasing (optional)
0 ignored issues
show
Documentation introduced by
Should the type for parameter $sourceCountry not be null|string?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
50
     */
51
    public function __construct(HttpClient $client, string $sourceCountry = null)
52
    {
53
        parent::__construct($client);
54
55
        $this->sourceCountry = $sourceCountry;
56
    }
57
58
    /**
59
     * {@inheritdoc}
60
     */
61
    public function geocodeQuery(GeocodeQuery $query): Collection
62
    {
63
        $address = $query->getText();
64
        if (filter_var($address, FILTER_VALIDATE_IP)) {
65
            throw new UnsupportedOperation('The ArcGISOnline provider does not support IP addresses, only street addresses.');
66
        }
67
68
        // Save a request if no valid address entered
69
        if (empty($address)) {
70
            throw new InvalidArgument('Address cannot be empty.');
71
        }
72
73
        $url = sprintf(self::ENDPOINT_URL, urlencode($address));
74
        $json = $this->executeQuery($url, $query->getLimit());
75
76
        // no result
77
        if (empty($json->locations)) {
78
            return new AddressCollection([]);
79
        }
80
81
        $results = [];
82
        foreach ($json->locations as $location) {
83
            $data = $location->feature->attributes;
84
85
            $coordinates = (array) $location->feature->geometry;
86
            $streetName = !empty($data->StAddr) ? $data->StAddr : null;
87
            $streetNumber = !empty($data->AddNum) ? $data->AddNum : null;
88
            $city = !empty($data->City) ? $data->City : null;
89
            $zipcode = !empty($data->Postal) ? $data->Postal : null;
90
            $countryCode = !empty($data->Country) ? $data->Country : null;
91
92
            $adminLevels = [];
93
            foreach (['Region', 'Subregion'] as $i => $property) {
94
                if (!empty($data->{$property})) {
95
                    $adminLevels[] = ['name' => $data->{$property}, 'level' => $i + 1];
96
                }
97
            }
98
99
            $results[] = Address::createFromArray([
100
                'providedBy' => $this->getName(),
101
                'latitude' => $coordinates['y'],
102
                'longitude' => $coordinates['x'],
103
                'streetNumber' => $streetNumber,
104
                'streetName' => $streetName,
105
                'locality' => $city,
106
                'postalCode' => $zipcode,
107
                'adminLevels' => $adminLevels,
108
                'countryCode' => $countryCode,
109
            ]);
110
        }
111
112
        return new AddressCollection($results);
113
    }
114
115
    /**
116
     * {@inheritdoc}
117
     */
118
    public function reverseQuery(ReverseQuery $query): Collection
119
    {
120
        $coordinates = $query->getCoordinates();
121
        $longitude = $coordinates->getLongitude();
122
        $latitude = $coordinates->getLatitude();
123
124
        $url = sprintf(self::REVERSE_ENDPOINT_URL, $longitude, $latitude);
125
        $json = $this->executeQuery($url, $query->getLimit());
126
127
        if (property_exists($json, 'error')) {
128
            return new AddressCollection([]);
129
        }
130
131
        $data = $json->address;
132
133
        $streetName = !empty($data->Address) ? $data->Address : null;
134
        $city = !empty($data->City) ? $data->City : null;
135
        $zipcode = !empty($data->Postal) ? $data->Postal : null;
136
        $region = !empty($data->Region) ? $data->Region : null;
137
        $county = !empty($data->Subregion) ? $data->Subregion : null;
138
        $countryCode = !empty($data->CountryCode) ? $data->CountryCode : null;
139
140
        return new AddressCollection([
141
            Address::createFromArray([
142
                'providedBy' => $this->getName(),
143
                'latitude' => $latitude,
144
                'longitude' => $longitude,
145
                'streetName' => $streetName,
146
                'locality' => $city,
147
                'postalCode' => $zipcode,
148
                'region' => $region,
149
                'countryCode' => $countryCode,
150
                'county' => $county,
151
            ]),
152
        ]);
153
    }
154
155
    /**
156
     * {@inheritdoc}
157
     */
158
    public function getName(): string
159
    {
160
        return 'arcgis_online';
161
    }
162
163
    /**
164
     * @param string $query
165
     * @param int    $limit
166
     *
167
     * @return string
168
     */
169
    private function buildQuery(string $query, int $limit): string
170
    {
171
        if (null !== $this->sourceCountry) {
172
            $query = sprintf('%s&sourceCountry=%s', $query, $this->sourceCountry);
173
        }
174
175
        return sprintf('%s&maxLocations=%d&f=%s&outFields=*', $query, $limit, 'json');
176
    }
177
178
    /**
179
     * @param string $url
180
     * @param int    $limit
181
     *
182
     * @return \stdClass
183
     */
184
    private function executeQuery(string $url, int $limit): \stdClass
185
    {
186
        $url = $this->buildQuery($url, $limit);
187
        $content = $this->getUrlContents($url);
188
        $json = json_decode($content);
189
190
        // API error
191
        if (!isset($json)) {
192
            throw InvalidServerResponse::create($url);
193
        }
194
195
        return $json;
196
    }
197
}
198