Completed
Push — develop ( c3a705...4b9394 )
by Greg
11:16
created

parsePlaceNameSearchResponse()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 29
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 16
c 1
b 0
f 0
nc 8
nop 1
dl 0
loc 29
rs 9.7333
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
18
declare(strict_types=1);
19
20
namespace Fisharebest\Webtrees\Module;
21
22
use Fisharebest\Webtrees\FlashMessages;
23
use Fisharebest\Webtrees\Gedcom;
24
use Fisharebest\Webtrees\Html;
25
use Fisharebest\Webtrees\I18N;
26
use Fisharebest\Webtrees\Site;
27
use GuzzleHttp\Psr7\Request;
28
use JsonException;
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: 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
    /**
73
     * Should this module be enabled when it is first installed?
74
     *
75
     * @return bool
76
     */
77
    public function isEnabledByDefault(): bool
78
    {
79
        return false;
80
    }
81
82
    /**
83
     * @return ResponseInterface
84
     */
85
    public function getAdminAction(): ResponseInterface
86
    {
87
        $this->layout = 'layouts/administration';
88
89
        // This was a global setting before it became a module setting...
90
        $default  = Site::getPreference('geonames');
91
        $username = $this->getPreference('username', $default);
92
93
        return $this->viewResponse('modules/geonames/config', [
94
            'username' => $username,
95
            'title'    => $this->title(),
96
        ]);
97
    }
98
99
    /**
100
     * @param ServerRequestInterface $request
101
     *
102
     * @return ResponseInterface
103
     */
104
    public function postAdminAction(ServerRequestInterface $request): ResponseInterface
105
    {
106
        $params = (array) $request->getParsedBody();
107
108
        $this->setPreference('username', $params['username' ?? '']);
109
110
        FlashMessages::addMessage(I18N::translate('The preferences for the module “%s” have been updated.', $this->title()), 'success');
111
112
        return redirect($this->getConfigLink());
113
    }
114
115
    /**
116
     * @param string $place
117
     *
118
     * @return RequestInterface
119
     */
120
    protected function createPlaceNameSearchRequest(string $place): RequestInterface
121
    {
122
        // This was a global setting before it became a module setting...
123
        $default  = Site::getPreference('geonames');
124
        $username = $this->getPreference('username', $default);
125
126
        $uri = Html::url('https://secure.geonames.org/searchJSON', [
127
            'name_startsWith' => $place,
128
            'featureClass'    => 'P',
129
            'lang'            => I18N::languageTag(),
130
            'username'        => $username,
131
        ]);
132
133
        return new Request('GET', $uri);
134
    }
135
136
    /**
137
     * @param ResponseInterface $response
138
     *
139
     * @return array<string>
140
     */
141
    protected function parsePlaceNameSearchResponse(ResponseInterface $response): array
142
    {
143
        $body   = $response->getBody()->getContents();
144
        $places = [];
145
146
        try {
147
            $results = json_decode($body, false, 512, JSON_THROW_ON_ERROR);
148
149
            foreach ($results->geonames as $result) {
150
                if (($result->countryName ?? null) === 'United Kingdom') {
151
                    // adminName1 will be England, Scotland, etc.
152
                    $result->countryName = null;
153
                }
154
155
                $parts = [
156
                    $result->name,
157
                    $result->adminName2 ?? null,
158
                    $result->adminName1 ?? null,
159
                    $result->countryName ?? null,
160
                ];
161
162
                $places[] = implode(Gedcom::PLACE_SEPARATOR, array_filter($parts));
163
            }
164
        } catch (JsonException $ex) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
165
        }
166
167
        usort($places, I18N::comparator());
168
169
        return $places;
170
    }
171
}
172