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