xref: /webtrees/app/Http/RequestHandlers/AutoCompletePlace.php (revision 89f7189b61a494347591c99bdb92afb7d8b66e1b)
163763244SGreg Roach<?php
263763244SGreg Roach
363763244SGreg Roach/**
463763244SGreg Roach * webtrees: online genealogy
5*89f7189bSGreg Roach * Copyright (C) 2021 webtrees development team
663763244SGreg Roach * This program is free software: you can redistribute it and/or modify
763763244SGreg Roach * it under the terms of the GNU General Public License as published by
863763244SGreg Roach * the Free Software Foundation, either version 3 of the License, or
963763244SGreg Roach * (at your option) any later version.
1063763244SGreg Roach * This program is distributed in the hope that it will be useful,
1163763244SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
1263763244SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1363763244SGreg Roach * GNU General Public License for more details.
1463763244SGreg Roach * You should have received a copy of the GNU General Public License
15*89f7189bSGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>.
1663763244SGreg Roach */
1763763244SGreg Roach
1863763244SGreg Roachdeclare(strict_types=1);
1963763244SGreg Roach
2063763244SGreg Roachnamespace Fisharebest\Webtrees\Http\RequestHandlers;
2163763244SGreg Roach
2263763244SGreg Roachuse Fisharebest\Webtrees\I18N;
2363763244SGreg Roachuse Fisharebest\Webtrees\Place;
2463763244SGreg Roachuse Fisharebest\Webtrees\Site;
2563763244SGreg Roachuse Fisharebest\Webtrees\Tree;
2663763244SGreg Roachuse GuzzleHttp\Client;
2763763244SGreg Roachuse GuzzleHttp\Exception\RequestException;
2863763244SGreg Roachuse Illuminate\Support\Collection;
2963763244SGreg Roachuse Psr\Http\Message\ServerRequestInterface;
3063763244SGreg Roach
3163763244SGreg Roachuse function assert;
3263763244SGreg Roachuse function is_array;
3363763244SGreg Roachuse function json_decode;
3463763244SGreg Roachuse function rawurlencode;
3563763244SGreg Roach
3663763244SGreg Roach/**
3763763244SGreg Roach * Autocomplete handler for places
3863763244SGreg Roach */
3963763244SGreg Roachclass AutoCompletePlace extends AbstractAutocompleteHandler
4063763244SGreg Roach{
4163763244SGreg Roach    // Options for fetching files using GuzzleHTTP
4263763244SGreg Roach    private const GUZZLE_OPTIONS = [
4363763244SGreg Roach        'connect_timeout' => 3,
4463763244SGreg Roach        'read_timeout'    => 3,
4563763244SGreg Roach        'timeout'         => 3,
4663763244SGreg Roach    ];
4763763244SGreg Roach
4863763244SGreg Roach    protected function search(ServerRequestInterface $request): Collection
4963763244SGreg Roach    {
5063763244SGreg Roach        $tree = $request->getAttribute('tree');
5163763244SGreg Roach        assert($tree instanceof Tree);
5263763244SGreg Roach
5363763244SGreg Roach        $query = $request->getAttribute('query');
5463763244SGreg Roach
5563763244SGreg Roach        $data = $this->search_service
5663763244SGreg Roach            ->searchPlaces($tree, $query, 0, static::LIMIT)
5763763244SGreg Roach            ->map(static function (Place $place): string {
5863763244SGreg Roach                return $place->gedcomName();
5963763244SGreg Roach            });
6063763244SGreg Roach
6163763244SGreg Roach        $geonames = Site::getPreference('geonames');
6263763244SGreg Roach
6363763244SGreg Roach        if ($data->isEmpty() && $geonames !== '') {
6463763244SGreg Roach            // No place found? Use an external gazetteer
6563763244SGreg Roach            $url =
6663763244SGreg Roach                'https://secure.geonames.org/searchJSON' .
6763763244SGreg Roach                '?name_startsWith=' . rawurlencode($query) .
6863763244SGreg Roach                '&lang=' . I18N::languageTag() .
6963763244SGreg Roach                '&fcode=CMTY&fcode=ADM4&fcode=PPL&fcode=PPLA&fcode=PPLC' .
7063763244SGreg Roach                '&style=full' .
7163763244SGreg Roach                '&username=' . rawurlencode($geonames);
7263763244SGreg Roach
7363763244SGreg Roach            // Read from the URL
7463763244SGreg Roach            $client = new Client();
7563763244SGreg Roach            try {
7663763244SGreg Roach                $json   = $client->get($url, self::GUZZLE_OPTIONS)->getBody()->__toString();
7763763244SGreg Roach                $places = json_decode($json, true);
7863763244SGreg Roach                if (isset($places['geonames']) && is_array($places['geonames'])) {
7963763244SGreg Roach                    foreach ($places['geonames'] as $k => $place) {
8063763244SGreg Roach                        $data->add($place['name'] . ', ' . $place['adminName2'] . ', ' . $place['adminName1'] . ', ' . $place['countryName']);
8163763244SGreg Roach                    }
8263763244SGreg Roach                }
8363763244SGreg Roach            } catch (RequestException $ex) {
8463763244SGreg Roach                // Service down?  Quota exceeded?
8563763244SGreg Roach            }
8663763244SGreg Roach        }
8763763244SGreg Roach
8863763244SGreg Roach        return new Collection($data);
8963763244SGreg Roach    }
9063763244SGreg Roach}
91