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