Skip to content

Commit 5bb494f

Browse files
committed
Add ArcGIS Online provider
1 parent 2090e06 commit 5bb494f

File tree

2 files changed

+453
-0
lines changed

2 files changed

+453
-0
lines changed
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
<?php
2+
3+
/**
4+
* This file is part of the Geocoder package.
5+
* For the full copyright and license information, please view the LICENSE
6+
* file that was distributed with this source code.
7+
*
8+
* @license MIT License
9+
*/
10+
11+
namespace Geocoder\Provider;
12+
13+
use Geocoder\Exception\NoResultException;
14+
use Geocoder\Exception\UnsupportedException;
15+
use Geocoder\HttpAdapter\HttpAdapterInterface;
16+
17+
/**
18+
* @author ALKOUM Dorian <baikunz@gmail.com>
19+
*/
20+
class ArcGISOnlineProvider extends AbstractProvider implements ProviderInterface
21+
{
22+
/**
23+
* @var string
24+
*/
25+
const ENDPOINT_URL = '%s://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/find?text=%s';
26+
27+
/**
28+
* @var string
29+
*/
30+
const REVERSE_ENDPOINT_URL = '%s://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode?location=%F,%F';
31+
32+
/**
33+
* @var string
34+
*/
35+
protected $sourceCountry = null;
36+
37+
/**
38+
* @var string
39+
*/
40+
protected $protocol = 'http';
41+
42+
/**
43+
* @param HttpAdapterInterface $adapter An HTTP adapter.
44+
* @param string $sourceCountry Country biasing (optional).
45+
* @param bool $useSsl Whether to use an SSL connection (optional)
46+
*/
47+
public function __construct(HttpAdapterInterface $adapter, $sourceCountry = null, $useSsl = false)
48+
{
49+
parent::__construct($adapter);
50+
51+
$this->sourceCountry = $sourceCountry;
52+
$this->protocol = $useSsl ? 'https' : 'http';
53+
}
54+
55+
/**
56+
* {@inheritDoc}
57+
*/
58+
public function getGeocodedData($address)
59+
{
60+
if (filter_var($address, FILTER_VALIDATE_IP)) {
61+
throw new UnsupportedException('The ArcGISOnlineProvider does not support IP addresses.');
62+
}
63+
64+
// Save a request if no valid address entered
65+
if (empty($address)) {
66+
throw new NoResultException('Invalid address.');
67+
}
68+
69+
$query = sprintf(
70+
static::ENDPOINT_URL,
71+
$this->protocol,
72+
urlencode($address)
73+
);
74+
75+
$json = $this->executeQuery($query);
76+
77+
// no result
78+
if (empty($json->locations)) {
79+
throw new NoResultException(sprintf('No results found for query %s', $query));
80+
}
81+
82+
$location = reset($json->locations);
83+
$data = $location->feature->attributes;
84+
85+
$coordinates = (array) $location->feature->geometry;
86+
$streetName = !empty($data->Match_addr) ? $data->Match_addr : 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+
$region = !empty($data->Region) ? $data->Region : null;
91+
$county = !empty($data->Subregion) ? $data->Subregion : null;
92+
$countryCode = !empty($data->Country) ? $data->Country : null;
93+
94+
return array_merge($this->getDefaults(), array(
95+
'latitude' => $coordinates['y'],
96+
'longitude' => $coordinates['x'],
97+
'streetNumber' => $streetNumber,
98+
'streetName' => $streetName,
99+
'city' => $city,
100+
'zipcode' => $zipcode,
101+
'region' => $region,
102+
'countryCode' => $countryCode,
103+
'county' => $county,
104+
));
105+
}
106+
107+
/**
108+
* {@inheritDoc}
109+
*/
110+
public function getReversedData(array $coordinates)
111+
{
112+
$query = sprintf(
113+
static::REVERSE_ENDPOINT_URL,
114+
$this->protocol,
115+
$coordinates[1],
116+
$coordinates[0]
117+
);
118+
119+
$json = $this->executeQuery($query);
120+
121+
if (property_exists($json, 'error')) {
122+
throw new NoResultException(sprintf('No results found for query %s', $query));
123+
}
124+
125+
$data = $json->address;
126+
127+
$streetName = !empty($data->Address) ? $data->Address : null;
128+
$city = !empty($data->City) ? $data->City : null;
129+
$zipcode = !empty($data->Postal) ? $data->Postal : null;
130+
$region = !empty($data->Region) ? $data->Region : null;
131+
$county = !empty($data->Subregion) ? $data->Subregion : null;
132+
$countryCode = !empty($data->CountryCode) ? $data->CountryCode : null;
133+
134+
return array_merge($this->getDefaults(), array(
135+
'latitude' => $coordinates[0],
136+
'longitude' => $coordinates[1],
137+
'streetName' => $streetName,
138+
'city' => $city,
139+
'zipcode' => $zipcode,
140+
'region' => $region,
141+
'countryCode' => $countryCode,
142+
'county' => $county,
143+
));
144+
}
145+
146+
/**
147+
* {@inheritDoc}
148+
*/
149+
public function getName()
150+
{
151+
return 'arcgis_online';
152+
}
153+
154+
/**
155+
* @param string $query
156+
*
157+
* @return string Query with extra params
158+
*/
159+
protected function buildQuery($query)
160+
{
161+
if (null !== $this->getSourceCountry()) {
162+
$query = sprintf('%s&sourceCountry=%s', $query, $this->getSourceCountry());
163+
}
164+
165+
$query = sprintf('%s&maxLocations=%d', $query, 1); // Limit results to 1
166+
$query = sprintf('%s&f=%s', $query, 'json'); // set format to json
167+
$query = sprintf('%s&outFields=*', $query); // Get all result fields
168+
169+
return $query;
170+
}
171+
172+
/**
173+
* Executes a query
174+
*
175+
* @param string $query
176+
*
177+
* @throws NoResultException
178+
*
179+
* @return stdClass json object representing the query result
180+
*/
181+
protected function executeQuery($query)
182+
{
183+
$query = $this->buildQuery($query);
184+
185+
$content = $this->getAdapter()->getContent($query);
186+
if (null === $content) {
187+
throw new NoResultException(sprintf('Could not execute query %s', $query));
188+
}
189+
190+
$json = json_decode($content);
191+
192+
// API error
193+
if (!isset($json)) {
194+
throw new NoResultException(sprintf('Could not execute query %s', $query));
195+
}
196+
197+
return $json;
198+
}
199+
200+
/**
201+
* Returns the configured source country or null.
202+
*
203+
* @return string|null
204+
*/
205+
protected function getSourceCountry()
206+
{
207+
return $this->sourceCountry;
208+
}
209+
}

0 commit comments

Comments
 (0)