xref: /webtrees/app/Http/RequestHandlers/HelpText.php (revision d11be7027e34e3121be11cc025421873364403f9)
1<?php
2
3/**
4 * webtrees: online genealogy
5 * Copyright (C) 2023 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\Auth;
23use Fisharebest\Webtrees\Date;
24use Fisharebest\Webtrees\I18N;
25use Psr\Http\Message\ResponseInterface;
26use Psr\Http\Message\ServerRequestInterface;
27use Psr\Http\Server\RequestHandlerInterface;
28
29use function array_keys;
30use function response;
31use function strip_tags;
32use function view;
33
34/**
35 * Show help text.
36 */
37class HelpText implements RequestHandlerInterface
38{
39    private const FRENCH_DATES = [
40        '@#DFRENCH R@ 12',
41        '@#DFRENCH R@ VEND 12',
42        'ABT @#DFRENCH R@ BRUM 12',
43        'BET @#DFRENCH R@ FRIM 12 AND @#DFRENCH R@ NIVO 12',
44        'FROM @#DFRENCH R@ PLUV 12 TO @#DFRENCH R@ VENT 12',
45        'AFT @#DFRENCH R@ GERM 12',
46        'BEF @#DFRENCH R@ FLOR 12',
47        'ABT @#DFRENCH R@ PRAI 12',
48        'FROM @#DFRENCH R@ MESS 12',
49        'TO @#DFRENCH R@ THER 12',
50        'EST @#DFRENCH R@ FRUC 12',
51        '@#DFRENCH R@ 03 COMP 12',
52    ];
53
54    private const HIJRI_DATES = [
55        '@#DHIJRI@ 1497',
56        '@#DHIJRI@ MUHAR 1497',
57        'ABT @#DHIJRI@ SAFAR 1497',
58        'BET @#DHIJRI@ RABIA 1497 AND @#DHIJRI@ RABIT 1497',
59        'FROM @#DHIJRI@ JUMAA 1497 TO @#DHIJRI@ JUMAT 1497',
60        'AFT @#DHIJRI@ RAJAB 1497',
61        'BEF @#DHIJRI@ SHAAB 1497',
62        'ABT @#DHIJRI@ RAMAD 1497',
63        'FROM @#DHIJRI@ SHAWW 1497',
64        'TO @#DHIJRI@ DHUAQ 1497',
65        '@#DHIJRI@ 03 DHUAH 1497',
66    ];
67
68    private const JALALI_DATES = [
69        '@#DJALALI@ 1497',
70        '@#DJALALI@ FARVA 1497',
71        'ABT @#DJALALI@ ORDIB 1497',
72        'BET @#DJALALI@ KHORD 1497 AND @#DHIJRI@ TIR 1497',
73        'FROM @#DJALALI@ MORDA 1497 TO @#DHIJRI@ SHAHR 1497',
74        'AFT @#DJALALI@ MEHR 1497',
75        'BEF @#DJALALI@ ABAN 1497',
76        'ABT @#DJALALI@ AZAR 1497',
77        'FROM @#DJALALI@ DEY 1497',
78        'TO @#DJALALI@ BAHMA 1497',
79        '@#DJALALI@ 03 XXXXX 1497',
80    ];
81
82    private const JEWISH_DATES = [
83        '@#DHEBREW@ 5481',
84        '@#DHEBREW@ TSH 5481',
85        'ABT @#DHEBREW@ CSH 5481',
86        'BET @#DHEBREW@ KSL 5481 AND @#DHEBREW@ TVT 5481',
87        'FROM @#DHEBREW@ SHV 5481 TO @#DHEBREW@ ADR 5481',
88        'AFT @#DHEBREW@ ADR 5481',
89        'AFT @#DHEBREW@ ADS 5480',
90        'BEF @#DHEBREW@ NSN 5481',
91        'ABT @#DHEBREW@ IYR 5481',
92        'FROM @#DHEBREW@ SVN 5481',
93        'TO @#DHEBREW@ TMZ 5481',
94        'EST @#DHEBREW@ AAV 5481',
95        '@#DHEBREW@ 03 ELL 5481',
96    ];
97
98    private const JULIAN_DATES = [
99        '@#DJULIAN@ 14 JAN 1700',
100        '@#DJULIAN@ 44 B.C.',
101        '@#DJULIAN@ 20 FEB 1742/43',
102        'BET @#DJULIAN@ 01 SEP 1752 AND @#DGREGORIAN@ 30 SEP 1752',
103    ];
104
105    private const DATE_SHORTCUTS = [
106        '1900'           => [],
107        'JAN 1900'       => [],
108        'FEB 1900'       => [],
109        'MAR 1900'       => [],
110        'APR 1900'       => [],
111        'MAY 1900'       => [],
112        'JUN 1900'       => [],
113        'JUL 1900'       => [],
114        'AUG 1900'       => [],
115        'SEP 1900'       => [],
116        'OCT 1900'       => [],
117        'NOV 1900'       => [],
118        'DEC 1900'       => [],
119        'ABT 1900'       => ['~1900'],
120        'EST 1900'       => ['*1900'],
121        'CAL 1900'       => ['#1900'],
122        'INT 1900 (...)' => [],
123    ];
124
125    private const DATE_RANGE_SHORTCUTS = [
126        'BET 1900 AND 1910'         => ['1900-1910'],
127        'AFT 1900'                  => ['>1900'],
128        'BEF 1910'                  => ['<1910'],
129        'BET JAN 1900 AND MAR 1900' => ['Q1 1900'],
130        'BET APR 1900 AND JUN 1900' => ['Q2 1900'],
131        'BET JUL 1900 AND SEP 1900' => ['Q3 1900'],
132        'BET OCT 1900 AND DEC 1900' => ['Q4 1900'],
133    ];
134
135    private const DATE_PERIOD_SHORTCUTS = [
136        'FROM 1900 TO 1910' => ['1900~1910'],
137        'FROM 1900'         => ['1900-'],
138        'TO 1910'           => ['-1900'],
139    ];
140
141    private const DMY_SHORTCUTS = [
142        '11 DEC 1913' => [
143            '11/12/1913',
144            '11-12-1913',
145            '11.12.1913',
146        ],
147        '01 FEB 2003' => [
148            '01/02/03',
149            '01-02-03',
150            '01.02.03',
151        ],
152    ];
153
154    private const MDY_SHORTCUTS = [
155        '11 DEC 1913' => [
156            '12/11/1913',
157            '12-11-1913',
158            '12.11.1913',
159        ],
160        '01 FEB 2003' => [
161            '02/01/03',
162            '02-01-03',
163            '02.01.03',
164        ],
165    ];
166
167    private const YMD_SHORTCUTS = [
168        '11 DEC 1913' => [
169            '11/12/1913',
170            '11-12-1913',
171            '11.12.1913',
172        ],
173        '01 FEB 2003' => [
174            '03/02/01',
175            '03-02-01',
176            '03.02.01',
177        ],
178    ];
179
180    /**
181     * @param ServerRequestInterface $request
182     *
183     * @return ResponseInterface
184     */
185    public function handle(ServerRequestInterface $request): ResponseInterface
186    {
187        $topic = $request->getAttribute('topic');
188
189        $dmy = I18N::language()->dateOrder();
190
191        switch ($topic) {
192            case 'DATE':
193                switch ($dmy) {
194                    case 'YMD':
195                        $date_shortcuts = self::DATE_SHORTCUTS + self::YMD_SHORTCUTS;
196                        break;
197                    case 'MDY':
198                        $date_shortcuts = self::DATE_SHORTCUTS + self::MDY_SHORTCUTS;
199                        break;
200                    case 'DMY':
201                    default:
202                        $date_shortcuts = self::DATE_SHORTCUTS + self::DMY_SHORTCUTS;
203                        break;
204                }
205
206                $title = I18N::translate('Date');
207                $text  = view('help/date', [
208                    'date_dates'            => $this->formatDates(array_keys($date_shortcuts)),
209                    'date_shortcuts'        => $date_shortcuts,
210                    'date_period_dates'     => $this->formatDates(array_keys(self::DATE_PERIOD_SHORTCUTS)),
211                    'date_period_shortcuts' => self::DATE_PERIOD_SHORTCUTS,
212                    'date_range_dates'      => $this->formatDates(array_keys(self::DATE_RANGE_SHORTCUTS)),
213                    'date_range_shortcuts'  => self::DATE_RANGE_SHORTCUTS,
214                    'french_dates'          => $this->formatDates(self::FRENCH_DATES),
215                    'hijri_dates'           => $this->formatDates(self::HIJRI_DATES),
216                    'jalali_dates'          => $this->formatDates(self::JALALI_DATES),
217                    'jewish_dates'          => $this->formatDates(self::JEWISH_DATES),
218                    'julian_dates'          => $this->formatDates(self::JULIAN_DATES),
219                ]);
220                break;
221
222            case 'NAME':
223                $title = I18N::translate('Name');
224                $text  = view('help/name');
225                break;
226
227            case 'SURN':
228                $title = I18N::translate('Surname');
229                $text  = view('help/surname');
230                break;
231
232            case 'OBJE':
233                $title = I18N::translate('Media object');
234                $text  = view('help/media-object');
235                break;
236
237            case 'PLAC':
238                $title = I18N::translate('Place');
239                $text  = view('help/place');
240                break;
241
242            case 'RESN':
243                $title = I18N::translate('Restriction');
244                $text  = view('help/restriction');
245                break;
246
247            case 'ROMN':
248                $title = I18N::translate('Romanized');
249                $text  = view('help/romanized');
250                break;
251
252            case '_HEB':
253                $title = I18N::translate('Hebrew');
254                $text  = view('help/hebrew');
255                break;
256
257            case 'data-fixes':
258                $title = I18N::translate('Data fixes');
259                $text  = view('help/data-fixes');
260                break;
261
262            case 'edit_SOUR_EVEN':
263                $title = I18N::translate('Associate events with this source');
264                $text  = view('help/source-events');
265                break;
266
267            case 'pending_changes':
268                $title = I18N::translate('Pending changes');
269                $text  = view('help/pending-changes', [
270                    'is_admin' => Auth::isAdmin(),
271                ]);
272                break;
273
274            case 'relationship-privacy':
275                $title = I18N::translate('Restrict to immediate family');
276                $text  = view('help/relationship-privacy');
277                break;
278
279            default:
280                $title = I18N::translate('Help');
281                $text  = I18N::translate('The help text has not been written for this item.');
282                break;
283        }
284
285        $html = view('modals/help', [
286            'title' => $title,
287            'text'  => $text,
288        ]);
289
290        return response($html);
291    }
292
293    /**
294     * Format GEDCOM dates in the local language.
295     *
296     * @param array<string>|array<int> $gedcom_dates
297     *
298     * @return array<string>
299     */
300    private function formatDates(array $gedcom_dates): array
301    {
302        $dates = [];
303
304        foreach ($gedcom_dates as $gedcom_date) {
305            // PHP converts numeric array keys ('1900') to integers (1900), so reverse this.
306            $gedcom_date = (string) $gedcom_date;
307
308            $date                = new Date($gedcom_date);
309            $dates[$gedcom_date] = strip_tags($date->display());
310        }
311
312        return $dates;
313    }
314}
315