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