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