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; |
14
|
|
|
|
15
|
|
|
use Geocoder\Exception\ProviderNotRegistered; |
16
|
|
|
use Geocoder\Model\Coordinates; |
17
|
|
|
use Geocoder\Query\GeocodeQuery; |
18
|
|
|
use Geocoder\Query\ReverseQuery; |
19
|
|
|
use Geocoder\Provider\Provider; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* @author William Durand <[email protected]> |
23
|
|
|
*/ |
24
|
|
|
class ProviderAggregator implements Geocoder |
25
|
|
|
{ |
26
|
|
|
/** |
27
|
|
|
* @var Provider[] |
28
|
|
|
*/ |
29
|
|
|
private $providers = []; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* @var Provider |
33
|
|
|
*/ |
34
|
|
|
private $provider; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* @var int |
38
|
|
|
*/ |
39
|
|
|
private $limit; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* A callable that decided what provider to use. |
43
|
|
|
* |
44
|
|
|
* @var callable |
45
|
|
|
*/ |
46
|
|
|
private $decider; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* @param int $limit |
50
|
|
|
*/ |
51
|
10 |
|
public function __construct(int $limit = Geocoder::DEFAULT_RESULT_LIMIT, callable $decider = null) |
52
|
|
|
{ |
53
|
10 |
|
$this->limit($limit); |
54
|
10 |
|
$this->decider = $decider ?? __CLASS__.'::getProvider'; |
55
|
10 |
|
} |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* {@inheritdoc} |
59
|
|
|
*/ |
60
|
1 |
View Code Duplication |
public function geocodeQuery(GeocodeQuery $query): Collection |
|
|
|
|
61
|
|
|
{ |
62
|
1 |
|
if (null === $query->getLimit()) { |
63
|
|
|
$query = $query->withLimit($this->limit); |
64
|
|
|
} |
65
|
|
|
|
66
|
1 |
|
return call_user_func($this->decider, $query, $this->providers, $this->provider)->geocodeQuery($query); |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* {@inheritdoc} |
71
|
|
|
*/ |
72
|
1 |
View Code Duplication |
public function reverseQuery(ReverseQuery $query): Collection |
|
|
|
|
73
|
|
|
{ |
74
|
1 |
|
if (null === $query->getLimit()) { |
75
|
|
|
$query = $query->withLimit($this->limit); |
76
|
|
|
} |
77
|
|
|
|
78
|
1 |
|
return call_user_func($this->decider, $query, $this->providers, $this->provider)->reverseQuery($query); |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* {@inheritdoc} |
83
|
|
|
*/ |
84
|
|
|
public function getName(): string |
85
|
|
|
{ |
86
|
|
|
return 'provider_aggregator'; |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* {@inheritdoc} |
91
|
|
|
*/ |
92
|
1 |
|
public function geocode(string $value): Collection |
93
|
|
|
{ |
94
|
1 |
|
return $this->geocodeQuery(GeocodeQuery::create($value) |
95
|
1 |
|
->withLimit($this->limit)); |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* {@inheritdoc} |
100
|
|
|
*/ |
101
|
1 |
|
public function reverse(float $latitude, float $longitude): Collection |
102
|
|
|
{ |
103
|
1 |
|
return $this->reverseQuery(ReverseQuery::create(new Coordinates($latitude, $longitude)) |
104
|
1 |
|
->withLimit($this->limit)); |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* @param $limit |
109
|
|
|
* |
110
|
|
|
* @return $this |
111
|
|
|
*/ |
112
|
10 |
|
public function limit(int $limit): self |
113
|
|
|
{ |
114
|
10 |
|
$this->limit = $limit; |
115
|
|
|
|
116
|
10 |
|
return $this; |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* @return int |
121
|
|
|
*/ |
122
|
1 |
|
public function getLimit(): int |
123
|
|
|
{ |
124
|
1 |
|
return $this->limit; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* Registers a new provider to the aggregator. |
129
|
|
|
* |
130
|
|
|
* @param Provider $provider |
131
|
|
|
* |
132
|
|
|
* @return ProviderAggregator |
133
|
|
|
*/ |
134
|
5 |
|
public function registerProvider(Provider $provider): self |
135
|
|
|
{ |
136
|
5 |
|
$this->providers[$provider->getName()] = $provider; |
137
|
|
|
|
138
|
5 |
|
return $this; |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
/** |
142
|
|
|
* Registers a set of providers. |
143
|
|
|
* |
144
|
|
|
* @param Provider[] $providers |
145
|
|
|
* |
146
|
|
|
* @return ProviderAggregator |
147
|
|
|
*/ |
148
|
2 |
|
public function registerProviders(array $providers = []): self |
149
|
|
|
{ |
150
|
2 |
|
foreach ($providers as $provider) { |
151
|
2 |
|
$this->registerProvider($provider); |
152
|
|
|
} |
153
|
|
|
|
154
|
2 |
|
return $this; |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
/** |
158
|
|
|
* Sets the default provider to use. |
159
|
|
|
* |
160
|
|
|
* @param string $name |
161
|
|
|
* |
162
|
|
|
* @return ProviderAggregator |
163
|
|
|
*/ |
164
|
3 |
|
public function using(string $name): self |
165
|
|
|
{ |
166
|
3 |
|
if (!isset($this->providers[$name])) { |
167
|
2 |
|
throw ProviderNotRegistered::create($name ?? '', $this->providers); |
168
|
|
|
} |
169
|
|
|
|
170
|
1 |
|
$this->provider = $this->providers[$name]; |
171
|
|
|
|
172
|
1 |
|
return $this; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Returns all registered providers indexed by their name. |
177
|
|
|
* |
178
|
|
|
* @return Provider[] |
179
|
|
|
*/ |
180
|
1 |
|
public function getProviders(): array |
181
|
|
|
{ |
182
|
1 |
|
return $this->providers; |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
/** |
186
|
|
|
* Get a provider to use for this query. |
187
|
|
|
* |
188
|
|
|
* @param GeocodeQuery|ReverseQuery $query |
189
|
|
|
* @param Provider[] $providers |
190
|
|
|
* @param Provider $currentProvider |
191
|
|
|
* |
192
|
|
|
* @return Provider |
193
|
|
|
* |
194
|
|
|
* @throws ProviderNotRegistered |
195
|
|
|
*/ |
196
|
4 |
|
private static function getProvider($query, array $providers, Provider $currentProvider = null): Provider |
|
|
|
|
197
|
|
|
{ |
198
|
4 |
|
if (null !== $currentProvider) { |
199
|
2 |
|
return $currentProvider; |
200
|
|
|
} |
201
|
|
|
|
202
|
3 |
|
if (0 === count($providers)) { |
203
|
1 |
|
throw ProviderNotRegistered::noProviderRegistered(); |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
// Take first |
207
|
2 |
|
$key = key($providers); |
208
|
|
|
|
209
|
2 |
|
return $providers[$key]; |
210
|
|
|
} |
211
|
|
|
} |
212
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.