@@ -329,103 +329,126 @@ private function fetchUrl(string $url, int $limit, ?string $locale, ?string $cou
329329
330330 $ results = [];
331331 foreach ($ json ['features ' ] as $ result ) {
332- if (!array_key_exists ('context ' , $ result )) {
332+ $ results [] = $ this ->parseFeature ($ result );
333+
334+ if (count ($ results ) >= $ limit ) {
333335 break ;
334336 }
337+ }
335338
336- $ builder = new AddressBuilder ( $ this -> getName () );
337- $ this -> parseCoordinates ( $ builder , $ result );
339+ return new AddressCollection ( $ results );
340+ }
338341
339- // set official Mapbox place id
340- if (isset ($ result ['id ' ])) {
341- $ builder ->setValue ('id ' , $ result ['id ' ]);
342- }
342+ /**
343+ * @param array<string, mixed> $result
344+ */
345+ private function parseFeature (array $ result ): MapboxAddress
346+ {
347+ $ properties = $ result ['properties ' ] ?? [];
348+ $ context = $ properties ['context ' ] ?? [];
343349
344- // set official Mapbox place id
345- if (isset ($ result ['text ' ])) {
346- $ builder ->setValue ('street_name ' , $ result ['text ' ]);
347- }
350+ $ builder = new AddressBuilder ($ this ->getName ());
351+ $ this ->parseCoordinates ($ builder , $ result );
348352
349- // update address components
350- foreach ($ result ['context ' ] as $ component ) {
351- $ this ->updateAddressComponent ($ builder , $ component ['id ' ], $ component );
353+ // update address components (context is an object keyed by feature type in v6)
354+ foreach ($ context as $ type => $ component ) {
355+ if (is_array ($ component )) {
356+ $ this ->updateAddressComponent ($ builder , (string ) $ type , $ component );
352357 }
358+ }
353359
354- /** @var MapboxAddress $address */
355- $ address = $ builder ->build (MapboxAddress::class);
356- $ address = $ address ->withId ($ builder ->getValue ('id ' ));
357- if (isset ($ result ['address ' ])) {
358- $ address = $ address ->withStreetNumber ($ result ['address ' ]);
359- }
360- if (isset ($ result ['place_type ' ])) {
361- $ address = $ address ->withResultType ($ result ['place_type ' ]);
362- }
363- if (isset ($ result ['place_name ' ])) {
364- $ address = $ address ->withFormattedAddress ($ result ['place_name ' ]);
365- }
366- $ address = $ address ->withStreetName ($ builder ->getValue ('street_name ' ));
367- $ address = $ address ->withNeighborhood ($ builder ->getValue ('neighborhood ' ));
368- $ results [] = $ address ;
360+ /** @var MapboxAddress $address */
361+ $ address = $ builder ->build (MapboxAddress::class);
369362
370- if (count ($ results ) >= $ limit ) {
371- break ;
363+ if (isset ($ properties ['mapbox_id ' ])) {
364+ $ address = $ address ->withId ((string ) $ properties ['mapbox_id ' ]);
365+ } elseif (isset ($ result ['id ' ])) {
366+ $ address = $ address ->withId ((string ) $ result ['id ' ]);
367+ }
368+
369+ // street name without the house number (v5 semantics)
370+ $ streetName = $ context ['address ' ]['street_name ' ] ?? $ context ['street ' ]['name ' ] ?? $ properties ['name ' ] ?? null ;
371+ if (null !== $ streetName ) {
372+ $ address = $ address ->withStreetName ((string ) $ streetName );
373+ }
374+
375+ $ streetNumber = $ context ['address ' ]['address_number ' ] ?? null ;
376+ if (null !== $ streetNumber ) {
377+ $ address = $ address ->withStreetNumber ((string ) $ streetNumber );
378+ }
379+
380+ if (isset ($ properties ['feature_type ' ])) {
381+ $ address = $ address ->withResultType ([(string ) $ properties ['feature_type ' ]]);
382+ }
383+
384+ if (isset ($ properties ['full_address ' ])) {
385+ $ address = $ address ->withFormattedAddress ((string ) $ properties ['full_address ' ]);
386+ }
387+
388+ $ neighborhood = $ context ['neighborhood ' ]['name ' ] ?? null ;
389+ if (null !== $ neighborhood && '' !== $ neighborhood ) {
390+ $ address = $ address ->withNeighborhood ((string ) $ neighborhood );
391+ }
392+
393+ if (isset ($ properties ['match_code ' ]) && is_array ($ properties ['match_code ' ])) {
394+ $ address = $ address ->withMatchCode ($ properties ['match_code ' ]);
395+ $ confidence = $ properties ['match_code ' ]['confidence ' ] ?? null ;
396+ if (null !== $ confidence ) {
397+ $ address = $ address ->withMatchConfidence ((string ) $ confidence );
372398 }
373399 }
374400
375- return new AddressCollection ($ results );
401+ if (isset ($ properties ['coordinates ' ]['accuracy ' ])) {
402+ $ address = $ address ->withAccuracy ((string ) $ properties ['coordinates ' ]['accuracy ' ]);
403+ }
404+
405+ return $ address ;
376406 }
377407
378408 /**
379409 * Update current resultSet with given key/value.
380410 *
381- * @param string $type Component type
382- * @param array<string, mixed> $value Component value
411+ * @param array<string, mixed> $component
383412 */
384- private function updateAddressComponent (AddressBuilder $ builder , string $ type , array $ value ): void
413+ private function updateAddressComponent (AddressBuilder $ builder , string $ type , array $ component ): void
385414 {
386- $ typeParts = explode ('. ' , $ type );
387- $ type = reset ($ typeParts );
415+ if (!isset ($ component ['name ' ]) || '' === $ component ['name ' ]) {
416+ return ;
417+ }
388418
389419 switch ($ type ) {
390420 case 'postcode ' :
391- $ builder ->setPostalCode ($ value [ ' text ' ]);
421+ $ builder ->setPostalCode ($ component [ ' name ' ]);
392422
393423 break ;
394424
395425 case 'locality ' :
396- $ builder ->setLocality ($ value [ ' text ' ]);
426+ $ builder ->setLocality ($ component [ ' name ' ]);
397427
398428 break ;
399429
400430 case 'country ' :
401- $ builder ->setCountry ($ value [ ' text ' ]);
402- if (isset ($ value [ ' short_code ' ])) {
403- $ builder ->setCountryCode (strtoupper ($ value [ ' short_code ' ]));
431+ $ builder ->setCountry ($ component [ ' name ' ]);
432+ if (isset ($ component [ ' country_code ' ])) {
433+ $ builder ->setCountryCode (strtoupper (( string ) $ component [ ' country_code ' ]));
404434 }
405435
406436 break ;
407437
408- case 'neighborhood ' :
409- $ builder ->setValue ($ type , $ value ['text ' ]);
410-
411- break ;
412-
413438 case 'place ' :
414- $ builder ->addAdminLevel (1 , $ value [ ' text ' ]);
415- $ builder ->setLocality ($ value [ ' text ' ]);
439+ $ builder ->addAdminLevel (1 , $ component [ ' name ' ]);
440+ $ builder ->setLocality ($ component [ ' name ' ]);
416441
417442 break ;
418443
419444 case 'region ' :
420- $ code = null ;
421- if (!empty ($ value ['short_code ' ]) && preg_match ('/[A-z]{2}-/ ' , $ value ['short_code ' ])) {
422- $ code = preg_replace ('/[A-z]{2}-/ ' , '' , $ value ['short_code ' ]);
423- }
424- $ builder ->addAdminLevel (2 , $ value ['text ' ], $ code );
445+ $ code = isset ($ component ['region_code ' ]) ? (string ) $ component ['region_code ' ] : null ;
446+ $ builder ->addAdminLevel (2 , $ component ['name ' ], $ code );
425447
426448 break ;
427449
428450 default :
451+ // address, street, district, neighborhood: handled (or intentionally ignored) elsewhere
429452 }
430453 }
431454
0 commit comments