Issues (2559)

app/Module/GeonamesAutocomplete.php (2 issues)

Labels
Severity
1
<?php
2
3
/**
4
 * webtrees: online genealogy
5
 * Copyright (C) 2025 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
18
declare(strict_types=1);
19
20
namespace Fisharebest\Webtrees\Module;
21
22
use Fisharebest\Webtrees\FlashMessages;
0 ignored issues
show
The type Fisharebest\Webtrees\FlashMessages was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
23
use Fisharebest\Webtrees\Gedcom;
24
use Fisharebest\Webtrees\Html;
25
use Fisharebest\Webtrees\I18N;
0 ignored issues
show
The type Fisharebest\Webtrees\I18N was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
26
use Fisharebest\Webtrees\Site;
27
use Fisharebest\Webtrees\Validator;
28
use GuzzleHttp\Psr7\Request;
29
use Psr\Http\Message\RequestInterface;
30
use Psr\Http\Message\ResponseInterface;
31
use Psr\Http\Message\ServerRequestInterface;
32
33
use function array_filter;
34
use function implode;
35
use function json_decode;
36
use function redirect;
37
use function usort;
38
39
use const JSON_THROW_ON_ERROR;
40
41
/**
42
 * Class GeonamesAutocomplete - use geonames.org to search for place names
43
 */
44
class GeonamesAutocomplete extends AbstractModule implements ModuleConfigInterface, ModuleMapAutocompleteInterface
45
{
46
    use ModuleConfigTrait;
47
    use ModuleMapAutocompleteTrait;
48
49
    /**
50
     * Name of the map provider.
51
     *
52
     * @return string
53
     */
54
    public function title(): string
55
    {
56
        // I18N: https://www.geonames.org
57
        return I18N::translate('GeoNames');
58
    }
59
60
    /**
61
     * Name of the map provider.
62
     *
63
     * @return string
64
     */
65
    public function description(): string
66
    {
67
        $link = '<a href="https://geonames.org">geonames.org</a>';
68
69
        return I18N::translate('Search for place names using %s.', $link);
70
    }
71
72
    public function isEnabledByDefault(): bool
73
    {
74
        return false;
75
    }
76
77
    /**
78
     * @return ResponseInterface
79
     */
80
    public function getAdminAction(): ResponseInterface
81
    {
82
        $this->layout = 'layouts/administration';
83
84
        // This was a global setting before it became a module setting...
85
        $default  = Site::getPreference('geonames');
86
        $username = $this->getPreference('username', $default);
87
88
        return $this->viewResponse('modules/geonames/config', [
89
            'username' => $username,
90
            'title'    => $this->title(),
91
        ]);
92
    }
93
94
    /**
95
     * @param ServerRequestInterface $request
96
     *
97
     * @return ResponseInterface
98
     */
99
    public function postAdminAction(ServerRequestInterface $request): ResponseInterface
100
    {
101
        $username = Validator::parsedBody($request)->string('username');
102
103
        $this->setPreference('username', $username);
104
105
        FlashMessages::addMessage(I18N::translate('The preferences for the module ā€œ%sā€ have been updated.', $this->title()), 'success');
106
107
        return redirect($this->getConfigLink());
108
    }
109
110
    /**
111
     * @param string $place
112
     *
113
     * @return RequestInterface
114
     */
115
    protected function createPlaceNameSearchRequest(string $place): RequestInterface
116
    {
117
        // This was a global setting before it became a module setting...
118
        $default  = Site::getPreference('geonames');
119
        $username = $this->getPreference('username', $default);
120
121
        $uri = Html::url('https://secure.geonames.org/searchJSON', [
122
            'name_startsWith' => $place,
123
            'featureClass'    => 'P',
124
            'lang'            => I18N::languageTag(),
125
            'username'        => $username,
126
        ]);
127
128
        return new Request('GET', $uri);
129
    }
130
131
    /**
132
     * @param ResponseInterface $response
133
     *
134
     * @return array<string>
135
     */
136
    protected function parsePlaceNameSearchResponse(ResponseInterface $response): array
137
    {
138
        $body    = $response->getBody()->getContents();
139
        $places  = [];
140
        $results = json_decode($body, false, 512, JSON_THROW_ON_ERROR);
141
142
        foreach ($results->geonames as $result) {
143
            if (($result->countryName ?? null) === 'United Kingdom') {
144
                // adminName1 will be England, Scotland, etc.
145
                $result->countryName = null;
146
            }
147
148
            $parts = [
149
                $result->name,
150
                $result->adminName2 ?? null,
151
                $result->adminName1 ?? null,
152
                $result->countryName ?? null,
153
            ];
154
155
            $places[] = implode(Gedcom::PLACE_SEPARATOR, array_filter($parts));
156
        }
157
158
        usort($places, I18N::comparator());
159
160
        return $places;
161
    }
162
}
163