1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2021 webtrees development team 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <https://www.gnu.org/licenses/>. 16 */ 17 18declare(strict_types=1); 19 20namespace Fisharebest\Webtrees\Http\RequestHandlers; 21 22use Fisharebest\Webtrees\I18N; 23use Fisharebest\Webtrees\Place; 24use Fisharebest\Webtrees\Site; 25use Fisharebest\Webtrees\Tree; 26use GuzzleHttp\Client; 27use GuzzleHttp\Exception\RequestException; 28use Illuminate\Support\Collection; 29use Psr\Http\Message\ServerRequestInterface; 30 31use function assert; 32use function is_array; 33use function json_decode; 34use function rawurlencode; 35 36/** 37 * Autocomplete handler for places 38 */ 39class AutoCompletePlace extends AbstractAutocompleteHandler 40{ 41 // Options for fetching files using GuzzleHTTP 42 private const GUZZLE_OPTIONS = [ 43 'connect_timeout' => 3, 44 'read_timeout' => 3, 45 'timeout' => 3, 46 ]; 47 48 protected function search(ServerRequestInterface $request): Collection 49 { 50 $tree = $request->getAttribute('tree'); 51 assert($tree instanceof Tree); 52 53 $query = $request->getAttribute('query'); 54 55 $data = $this->search_service 56 ->searchPlaces($tree, $query, 0, static::LIMIT) 57 ->map(static function (Place $place): string { 58 return $place->gedcomName(); 59 }); 60 61 $geonames = Site::getPreference('geonames'); 62 63 if ($data->isEmpty() && $geonames !== '') { 64 // No place found? Use an external gazetteer 65 $url = 66 'https://secure.geonames.org/searchJSON' . 67 '?name_startsWith=' . rawurlencode($query) . 68 '&lang=' . I18N::languageTag() . 69 '&fcode=CMTY&fcode=ADM4&fcode=PPL&fcode=PPLA&fcode=PPLC' . 70 '&style=full' . 71 '&username=' . rawurlencode($geonames); 72 73 // Read from the URL 74 $client = new Client(); 75 try { 76 $json = $client->get($url, self::GUZZLE_OPTIONS)->getBody()->__toString(); 77 $places = json_decode($json, true); 78 if (isset($places['geonames']) && is_array($places['geonames'])) { 79 foreach ($places['geonames'] as $k => $place) { 80 $data->add($place['name'] . ', ' . $place['adminName2'] . ', ' . $place['adminName1'] . ', ' . $place['countryName']); 81 } 82 } 83 } catch (RequestException $ex) { 84 // Service down? Quota exceeded? 85 } 86 } 87 88 return new Collection($data); 89 } 90} 91