1<?php 2 3declare(strict_types=1); 4 5use Fisharebest\Webtrees\Age; 6use Fisharebest\Webtrees\Date; 7use Fisharebest\Webtrees\Fact; 8use Fisharebest\Webtrees\Family; 9use Fisharebest\Webtrees\Gedcom; 10use Fisharebest\Webtrees\GedcomRecord; 11use Fisharebest\Webtrees\I18N; 12use Fisharebest\Webtrees\Individual; 13use Fisharebest\Webtrees\Registry; 14 15/** 16 * @var bool $cal_link 17 * @var Fact $fact 18 * @var GedcomRecord $record 19 * @var bool $time 20 */ 21 22$element_factory = Registry::elementFactory(); 23 24$factrec = $fact->gedcom(); 25$html = ''; 26 27// Recorded age 28if (preg_match('/\n2 AGE (.+)/', $factrec, $match) === 1) { 29 $fact_age = $element_factory->make($fact->tag() . ':AGE')->value($match[1], $record->tree()); 30} else { 31 $fact_age = ''; 32} 33 34if (preg_match('/\n2 HUSB\n3 AGE (.+)/', $factrec, $match) === 1) { 35 $husb_age = $element_factory->make($fact->tag() . ':HUSB:AGE')->value($match[1], $record->tree()); 36} else { 37 $husb_age = ''; 38} 39 40if (preg_match('/\n2 WIFE\n3 AGE (.+)/', $factrec, $match) === 1) { 41 $wife_age = $element_factory->make($fact->tag() . ':WIFE:AGE')->value($match[1], $record->tree()); 42} else { 43 $wife_age = ''; 44} 45 46// Calculated age 47[, $tag] = explode(':', $fact->tag()); 48 49if (preg_match('/\n2 DATE (.+)/', $factrec, $match) === 1) { 50 $date = new Date($match[1]); 51 $html .= ' ' . $date->display($cal_link ? $record->tree() : null, null, true); 52 // Time isn't valid GEDCOM, but it is widely used. 53 if ($time && preg_match('/\n3 TIME (.+)/', $factrec, $match) === 1) { 54 $html .= ' – <span class="date">' . $match[1] . '</span>'; 55 } 56 57 if ($record instanceof Individual) { 58 if ( 59 in_array($tag, Gedcom::BIRTH_EVENTS, true) && 60 $record === $fact->record() && 61 $record->tree()->getPreference('SHOW_PARENTS_AGE') === '1' 62 ) { 63 // age of parents at child birth 64 $html .= view('fact-parents-age', ['individual' => $record, 'birth_date' => $date]); 65 } 66 67 if ($tag !== 'BIRT' && $tag !== 'CHAN' && $tag !== 'NO' && $tag !== '_TODO') { 68 // age at event 69 $birth_date = $record->getBirthDate(); 70 // Can't use getDeathDate(), as this also gives BURI/CREM events, which 71 // wouldn't give the correct "days after death" result for people with 72 // no DEAT. 73 $death_event = $record->facts(['DEAT'])->first(); 74 if ($death_event instanceof Fact) { 75 $death_date = $death_event->date(); 76 } else { 77 $death_date = new Date(''); 78 } 79 $ageText = ''; 80 81 if ($tag === 'DEAT' || Date::compare($date, $death_date) <= 0 || !$record->isDead()) { 82 // Before death, print age 83 $age = (string) new Age($birth_date, $date); 84 85 // Only show calculated age if it differs from recorded age 86 if ($age !== '') { 87 if ( 88 $fact_age !== '' && !str_starts_with($fact_age, $age) || 89 $fact_age === '' && $husb_age === '' && $wife_age === '' || 90 $husb_age !== '' && !str_starts_with($husb_age, $age) && $record->sex() === 'M' || 91 $wife_age !== '' && !str_starts_with($wife_age, $age) && $record->sex() === 'F' 92 ) { 93 switch ($record->sex()) { 94 case 'M': 95 /* I18N: The age of an individual at a given date */ 96 $ageText = I18N::translateContext('Male', '(aged %s)', $age); 97 break; 98 case 'F': 99 /* I18N: The age of an individual at a given date */ 100 $ageText = I18N::translateContext('Female', '(aged %s)', $age); 101 break; 102 default: 103 /* I18N: The age of an individual at a given date */ 104 $ageText = I18N::translate('(aged %s)', $age); 105 break; 106 } 107 } 108 } 109 } 110 111 if ($tag !== 'DEAT' && $death_date->isOK() && Date::compare($death_date, $date) <= 0) { 112 $death_day = $death_date->minimumDate()->day(); 113 $event_day = $date->minimumDate()->day(); 114 if ($death_day !== 0 && $event_day !== 0 && Date::compare($death_date, $date) === 0) { 115 // On the exact date of death? 116 // NOTE: this path is never reached. Keep the code (translation) in case 117 // we decide to re-introduce it. 118 $ageText = I18N::translate('(on the date of death)'); 119 } else { 120 // After death 121 $age = (string) new Age($death_date, $date); 122 $ageText = I18N::translate('(%s after death)', $age); 123 } 124 125 // Family events which occur after death are probably errors 126 if ($fact->record() instanceof Family) { 127 $ageText .= view('icons/warning'); 128 } 129 } 130 131 if ($ageText !== '') { 132 $html .= ' <span class="age">' . $ageText . '</span>'; 133 } 134 } 135 } 136} 137// print gedcom ages 138$age_labels = [ 139 I18N::translate('Age') => $fact_age, 140 I18N::translate('Husband') => $husb_age, 141 I18N::translate('Wife') => $wife_age, 142]; 143 144foreach (array_filter($age_labels) as $label => $age) { 145 $html .= ' <span class="label">' . $label . ':</span> <span class="age">' . $age . '</span>'; 146} 147 148?> 149<span class="wt-fact-date-age"> 150 <?= $html ?> 151</span> 152