Skip to content

Commit 49afa04

Browse files
committed
Refactor providers (part 1)
This PR is based on @MattKetmo's work. His initial idea was a sort of eye-opener to me, hence this PR. I removed useless methods in the AbstractProvider. I believe we could have a AbstractLocaleAwareProvider too. The LocaleAwareProvider interface does not make much sense at this point, I'd drop it. The ProviderBasedGeocoder should be an aggregator or proxy. The codebase is getting more and more readable and clean. Edit: I chose to keep the LocaleAwareProvider interface as it is a pretty common use case.
1 parent 045c412 commit 49afa04

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1220
-1311
lines changed

src/Geocoder/Dumper/Gpx.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
namespace Geocoder\Dumper;
1212

13-
use Geocoder\ProviderBasedGeocoder;
13+
use Geocoder\Geocoder;
1414
use Geocoder\Model\Address;
1515

1616
/**
@@ -35,7 +35,7 @@ public function dump(Address $address)
3535
xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
3636
3737
GPX
38-
, ProviderBasedGeocoder::VERSION);
38+
, Geocoder::VERSION);
3939

4040
if ($address->getBounds()->isDefined()) {
4141
$bounds = $address->getBounds();

src/Geocoder/Geocoder.php

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ interface Geocoder
2525
/**
2626
* Geocodes a given value.
2727
*
28-
* @param string $value A value to geocode.
28+
* @param string $value
2929
*
3030
* @return Address[]
3131
*/
@@ -34,10 +34,28 @@ public function geocode($value);
3434
/**
3535
* Reverses geocode given latitude and longitude values.
3636
*
37-
* @param double $latitude Latitude.
38-
* @param double $longitude Longitude.
37+
* @param double $latitude.
38+
* @param double $longitude
3939
*
4040
* @return Address[]
4141
*/
4242
public function reverse($latitude, $longitude);
43+
44+
/**
45+
* Returns the maximum number of Address objects that can be
46+
* returned by `geocode()` or `reverse()` methods.
47+
*
48+
* @return integer
49+
*/
50+
public function getLimit();
51+
52+
/**
53+
* Sets the maximum number of `Address` objects that can be
54+
* returned by `geocode()` or `reverse()` methods.
55+
*
56+
* @param integer $limit
57+
*
58+
* @return Geocoder
59+
*/
60+
public function limit($limit);
4361
}

src/Geocoder/Provider/AbstractProvider.php

Lines changed: 33 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010

1111
namespace Geocoder\Provider;
1212

13+
use Geocoder\Geocoder;
1314
use Geocoder\Model\AddressFactory;
14-
use Geocoder\ProviderBasedGeocoder;
1515
use Ivory\HttpAdapter\HttpAdapterInterface;
1616

1717
/**
@@ -22,63 +22,53 @@ abstract class AbstractProvider
2222
/**
2323
* @var HttpAdapterInterface
2424
*/
25-
protected $adapter;
25+
private $adapter;
2626

2727
/**
28-
* @var string
28+
* @var AddressFactory
2929
*/
30-
protected $locale;
30+
private $factory;
3131

3232
/**
3333
* @var integer
3434
*/
35-
protected $maxResults = ProviderBasedGeocoder::MAX_RESULTS;
35+
private $limit = Provider::MAX_RESULTS;
3636

3737
/**
38-
* @var AddressFactory
38+
* @param HttpAdapterInterface $adapter An HTTP adapter
3939
*/
40-
protected $factory;
41-
42-
/**
43-
* @param HttpAdapterInterface $adapter An HTTP adapter.
44-
* @param string $locale A locale (optional).
45-
*/
46-
public function __construct(HttpAdapterInterface $adapter, $locale = null)
40+
public function __construct(HttpAdapterInterface $adapter)
4741
{
48-
$this->setLocale($locale);
49-
5042
$this->adapter = $adapter;
5143
$this->factory = new AddressFactory();
5244
}
5345

5446
/**
55-
* Returns the HTTP adapter.
56-
*
57-
* @return HttpAdapterInterface
47+
* {@inheritDoc}
5848
*/
59-
public function getAdapter()
49+
public function limit($limit)
6050
{
61-
return $this->adapter;
51+
$this->limit = $limit;
52+
53+
return $this;
6254
}
6355

6456
/**
6557
* {@inheritDoc}
6658
*/
67-
public function setMaxResults($maxResults)
59+
public function getLimit()
6860
{
69-
$this->maxResults = $maxResults;
70-
71-
return $this;
61+
return $this->limit;
7262
}
7363

7464
/**
75-
* Returns the maximum of wished results.
65+
* Returns the HTTP adapter.
7666
*
77-
* @return integer
67+
* @return HttpAdapterInterface
7868
*/
79-
public function getMaxResults()
69+
public function getAdapter()
8070
{
81-
return $this->maxResults;
71+
return $this->adapter;
8272
}
8373

8474
/**
@@ -88,10 +78,15 @@ public function getMaxResults()
8878
*/
8979
protected function getDefaults()
9080
{
91-
return array(
81+
return [
9282
'latitude' => null,
9383
'longitude' => null,
94-
'bounds' => null,
84+
'bounds' => [
85+
'south' => null,
86+
'west' => null,
87+
'north' => null,
88+
'east' => null,
89+
],
9590
'streetNumber' => null,
9691
'streetName' => null,
9792
'locality' => null,
@@ -104,7 +99,7 @@ protected function getDefaults()
10499
'country' => null,
105100
'countryCode' => null,
106101
'timezone' => null,
107-
);
102+
];
108103
}
109104

110105
/**
@@ -114,33 +109,25 @@ protected function getDefaults()
114109
*/
115110
protected function getLocalhostDefaults()
116111
{
117-
return array(
112+
return [
118113
'locality' => 'localhost',
119114
'region' => 'localhost',
120115
'county' => 'localhost',
121116
'country' => 'localhost',
122-
);
123-
}
124-
125-
/**
126-
* @param array $results
127-
*
128-
* @return array
129-
*/
130-
protected function fixEncoding(array $results)
131-
{
132-
return array_map(function ($value) {
133-
return is_string($value) ? utf8_encode($value) : $value;
134-
}, $results);
117+
];
135118
}
136119

137120
/**
138121
* @param array $data An array of data.
139122
*
140123
* @return \Geocoder\Model\Address[]
141124
*/
142-
protected function returnResult(array $data = [])
125+
protected function returnResults(array $data = [])
143126
{
127+
if (0 < $this->getLimit()) {
128+
$data = array_slice($data, 0, $this->getLimit());
129+
}
130+
144131
return $this->factory->createFromArray($data);
145132
}
146133
}

src/Geocoder/Provider/ArcGISOnline.php

Lines changed: 29 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,16 @@ class ArcGISOnline extends AbstractProvider implements Provider
4040
private $protocol;
4141

4242
/**
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).
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)
4646
*/
4747
public function __construct(HttpAdapterInterface $adapter, $sourceCountry = null, $useSsl = false)
4848
{
4949
parent::__construct($adapter);
5050

5151
$this->sourceCountry = $sourceCountry;
52-
$this->protocol = $useSsl ? 'https' : 'http';
52+
$this->protocol = $useSsl ? 'https' : 'http';
5353
}
5454

5555
/**
@@ -58,7 +58,7 @@ public function __construct(HttpAdapterInterface $adapter, $sourceCountry = null
5858
public function geocode($address)
5959
{
6060
if (filter_var($address, FILTER_VALIDATE_IP)) {
61-
throw new UnsupportedOperation('The ArcGISOnline does not support IP addresses.');
61+
throw new UnsupportedOperation('The ArcGISOnline provider does not support IP addresses, only street addresses.');
6262
}
6363

6464
// Save a request if no valid address entered
@@ -67,16 +67,14 @@ public function geocode($address)
6767
}
6868

6969
$query = sprintf(self::ENDPOINT_URL, $this->protocol, urlencode($address));
70-
71-
$json = $this->executeQuery($query);
70+
$json = $this->executeQuery($query);
7271

7372
// no result
7473
if (empty($json->locations)) {
75-
throw new NoResult(sprintf('No results found for query %s', $query));
74+
throw new NoResult(sprintf('No results found for query "%s".', $query));
7675
}
7776

78-
$results = array();
79-
77+
$results = [];
8078
foreach ($json->locations as $location) {
8179
$data = $location->feature->attributes;
8280

@@ -89,7 +87,7 @@ public function geocode($address)
8987
$county = !empty($data->Subregion) ? $data->Subregion : null;
9088
$countryCode = !empty($data->Country) ? $data->Country : null;
9189

92-
$results[] = array_merge($this->getDefaults(), array(
90+
$results[] = array_merge($this->getDefaults(), [
9391
'latitude' => $coordinates['y'],
9492
'longitude' => $coordinates['x'],
9593
'streetNumber' => $streetNumber,
@@ -99,10 +97,10 @@ public function geocode($address)
9997
'region' => $region,
10098
'countryCode' => $countryCode,
10199
'county' => $county,
102-
));
100+
]);
103101
}
104102

105-
return $results;
103+
return $this->returnResults($results);
106104
}
107105

108106
/**
@@ -111,11 +109,10 @@ public function geocode($address)
111109
public function reverse($latitude, $longitude)
112110
{
113111
$query = sprintf(self::REVERSE_ENDPOINT_URL, $this->protocol, $coordinates[1], $coordinates[0]);
114-
115-
$json = $this->executeQuery($query);
112+
$json = $this->executeQuery($query);
116113

117114
if (property_exists($json, 'error')) {
118-
throw new NoResult(sprintf('No results found for query %s', $query));
115+
throw new NoResult(sprintf('No results found for query "%s".', $query));
119116
}
120117

121118
$data = $json->address;
@@ -127,16 +124,18 @@ public function reverse($latitude, $longitude)
127124
$county = !empty($data->Subregion) ? $data->Subregion : null;
128125
$countryCode = !empty($data->CountryCode) ? $data->CountryCode : null;
129126

130-
return array(array_merge($this->getDefaults(), array(
131-
'latitude' => $coordinates[0],
132-
'longitude' => $coordinates[1],
133-
'streetName' => $streetName,
134-
'locality' => $city,
135-
'postalCode' => $zipcode,
136-
'region' => $region,
137-
'countryCode' => $countryCode,
138-
'county' => $county,
139-
)));
127+
return $this->returnResults([
128+
array_merge($this->getDefaults(), [
129+
'latitude' => $coordinates[0],
130+
'longitude' => $coordinates[1],
131+
'streetName' => $streetName,
132+
'locality' => $city,
133+
'postalCode' => $zipcode,
134+
'region' => $region,
135+
'countryCode' => $countryCode,
136+
'county' => $county,
137+
])
138+
]);
140139
}
141140

142141
/**
@@ -147,43 +146,29 @@ public function getName()
147146
return 'arcgis_online';
148147
}
149148

150-
/**
151-
* @param string $query
152-
*
153-
* @return string Query with extra params
154-
*/
155149
private function buildQuery($query)
156150
{
157151
if (null !== $this->sourceCountry) {
158152
$query = sprintf('%s&sourceCountry=%s', $query, $this->sourceCountry);
159153
}
160154

161-
return sprintf('%s&maxLocations=%d&f=%s&outFields=*', $query, $this->getMaxResults(), 'json');
155+
return sprintf('%s&maxLocations=%d&f=%s&outFields=*', $query, $this->getLimit(), 'json');
162156
}
163157

164-
/**
165-
* Executes a query
166-
*
167-
* @param string $query
168-
*
169-
* @throws NoResult
170-
*
171-
* @return \stdClass json object representing the query result
172-
*/
173158
private function executeQuery($query)
174159
{
175-
$query = $this->buildQuery($query);
160+
$query = $this->buildQuery($query);
176161
$content = (string) $this->getAdapter()->get($query)->getBody();
177162

178163
if (empty($content)) {
179-
throw new NoResult(sprintf('Could not execute query %s', $query));
164+
throw new NoResult(sprintf('Could not execute query "%s".', $query));
180165
}
181166

182167
$json = json_decode($content);
183168

184169
// API error
185170
if (!isset($json)) {
186-
throw new NoResult(sprintf('Could not execute query %s', $query));
171+
throw new NoResult(sprintf('Could not execute query "%s".', $query));
187172
}
188173

189174
return $json;

0 commit comments

Comments
 (0)