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