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