1717use Geocoder \Exception \QuotaExceeded ;
1818use Geocoder \Exception \UnsupportedOperation ;
1919use Geocoder \Http \Provider \AbstractHttpProvider ;
20- use Geocoder \Model \Address ;
20+ use Geocoder \Model \AddressBuilder ;
2121use Geocoder \Model \AddressCollection ;
22+ use Geocoder \Provider \Pelias \Model \PeliasAddress ;
2223use Geocoder \Provider \Provider ;
2324use Geocoder \Query \GeocodeQuery ;
2425use Geocoder \Query \ReverseQuery ;
@@ -60,14 +61,16 @@ protected function getGeocodeQueryUrl(GeocodeQuery $query, array $query_data = [
6061 $ data = [
6162 'text ' => $ address ,
6263 'size ' => $ query ->getLimit (),
64+ 'layers ' => null !== $ query ->getData ('layers ' ) ? implode (', ' , $ query ->getData ('layers ' )) : null ,
65+ 'boundary.country ' => null !== $ query ->getData ('boundary.country ' ) ? implode (', ' , $ query ->getData ('boundary.country ' )) : null ,
6366 ];
6467
6568 return sprintf ('%s/search?%s ' , $ this ->root , http_build_query (array_merge ($ data , $ query_data )));
6669 }
6770
6871 public function geocodeQuery (GeocodeQuery $ query ): Collection
6972 {
70- return $ this ->executeQuery ($ this ->getGeocodeQueryUrl ($ query ));
73+ return $ this ->executeQuery ($ this ->getGeocodeQueryUrl ($ query ), $ query -> getLocale () );
7174 }
7275
7376 /**
@@ -85,24 +88,32 @@ protected function getReverseQueryUrl(ReverseQuery $query, array $query_data = [
8588 'point.lat ' => $ latitude ,
8689 'point.lon ' => $ longitude ,
8790 'size ' => $ query ->getLimit (),
91+ 'layers ' => null !== $ query ->getData ('layers ' ) ? implode (', ' , $ query ->getData ('layers ' )) : null ,
92+ 'boundary.country ' => null !== $ query ->getData ('boundary.country ' ) ? implode (', ' , $ query ->getData ('boundary.country ' )) : null ,
8893 ];
8994
9095 return sprintf ('%s/reverse?%s ' , $ this ->root , http_build_query (array_merge ($ data , $ query_data )));
9196 }
9297
9398 public function reverseQuery (ReverseQuery $ query ): Collection
9499 {
95- return $ this ->executeQuery ($ this ->getReverseQueryUrl ($ query ));
100+ return $ this ->executeQuery ($ this ->getReverseQueryUrl ($ query ), $ query -> getLocale () );
96101 }
97102
98103 public function getName (): string
99104 {
100105 return 'pelias ' ;
101106 }
102107
103- protected function executeQuery (string $ url ): AddressCollection
108+ protected function executeQuery (string $ url, ? string $ locale ): AddressCollection
104109 {
105- $ content = $ this ->getUrlContents ($ url );
110+ $ headers = [];
111+ if (null !== $ locale ) {
112+ $ headers ['Accept-Language ' ] = $ locale ;
113+ }
114+
115+ $ request = $ this ->createRequest ('GET ' , $ url , $ headers );
116+ $ content = $ this ->getParsedResponse ($ request );
106117 $ json = json_decode ($ content , true );
107118
108119 if (isset ($ json ['meta ' ])) {
@@ -124,53 +135,53 @@ protected function executeQuery(string $url): AddressCollection
124135 return new AddressCollection ([]);
125136 }
126137
127- $ locations = $ json ['features ' ];
138+ $ features = $ json ['features ' ];
128139
129- if (empty ($ locations )) {
140+ if (empty ($ features )) {
130141 return new AddressCollection ([]);
131142 }
132143
133144 $ results = [];
134- foreach ($ locations as $ location ) {
135- if (isset ($ location ['bbox ' ])) {
136- $ bounds = [
137- 'south ' => $ location ['bbox ' ][3 ],
138- 'west ' => $ location ['bbox ' ][2 ],
139- 'north ' => $ location ['bbox ' ][1 ],
140- 'east ' => $ location ['bbox ' ][0 ],
141- ];
142- } else {
143- $ bounds = [
144- 'south ' => null ,
145- 'west ' => null ,
146- 'north ' => null ,
147- 'east ' => null ,
148- ];
145+ foreach ($ features as $ feature ) {
146+ $ builder = new AddressBuilder ($ this ->getName ());
147+ $ builder ->setCoordinates ($ feature ['geometry ' ]['coordinates ' ][1 ], $ feature ['geometry ' ]['coordinates ' ][0 ]);
148+ $ builder ->setStreetNumber ($ feature ['properties ' ]['housenumber ' ] ?? null );
149+ $ builder ->setStreetName ($ this ->guessStreetName ($ feature ['properties ' ]));
150+ $ builder ->setSubLocality ($ this ->guessSubLocality ($ feature ['properties ' ]));
151+ $ builder ->setLocality ($ this ->guessLocality ($ feature ['properties ' ]));
152+ $ builder ->setPostalCode ($ feature ['properties ' ]['postalcode ' ] ?? null );
153+ $ builder ->setCountry ($ feature ['properties ' ]['country ' ] ?? null );
154+ $ builder ->setCountryCode (
155+ isset ($ feature ['properties ' ]['country_code ' ]) ? strtoupper ($ feature ['properties ' ]['country_code ' ]) :
156+ (isset ($ feature ['properties ' ]['country_a ' ]) ? strtoupper ($ feature ['properties ' ]['country_a ' ]) : null ));
157+ $ builder ->setTimezone ($ feature ['properties ' ]['timezone ' ] ?? null );
158+
159+ if (isset ($ feature ['bbox ' ])) {
160+ $ builder ->setBounds ($ feature ['bbox ' ][3 ], $ feature ['bbox ' ][2 ], $ feature ['bbox ' ][1 ], $ feature ['bbox ' ][0 ]);
149161 }
150162
151- $ props = $ location ['properties ' ];
152-
153- $ adminLevels = [];
154- foreach (['region ' , 'county ' , 'locality ' , 'macroregion ' , 'country ' ] as $ i => $ component ) {
155- if (isset ($ props [$ component ])) {
156- $ adminLevels [] = ['name ' => $ props [$ component ], 'level ' => $ i + 1 ];
163+ $ level = 1 ;
164+ foreach (['macroregion ' , 'region ' , 'macrocounty ' , 'county ' , 'locality ' , 'localadmin ' , 'borough ' ] as $ component ) {
165+ if (isset ($ feature ['properties ' ][$ component ])) {
166+ $ builder ->addAdminLevel ($ level ++, $ feature ['properties ' ][$ component ], $ feature ['properties ' ][$ component .'_a ' ] ?? null );
167+ }
168+ // Administrative level should be an integer in [1,5].
169+ if ($ level > 5 ) {
170+ break ;
157171 }
158172 }
159173
160- $ results [] = Address::createFromArray ([
161- 'providedBy ' => $ this ->getName (),
162- 'latitude ' => $ location ['geometry ' ]['coordinates ' ][1 ],
163- 'longitude ' => $ location ['geometry ' ]['coordinates ' ][0 ],
164- 'bounds ' => $ bounds ,
165- 'streetNumber ' => isset ($ props ['housenumber ' ]) ? $ props ['housenumber ' ] : null ,
166- 'streetName ' => isset ($ props ['street ' ]) ? $ props ['street ' ] : null ,
167- 'subLocality ' => isset ($ props ['neighbourhood ' ]) ? $ props ['neighbourhood ' ] : null ,
168- 'locality ' => isset ($ props ['locality ' ]) ? $ props ['locality ' ] : null ,
169- 'postalCode ' => isset ($ props ['postalcode ' ]) ? $ props ['postalcode ' ] : null ,
170- 'adminLevels ' => $ adminLevels ,
171- 'country ' => isset ($ props ['country ' ]) ? $ props ['country ' ] : null ,
172- 'countryCode ' => isset ($ props ['country_a ' ]) ? strtoupper ($ props ['country_a ' ]) : null ,
173- ]);
174+ /** @var PeliasAddress $location */
175+ $ location = $ builder ->build (PeliasAddress::class);
176+
177+ $ location = $ location ->withId ($ feature ['properties ' ]['id ' ] ?? null );
178+ $ location = $ location ->withLayer ($ feature ['properties ' ]['layer ' ] ?? null );
179+ $ location = $ location ->withSource ($ feature ['properties ' ]['source ' ] ?? null );
180+ $ location = $ location ->withName ($ feature ['properties ' ]['name ' ] ?? null );
181+ $ location = $ location ->withConfidence ($ feature ['properties ' ]['confidence ' ] ?? null );
182+ $ location = $ location ->withAccuracy ($ feature ['properties ' ]['accuracy ' ] ?? null );
183+
184+ $ results [] = $ location ;
174185 }
175186
176187 return new AddressCollection ($ results );
@@ -181,35 +192,35 @@ protected function executeQuery(string $url): AddressCollection
181192 *
182193 * @return string|null
183194 */
184- protected function guessLocality (array $ components )
195+ protected static function guessLocality (array $ components )
185196 {
186- $ localityKeys = ['city ' , 'town ' , 'village ' , 'hamlet ' ];
197+ $ localityKeys = ['locality ' , ' localadmin ' , ' city ' , 'town ' , 'village ' , 'hamlet ' ];
187198
188- return $ this -> guessBestComponent ($ components , $ localityKeys );
199+ return self :: guessBestComponent ($ components , $ localityKeys );
189200 }
190201
191202 /**
192203 * @param array<string, mixed> $components
193204 *
194205 * @return string|null
195206 */
196- protected function guessStreetName (array $ components )
207+ protected static function guessSubLocality (array $ components )
197208 {
198- $ streetNameKeys = ['road ' , 'street ' , ' street_name ' , ' residential ' ];
209+ $ subLocalityKeys = ['neighbourhood ' , 'city_district ' ];
199210
200- return $ this -> guessBestComponent ($ components , $ streetNameKeys );
211+ return self :: guessBestComponent ($ components , $ subLocalityKeys );
201212 }
202213
203214 /**
204215 * @param array<string, mixed> $components
205216 *
206217 * @return string|null
207218 */
208- protected function guessSubLocality (array $ components )
219+ protected static function guessStreetName (array $ components )
209220 {
210- $ subLocalityKeys = ['neighbourhood ' , 'city_district ' ];
221+ $ streetNameKeys = ['road ' , 'street ' , ' street_name ' , ' residential ' ];
211222
212- return $ this -> guessBestComponent ($ components , $ subLocalityKeys );
223+ return self :: guessBestComponent ($ components , $ streetNameKeys );
213224 }
214225
215226 /**
@@ -218,7 +229,7 @@ protected function guessSubLocality(array $components)
218229 *
219230 * @return string|null
220231 */
221- protected function guessBestComponent (array $ components , array $ keys )
232+ protected static function guessBestComponent (array $ components , array $ keys )
222233 {
223234 foreach ($ keys as $ key ) {
224235 if (isset ($ components [$ key ]) && !empty ($ components [$ key ])) {
0 commit comments