xref: /webtrees/resources/views/fact-date.phtml (revision 00ef1d3af59aba99c1ae5c92c7e655525c97797b)
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