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