12c066a59SGreg Roach<?php 22c066a59SGreg Roach 32c066a59SGreg Roach/** 42c066a59SGreg Roach * webtrees: online genealogy 5d11be702SGreg Roach * Copyright (C) 2023 webtrees development team 62c066a59SGreg Roach * This program is free software: you can redistribute it and/or modify 72c066a59SGreg Roach * it under the terms of the GNU General Public License as published by 82c066a59SGreg Roach * the Free Software Foundation, either version 3 of the License, or 92c066a59SGreg Roach * (at your option) any later version. 102c066a59SGreg Roach * This program is distributed in the hope that it will be useful, 112c066a59SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 122c066a59SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 132c066a59SGreg Roach * GNU General Public License for more details. 142c066a59SGreg Roach * You should have received a copy of the GNU General Public License 152c066a59SGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>. 162c066a59SGreg Roach */ 172c066a59SGreg Roach 182c066a59SGreg Roachdeclare(strict_types=1); 192c066a59SGreg Roach 202c066a59SGreg Roachnamespace Fisharebest\Webtrees\Services; 212c066a59SGreg Roach 222c066a59SGreg Roachuse Fisharebest\Webtrees\Date; 232c066a59SGreg Roachuse Fisharebest\Webtrees\Fact; 242c066a59SGreg Roachuse Fisharebest\Webtrees\Family; 252c066a59SGreg Roachuse Fisharebest\Webtrees\I18N; 262c066a59SGreg Roachuse Fisharebest\Webtrees\Individual; 272c066a59SGreg Roachuse Fisharebest\Webtrees\Module\ModuleHistoricEventsInterface; 282c066a59SGreg Roachuse Illuminate\Support\Collection; 292c066a59SGreg Roach 302c066a59SGreg Roachuse function explode; 312c066a59SGreg Roachuse function preg_match; 322c066a59SGreg Roachuse function preg_replace; 332c066a59SGreg Roachuse function str_replace; 342c066a59SGreg Roach 352c066a59SGreg Roach/** 362c066a59SGreg Roach * Provide lists of facts for IndividualFactsTabModule. 372c066a59SGreg Roach */ 382c066a59SGreg Roachclass IndividualFactsService 392c066a59SGreg Roach{ 402c066a59SGreg Roach private LinkedRecordService $linked_record_service; 412c066a59SGreg Roach 422c066a59SGreg Roach private ModuleService $module_service; 432c066a59SGreg Roach 442c066a59SGreg Roach /** 452c066a59SGreg Roach * @param LinkedRecordService $linked_record_service 462c066a59SGreg Roach * @param ModuleService $module_service 472c066a59SGreg Roach */ 482c066a59SGreg Roach public function __construct( 492c066a59SGreg Roach LinkedRecordService $linked_record_service, 502c066a59SGreg Roach ModuleService $module_service 512c066a59SGreg Roach ) { 522c066a59SGreg Roach $this->linked_record_service = $linked_record_service; 532c066a59SGreg Roach $this->module_service = $module_service; 542c066a59SGreg Roach } 552c066a59SGreg Roach 562c066a59SGreg Roach /** 572c066a59SGreg Roach * The individuals own facts, such as birth and death. 582c066a59SGreg Roach * 592c066a59SGreg Roach * @param Individual $individual 602c066a59SGreg Roach * @param Collection<int,string> $exclude_facts 612c066a59SGreg Roach * 62ccbecad5SGreg Roach * @return Collection<int,Fact> 632c066a59SGreg Roach */ 642c066a59SGreg Roach public function individualFacts(Individual $individual, Collection $exclude_facts): Collection 652c066a59SGreg Roach { 662c066a59SGreg Roach return $individual->facts() 672c066a59SGreg Roach ->filter(fn (Fact $fact): bool => !$exclude_facts->contains($fact->tag())); 682c066a59SGreg Roach } 692c066a59SGreg Roach 702c066a59SGreg Roach /** 712c066a59SGreg Roach * The individuals own family facts, such as marriage and divorce. 722c066a59SGreg Roach * 732c066a59SGreg Roach * @param Individual $individual 742c066a59SGreg Roach * @param Collection<int,string> $exclude_facts 752c066a59SGreg Roach * 76ccbecad5SGreg Roach * @return Collection<int,Fact> 772c066a59SGreg Roach */ 782c066a59SGreg Roach public function familyFacts(Individual $individual, Collection $exclude_facts): Collection 792c066a59SGreg Roach { 802c066a59SGreg Roach return $individual->spouseFamilies() 812c066a59SGreg Roach ->map(fn (Family $family): Collection => $family->facts()) 822c066a59SGreg Roach ->flatten() 832c066a59SGreg Roach ->filter(fn (Fact $fact): bool => !$exclude_facts->contains($fact->tag())); 842c066a59SGreg Roach } 852c066a59SGreg Roach 862c066a59SGreg Roach /** 872c066a59SGreg Roach * Get the events of associates. 882c066a59SGreg Roach * 892c066a59SGreg Roach * @param Individual $individual 902c066a59SGreg Roach * 912c066a59SGreg Roach * @return Collection<int,Fact> 922c066a59SGreg Roach */ 932c066a59SGreg Roach public function associateFacts(Individual $individual): Collection 942c066a59SGreg Roach { 952c066a59SGreg Roach $facts = []; 962c066a59SGreg Roach 972c066a59SGreg Roach $asso1 = $this->linked_record_service->linkedIndividuals($individual, 'ASSO'); 982c066a59SGreg Roach $asso2 = $this->linked_record_service->linkedIndividuals($individual, '_ASSO'); 992c066a59SGreg Roach $asso3 = $this->linked_record_service->linkedFamilies($individual, 'ASSO'); 1002c066a59SGreg Roach $asso4 = $this->linked_record_service->linkedFamilies($individual, '_ASSO'); 1012c066a59SGreg Roach 1022c066a59SGreg Roach $associates = $asso1->merge($asso2)->merge($asso3)->merge($asso4); 1032c066a59SGreg Roach 1042c066a59SGreg Roach foreach ($associates as $associate) { 1052c066a59SGreg Roach foreach ($associate->facts() as $fact) { 1062c066a59SGreg Roach if (preg_match('/\n\d _?ASSO @' . $individual->xref() . '@/', $fact->gedcom())) { 1072c066a59SGreg Roach // Extract the important details from the fact 1082c066a59SGreg Roach $factrec = explode("\n", $fact->gedcom(), 2)[0]; 1092c066a59SGreg Roach if (preg_match('/\n2 DATE .*/', $fact->gedcom(), $match)) { 1102c066a59SGreg Roach $factrec .= $match[0]; 1112c066a59SGreg Roach } 1122c066a59SGreg Roach if (preg_match('/\n2 PLAC .*/', $fact->gedcom(), $match)) { 1132c066a59SGreg Roach $factrec .= $match[0]; 1142c066a59SGreg Roach } 1152c066a59SGreg Roach if ($associate instanceof Family) { 1162c066a59SGreg Roach foreach ($associate->spouses() as $spouse) { 1172c066a59SGreg Roach $factrec .= "\n2 _ASSO @" . $spouse->xref() . '@'; 1182c066a59SGreg Roach } 1192c066a59SGreg Roach } else { 1202c066a59SGreg Roach $factrec .= "\n2 _ASSO @" . $associate->xref() . '@'; 1212c066a59SGreg Roach } 1222c066a59SGreg Roach $facts[] = new Fact($factrec, $associate, 'asso'); 1232c066a59SGreg Roach } 1242c066a59SGreg Roach } 1252c066a59SGreg Roach } 1262c066a59SGreg Roach 1272c066a59SGreg Roach return new Collection($facts); 1282c066a59SGreg Roach } 1292c066a59SGreg Roach 1302c066a59SGreg Roach /** 1312c066a59SGreg Roach * Get the events of close relatives. 1322c066a59SGreg Roach * 1332c066a59SGreg Roach * @param Individual $individual 1342c066a59SGreg Roach * 1352c066a59SGreg Roach * @return Collection<int,Fact> 1362c066a59SGreg Roach */ 1372c066a59SGreg Roach public function relativeFacts(Individual $individual): Collection 1382c066a59SGreg Roach { 1392c066a59SGreg Roach // Only include events of close relatives that are between birth and death 1402c066a59SGreg Roach $min_date = $individual->getEstimatedBirthDate(); 1412c066a59SGreg Roach $max_date = $individual->getEstimatedDeathDate(); 1422c066a59SGreg Roach 1432c066a59SGreg Roach $parent_facts = $this->parentFacts($individual, 1, $min_date, $max_date); 1442c066a59SGreg Roach 1452c066a59SGreg Roach $spouse_facts = $individual->spouseFamilies() 1462c066a59SGreg Roach ->filter(fn (Family $family): bool => $family->spouse($individual) instanceof Individual) 1472c066a59SGreg Roach ->map(fn (Family $family): Collection => $this->spouseFacts($individual, $family->spouse($individual), $min_date, $max_date)) 1482c066a59SGreg Roach ->flatten(); 1492c066a59SGreg Roach 1502c066a59SGreg Roach $child_facts = $individual->spouseFamilies() 1512c066a59SGreg Roach ->map(fn (Family $family): Collection => $this->childFacts($individual, $family, '_CHIL', '', $min_date, $max_date)) 1522c066a59SGreg Roach ->flatten(); 1532c066a59SGreg Roach 1542c066a59SGreg Roach return $parent_facts 1552c066a59SGreg Roach ->merge($child_facts) 156357f854eSGreg Roach ->merge($spouse_facts) 157357f854eSGreg Roach ->unique(); 1582c066a59SGreg Roach } 1592c066a59SGreg Roach 1602c066a59SGreg Roach /** 1612c066a59SGreg Roach * Get any historical events. 1622c066a59SGreg Roach * 1632c066a59SGreg Roach * @param Individual $individual 1642c066a59SGreg Roach * 1652c066a59SGreg Roach * @return Collection<int,Fact> 1662c066a59SGreg Roach */ 1672c066a59SGreg Roach public function historicFacts(Individual $individual): Collection 1682c066a59SGreg Roach { 1692c066a59SGreg Roach return $this->module_service->findByInterface(ModuleHistoricEventsInterface::class) 170*f25fc0f9SGreg Roach ->map(static fn (ModuleHistoricEventsInterface $module): Collection => $module->historicEventsForIndividual($individual)) 1712c066a59SGreg Roach ->flatten(); 1722c066a59SGreg Roach } 1732c066a59SGreg Roach 1742c066a59SGreg Roach /** 1752c066a59SGreg Roach * Get the events of children and grandchildren. 1762c066a59SGreg Roach * 1772c066a59SGreg Roach * @param Individual $person 1782c066a59SGreg Roach * @param Family $family 1792c066a59SGreg Roach * @param string $option 1802c066a59SGreg Roach * @param string $relation 1812c066a59SGreg Roach * @param Date $min_date 1822c066a59SGreg Roach * @param Date $max_date 1832c066a59SGreg Roach * 1842c066a59SGreg Roach * @return Collection<int,Fact> 1852c066a59SGreg Roach */ 1862c066a59SGreg Roach private function childFacts(Individual $person, Family $family, string $option, string $relation, Date $min_date, Date $max_date): Collection 1872c066a59SGreg Roach { 1882c066a59SGreg Roach $SHOW_RELATIVES_EVENTS = $person->tree()->getPreference('SHOW_RELATIVES_EVENTS'); 1892c066a59SGreg Roach 1902c066a59SGreg Roach $birth_of_a_child = [ 1912c066a59SGreg Roach 'INDI:BIRT' => [ 1922c066a59SGreg Roach 'M' => I18N::translate('Birth of a son'), 1932c066a59SGreg Roach 'F' => I18N::translate('Birth of a daughter'), 1942c066a59SGreg Roach 'U' => I18N::translate('Birth of a child'), 1952c066a59SGreg Roach ], 1962c066a59SGreg Roach 'INDI:CHR' => [ 1972c066a59SGreg Roach 'M' => I18N::translate('Christening of a son'), 1982c066a59SGreg Roach 'F' => I18N::translate('Christening of a daughter'), 1992c066a59SGreg Roach 'U' => I18N::translate('Christening of a child'), 2002c066a59SGreg Roach ], 2012c066a59SGreg Roach 'INDI:BAPM' => [ 2022c066a59SGreg Roach 'M' => I18N::translate('Baptism of a son'), 2032c066a59SGreg Roach 'F' => I18N::translate('Baptism of a daughter'), 2042c066a59SGreg Roach 'U' => I18N::translate('Baptism of a child'), 2052c066a59SGreg Roach ], 2062c066a59SGreg Roach 'INDI:ADOP' => [ 2072c066a59SGreg Roach 'M' => I18N::translate('Adoption of a son'), 2082c066a59SGreg Roach 'F' => I18N::translate('Adoption of a daughter'), 2092c066a59SGreg Roach 'U' => I18N::translate('Adoption of a child'), 2102c066a59SGreg Roach ], 2112c066a59SGreg Roach ]; 2122c066a59SGreg Roach 2132c066a59SGreg Roach $birth_of_a_sibling = [ 2142c066a59SGreg Roach 'INDI:BIRT' => [ 2152c066a59SGreg Roach 'M' => I18N::translate('Birth of a brother'), 2162c066a59SGreg Roach 'F' => I18N::translate('Birth of a sister'), 2172c066a59SGreg Roach 'U' => I18N::translate('Birth of a sibling'), 2182c066a59SGreg Roach ], 2192c066a59SGreg Roach 'INDI:CHR' => [ 2202c066a59SGreg Roach 'M' => I18N::translate('Christening of a brother'), 2212c066a59SGreg Roach 'F' => I18N::translate('Christening of a sister'), 2222c066a59SGreg Roach 'U' => I18N::translate('Christening of a sibling'), 2232c066a59SGreg Roach ], 2242c066a59SGreg Roach 'INDI:BAPM' => [ 2252c066a59SGreg Roach 'M' => I18N::translate('Baptism of a brother'), 2262c066a59SGreg Roach 'F' => I18N::translate('Baptism of a sister'), 2272c066a59SGreg Roach 'U' => I18N::translate('Baptism of a sibling'), 2282c066a59SGreg Roach ], 2292c066a59SGreg Roach 'INDI:ADOP' => [ 2302c066a59SGreg Roach 'M' => I18N::translate('Adoption of a brother'), 2312c066a59SGreg Roach 'F' => I18N::translate('Adoption of a sister'), 2322c066a59SGreg Roach 'U' => I18N::translate('Adoption of a sibling'), 2332c066a59SGreg Roach ], 2342c066a59SGreg Roach ]; 2352c066a59SGreg Roach 2362c066a59SGreg Roach $birth_of_a_half_sibling = [ 2372c066a59SGreg Roach 'INDI:BIRT' => [ 2382c066a59SGreg Roach 'M' => I18N::translate('Birth of a half-brother'), 2392c066a59SGreg Roach 'F' => I18N::translate('Birth of a half-sister'), 2402c066a59SGreg Roach 'U' => I18N::translate('Birth of a half-sibling'), 2412c066a59SGreg Roach ], 2422c066a59SGreg Roach 'INDI:CHR' => [ 2432c066a59SGreg Roach 'M' => I18N::translate('Christening of a half-brother'), 2442c066a59SGreg Roach 'F' => I18N::translate('Christening of a half-sister'), 2452c066a59SGreg Roach 'U' => I18N::translate('Christening of a half-sibling'), 2462c066a59SGreg Roach ], 2472c066a59SGreg Roach 'INDI:BAPM' => [ 2482c066a59SGreg Roach 'M' => I18N::translate('Baptism of a half-brother'), 2492c066a59SGreg Roach 'F' => I18N::translate('Baptism of a half-sister'), 2502c066a59SGreg Roach 'U' => I18N::translate('Baptism of a half-sibling'), 2512c066a59SGreg Roach ], 2522c066a59SGreg Roach 'INDI:ADOP' => [ 2532c066a59SGreg Roach 'M' => I18N::translate('Adoption of a half-brother'), 2542c066a59SGreg Roach 'F' => I18N::translate('Adoption of a half-sister'), 2552c066a59SGreg Roach 'U' => I18N::translate('Adoption of a half-sibling'), 2562c066a59SGreg Roach ], 2572c066a59SGreg Roach ]; 2582c066a59SGreg Roach 2592c066a59SGreg Roach $birth_of_a_grandchild = [ 2602c066a59SGreg Roach 'INDI:BIRT' => [ 2612c066a59SGreg Roach 'M' => I18N::translate('Birth of a grandson'), 2622c066a59SGreg Roach 'F' => I18N::translate('Birth of a granddaughter'), 2632c066a59SGreg Roach 'U' => I18N::translate('Birth of a grandchild'), 2642c066a59SGreg Roach ], 2652c066a59SGreg Roach 'INDI:CHR' => [ 2662c066a59SGreg Roach 'M' => I18N::translate('Christening of a grandson'), 2672c066a59SGreg Roach 'F' => I18N::translate('Christening of a granddaughter'), 2682c066a59SGreg Roach 'U' => I18N::translate('Christening of a grandchild'), 2692c066a59SGreg Roach ], 2702c066a59SGreg Roach 'INDI:BAPM' => [ 2712c066a59SGreg Roach 'M' => I18N::translate('Baptism of a grandson'), 2722c066a59SGreg Roach 'F' => I18N::translate('Baptism of a granddaughter'), 2732c066a59SGreg Roach 'U' => I18N::translate('Baptism of a grandchild'), 2742c066a59SGreg Roach ], 2752c066a59SGreg Roach 'INDI:ADOP' => [ 2762c066a59SGreg Roach 'M' => I18N::translate('Adoption of a grandson'), 2772c066a59SGreg Roach 'F' => I18N::translate('Adoption of a granddaughter'), 2782c066a59SGreg Roach 'U' => I18N::translate('Adoption of a grandchild'), 2792c066a59SGreg Roach ], 2802c066a59SGreg Roach ]; 2812c066a59SGreg Roach 2822c066a59SGreg Roach $birth_of_a_grandchild1 = [ 2832c066a59SGreg Roach 'INDI:BIRT' => [ 2842c066a59SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Birth of a grandson'), 2852c066a59SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Birth of a granddaughter'), 2862c066a59SGreg Roach 'U' => I18N::translate('Birth of a grandchild'), 2872c066a59SGreg Roach ], 2882c066a59SGreg Roach 'INDI:CHR' => [ 2892c066a59SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Christening of a grandson'), 2902c066a59SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Christening of a granddaughter'), 2912c066a59SGreg Roach 'U' => I18N::translate('Christening of a grandchild'), 2922c066a59SGreg Roach ], 2932c066a59SGreg Roach 'INDI:BAPM' => [ 2942c066a59SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Baptism of a grandson'), 2952c066a59SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Baptism of a granddaughter'), 2962c066a59SGreg Roach 'U' => I18N::translate('Baptism of a grandchild'), 2972c066a59SGreg Roach ], 2982c066a59SGreg Roach 'INDI:ADOP' => [ 2992c066a59SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Adoption of a grandson'), 3002c066a59SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Adoption of a granddaughter'), 3012c066a59SGreg Roach 'U' => I18N::translate('Adoption of a grandchild'), 3022c066a59SGreg Roach ], 3032c066a59SGreg Roach ]; 3042c066a59SGreg Roach 3052c066a59SGreg Roach $birth_of_a_grandchild2 = [ 3062c066a59SGreg Roach 'INDI:BIRT' => [ 3072c066a59SGreg Roach 'M' => I18N::translateContext('son’s son', 'Birth of a grandson'), 3082c066a59SGreg Roach 'F' => I18N::translateContext('son’s daughter', 'Birth of a granddaughter'), 3092c066a59SGreg Roach 'U' => I18N::translate('Birth of a grandchild'), 3102c066a59SGreg Roach ], 3112c066a59SGreg Roach 'INDI:CHR' => [ 3122c066a59SGreg Roach 'M' => I18N::translateContext('son’s son', 'Christening of a grandson'), 3132c066a59SGreg Roach 'F' => I18N::translateContext('son’s daughter', 'Christening of a granddaughter'), 3142c066a59SGreg Roach 'U' => I18N::translate('Christening of a grandchild'), 3152c066a59SGreg Roach ], 3162c066a59SGreg Roach 'INDI:BAPM' => [ 3172c066a59SGreg Roach 'M' => I18N::translateContext('son’s son', 'Baptism of a grandson'), 3182c066a59SGreg Roach 'F' => I18N::translateContext('son’s daughter', 'Baptism of a granddaughter'), 3192c066a59SGreg Roach 'U' => I18N::translate('Baptism of a grandchild'), 3202c066a59SGreg Roach ], 3212c066a59SGreg Roach 'INDI:ADOP' => [ 3222c066a59SGreg Roach 'M' => I18N::translateContext('son’s son', 'Adoption of a grandson'), 3232c066a59SGreg Roach 'F' => I18N::translateContext('son’s daughter', 'Adoption of a granddaughter'), 3242c066a59SGreg Roach 'U' => I18N::translate('Adoption of a grandchild'), 3252c066a59SGreg Roach ], 3262c066a59SGreg Roach ]; 3272c066a59SGreg Roach 3282c066a59SGreg Roach $death_of_a_child = [ 3292c066a59SGreg Roach 'INDI:DEAT' => [ 3302c066a59SGreg Roach 'M' => I18N::translate('Death of a son'), 3312c066a59SGreg Roach 'F' => I18N::translate('Death of a daughter'), 3322c066a59SGreg Roach 'U' => I18N::translate('Death of a child'), 3332c066a59SGreg Roach ], 3342c066a59SGreg Roach 'INDI:BURI' => [ 3352c066a59SGreg Roach 'M' => I18N::translate('Burial of a son'), 3362c066a59SGreg Roach 'F' => I18N::translate('Burial of a daughter'), 3372c066a59SGreg Roach 'U' => I18N::translate('Burial of a child'), 3382c066a59SGreg Roach ], 3392c066a59SGreg Roach 'INDI:CREM' => [ 3402c066a59SGreg Roach 'M' => I18N::translate('Cremation of a son'), 3412c066a59SGreg Roach 'F' => I18N::translate('Cremation of a daughter'), 3422c066a59SGreg Roach 'U' => I18N::translate('Cremation of a child'), 3432c066a59SGreg Roach ], 3442c066a59SGreg Roach ]; 3452c066a59SGreg Roach 3462c066a59SGreg Roach $death_of_a_sibling = [ 3472c066a59SGreg Roach 'INDI:DEAT' => [ 3482c066a59SGreg Roach 'M' => I18N::translate('Death of a brother'), 3492c066a59SGreg Roach 'F' => I18N::translate('Death of a sister'), 3502c066a59SGreg Roach 'U' => I18N::translate('Death of a sibling'), 3512c066a59SGreg Roach ], 3522c066a59SGreg Roach 'INDI:BURI' => [ 3532c066a59SGreg Roach 'M' => I18N::translate('Burial of a brother'), 3542c066a59SGreg Roach 'F' => I18N::translate('Burial of a sister'), 3552c066a59SGreg Roach 'U' => I18N::translate('Burial of a sibling'), 3562c066a59SGreg Roach ], 3572c066a59SGreg Roach 'INDI:CREM' => [ 3582c066a59SGreg Roach 'M' => I18N::translate('Cremation of a brother'), 3592c066a59SGreg Roach 'F' => I18N::translate('Cremation of a sister'), 3602c066a59SGreg Roach 'U' => I18N::translate('Cremation of a sibling'), 3612c066a59SGreg Roach ], 3622c066a59SGreg Roach ]; 3632c066a59SGreg Roach 3642c066a59SGreg Roach $death_of_a_half_sibling = [ 3652c066a59SGreg Roach 'INDI:DEAT' => [ 3662c066a59SGreg Roach 'M' => I18N::translate('Death of a half-brother'), 3672c066a59SGreg Roach 'F' => I18N::translate('Death of a half-sister'), 3682c066a59SGreg Roach 'U' => I18N::translate('Death of a half-sibling'), 3692c066a59SGreg Roach ], 3702c066a59SGreg Roach 'INDI:BURI' => [ 3712c066a59SGreg Roach 'M' => I18N::translate('Burial of a half-brother'), 3722c066a59SGreg Roach 'F' => I18N::translate('Burial of a half-sister'), 3732c066a59SGreg Roach 'U' => I18N::translate('Burial of a half-sibling'), 3742c066a59SGreg Roach ], 3752c066a59SGreg Roach 'INDI:CREM' => [ 3762c066a59SGreg Roach 'M' => I18N::translate('Cremation of a half-brother'), 3772c066a59SGreg Roach 'F' => I18N::translate('Cremation of a half-sister'), 3782c066a59SGreg Roach 'U' => I18N::translate('Cremation of a half-sibling'), 3792c066a59SGreg Roach ], 3802c066a59SGreg Roach ]; 3812c066a59SGreg Roach 3822c066a59SGreg Roach $death_of_a_grandchild = [ 3832c066a59SGreg Roach 'INDI:DEAT' => [ 3842c066a59SGreg Roach 'M' => I18N::translate('Death of a grandson'), 3852c066a59SGreg Roach 'F' => I18N::translate('Death of a granddaughter'), 3862c066a59SGreg Roach 'U' => I18N::translate('Death of a grandchild'), 3872c066a59SGreg Roach ], 3882c066a59SGreg Roach 'INDI:BURI' => [ 3892c066a59SGreg Roach 'M' => I18N::translate('Burial of a grandson'), 3902c066a59SGreg Roach 'F' => I18N::translate('Burial of a granddaughter'), 3912c066a59SGreg Roach 'U' => I18N::translate('Burial of a grandchild'), 3922c066a59SGreg Roach ], 3932c066a59SGreg Roach 'INDI:CREM' => [ 3942c066a59SGreg Roach 'M' => I18N::translate('Cremation of a grandson'), 3952c066a59SGreg Roach 'F' => I18N::translate('Cremation of a granddaughter'), 3962c066a59SGreg Roach 'U' => I18N::translate('Baptism of a grandchild'), 3972c066a59SGreg Roach ], 3982c066a59SGreg Roach ]; 3992c066a59SGreg Roach 4002c066a59SGreg Roach $death_of_a_grandchild1 = [ 4012c066a59SGreg Roach 'INDI:DEAT' => [ 4022c066a59SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Death of a grandson'), 4032c066a59SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Death of a granddaughter'), 4042c066a59SGreg Roach 'U' => I18N::translate('Death of a grandchild'), 4052c066a59SGreg Roach ], 4062c066a59SGreg Roach 'INDI:BURI' => [ 4072c066a59SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Burial of a grandson'), 4082c066a59SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Burial of a granddaughter'), 4092c066a59SGreg Roach 'U' => I18N::translate('Burial of a grandchild'), 4102c066a59SGreg Roach ], 4112c066a59SGreg Roach 'INDI:CREM' => [ 4122c066a59SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Cremation of a grandson'), 4132c066a59SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Cremation of a granddaughter'), 4142c066a59SGreg Roach 'U' => I18N::translate('Baptism of a grandchild'), 4152c066a59SGreg Roach ], 4162c066a59SGreg Roach ]; 4172c066a59SGreg Roach 4182c066a59SGreg Roach $death_of_a_grandchild2 = [ 4192c066a59SGreg Roach 'INDI:DEAT' => [ 4202c066a59SGreg Roach 'M' => I18N::translateContext('son’s son', 'Death of a grandson'), 4212c066a59SGreg Roach 'F' => I18N::translateContext('son’s daughter', 'Death of a granddaughter'), 4222c066a59SGreg Roach 'U' => I18N::translate('Death of a grandchild'), 4232c066a59SGreg Roach ], 4242c066a59SGreg Roach 'INDI:BURI' => [ 4252c066a59SGreg Roach 'M' => I18N::translateContext('son’s son', 'Burial of a grandson'), 4262c066a59SGreg Roach 'F' => I18N::translateContext('son’s daughter', 'Burial of a granddaughter'), 4272c066a59SGreg Roach 'U' => I18N::translate('Burial of a grandchild'), 4282c066a59SGreg Roach ], 4292c066a59SGreg Roach 'INDI:CREM' => [ 4302c066a59SGreg Roach 'M' => I18N::translateContext('son’s son', 'Cremation of a grandson'), 4312c066a59SGreg Roach 'F' => I18N::translateContext('son’s daughter', 'Cremation of a granddaughter'), 4322c066a59SGreg Roach 'U' => I18N::translate('Cremation of a grandchild'), 4332c066a59SGreg Roach ], 4342c066a59SGreg Roach ]; 4352c066a59SGreg Roach 4362c066a59SGreg Roach $marriage_of_a_child = [ 4372c066a59SGreg Roach 'M' => I18N::translate('Marriage of a son'), 4382c066a59SGreg Roach 'F' => I18N::translate('Marriage of a daughter'), 4392c066a59SGreg Roach 'U' => I18N::translate('Marriage of a child'), 4402c066a59SGreg Roach ]; 4412c066a59SGreg Roach 4422c066a59SGreg Roach $marriage_of_a_grandchild = [ 4432c066a59SGreg Roach 'M' => I18N::translate('Marriage of a grandson'), 4442c066a59SGreg Roach 'F' => I18N::translate('Marriage of a granddaughter'), 4452c066a59SGreg Roach 'U' => I18N::translate('Marriage of a grandchild'), 4462c066a59SGreg Roach ]; 4472c066a59SGreg Roach 4482c066a59SGreg Roach $marriage_of_a_grandchild1 = [ 4492c066a59SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Marriage of a grandson'), 4502c066a59SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Marriage of a granddaughter'), 4512c066a59SGreg Roach 'U' => I18N::translate('Marriage of a grandchild'), 4522c066a59SGreg Roach ]; 4532c066a59SGreg Roach 4542c066a59SGreg Roach $marriage_of_a_grandchild2 = [ 4552c066a59SGreg Roach 'M' => I18N::translateContext('son’s son', 'Marriage of a grandson'), 4562c066a59SGreg Roach 'F' => I18N::translateContext('son’s daughter', 'Marriage of a granddaughter'), 4572c066a59SGreg Roach 'U' => I18N::translate('Marriage of a grandchild'), 4582c066a59SGreg Roach ]; 4592c066a59SGreg Roach 4602c066a59SGreg Roach $marriage_of_a_sibling = [ 4612c066a59SGreg Roach 'M' => I18N::translate('Marriage of a brother'), 4622c066a59SGreg Roach 'F' => I18N::translate('Marriage of a sister'), 4632c066a59SGreg Roach 'U' => I18N::translate('Marriage of a sibling'), 4642c066a59SGreg Roach ]; 4652c066a59SGreg Roach 4662c066a59SGreg Roach $marriage_of_a_half_sibling = [ 4672c066a59SGreg Roach 'M' => I18N::translate('Marriage of a half-brother'), 4682c066a59SGreg Roach 'F' => I18N::translate('Marriage of a half-sister'), 4692c066a59SGreg Roach 'U' => I18N::translate('Marriage of a half-sibling'), 4702c066a59SGreg Roach ]; 4712c066a59SGreg Roach 4722c066a59SGreg Roach $facts = new Collection(); 4732c066a59SGreg Roach 4742c066a59SGreg Roach // Deal with recursion. 4752c066a59SGreg Roach if ($option === '_CHIL') { 4762c066a59SGreg Roach // Add grandchildren 4772c066a59SGreg Roach foreach ($family->children() as $child) { 4782c066a59SGreg Roach foreach ($child->spouseFamilies() as $cfamily) { 4792c066a59SGreg Roach switch ($child->sex()) { 4802c066a59SGreg Roach case 'M': 4812c066a59SGreg Roach foreach ($this->childFacts($person, $cfamily, '_GCHI', 'son', $min_date, $max_date) as $fact) { 4822c066a59SGreg Roach $facts[] = $fact; 4832c066a59SGreg Roach } 4842c066a59SGreg Roach break; 4852c066a59SGreg Roach case 'F': 4862c066a59SGreg Roach foreach ($this->childFacts($person, $cfamily, '_GCHI', 'dau', $min_date, $max_date) as $fact) { 4872c066a59SGreg Roach $facts[] = $fact; 4882c066a59SGreg Roach } 4892c066a59SGreg Roach break; 4902c066a59SGreg Roach default: 4912c066a59SGreg Roach foreach ($this->childFacts($person, $cfamily, '_GCHI', 'chi', $min_date, $max_date) as $fact) { 4922c066a59SGreg Roach $facts[] = $fact; 4932c066a59SGreg Roach } 4942c066a59SGreg Roach break; 4952c066a59SGreg Roach } 4962c066a59SGreg Roach } 4972c066a59SGreg Roach } 4982c066a59SGreg Roach } 4992c066a59SGreg Roach 5002c066a59SGreg Roach // For each child in the family 5012c066a59SGreg Roach foreach ($family->children() as $child) { 5022c066a59SGreg Roach if ($child->xref() === $person->xref()) { 5032c066a59SGreg Roach // We are not our own sibling! 5042c066a59SGreg Roach continue; 5052c066a59SGreg Roach } 5062c066a59SGreg Roach // add child’s birth 5072c066a59SGreg Roach if (str_contains($SHOW_RELATIVES_EVENTS, '_BIRT' . str_replace('_HSIB', '_SIBL', $option))) { 5082c066a59SGreg Roach foreach ($child->facts(['BIRT', 'CHR', 'BAPM', 'ADOP']) as $fact) { 5092c066a59SGreg Roach // Always show _BIRT_CHIL, even if the dates are not known 5102c066a59SGreg Roach if ($option === '_CHIL' || $this->includeFact($fact, $min_date, $max_date)) { 5112c066a59SGreg Roach switch ($option) { 5122c066a59SGreg Roach case '_GCHI': 5132c066a59SGreg Roach switch ($relation) { 5142c066a59SGreg Roach case 'dau': 5152c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $birth_of_a_grandchild1[$fact->tag()], $fact->record()->sex()); 5162c066a59SGreg Roach break; 5172c066a59SGreg Roach case 'son': 5182c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $birth_of_a_grandchild2[$fact->tag()], $fact->record()->sex()); 5192c066a59SGreg Roach break; 5202c066a59SGreg Roach case 'chil': 5212c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $birth_of_a_grandchild[$fact->tag()], $fact->record()->sex()); 5222c066a59SGreg Roach break; 5232c066a59SGreg Roach } 5242c066a59SGreg Roach break; 5252c066a59SGreg Roach case '_SIBL': 5262c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $birth_of_a_sibling[$fact->tag()], $fact->record()->sex()); 5272c066a59SGreg Roach break; 5282c066a59SGreg Roach case '_HSIB': 5292c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $birth_of_a_half_sibling[$fact->tag()], $fact->record()->sex()); 5302c066a59SGreg Roach break; 5312c066a59SGreg Roach case '_CHIL': 5322c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $birth_of_a_child[$fact->tag()], $fact->record()->sex()); 5332c066a59SGreg Roach break; 5342c066a59SGreg Roach } 5352c066a59SGreg Roach } 5362c066a59SGreg Roach } 5372c066a59SGreg Roach } 5382c066a59SGreg Roach // add child’s death 5392c066a59SGreg Roach if (str_contains($SHOW_RELATIVES_EVENTS, '_DEAT' . str_replace('_HSIB', '_SIBL', $option))) { 5402c066a59SGreg Roach foreach ($child->facts(['DEAT', 'BURI', 'CREM']) as $fact) { 5412c066a59SGreg Roach if ($this->includeFact($fact, $min_date, $max_date)) { 5422c066a59SGreg Roach switch ($option) { 5432c066a59SGreg Roach case '_GCHI': 5442c066a59SGreg Roach switch ($relation) { 5452c066a59SGreg Roach case 'dau': 5462c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_grandchild1[$fact->tag()], $fact->record()->sex()); 5472c066a59SGreg Roach break; 5482c066a59SGreg Roach case 'son': 5492c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_grandchild2[$fact->tag()], $fact->record()->sex()); 5502c066a59SGreg Roach break; 5512c066a59SGreg Roach case 'chi': 5522c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_grandchild[$fact->tag()], $fact->record()->sex()); 5532c066a59SGreg Roach break; 5542c066a59SGreg Roach } 5552c066a59SGreg Roach break; 5562c066a59SGreg Roach case '_SIBL': 5572c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_sibling[$fact->tag()], $fact->record()->sex()); 5582c066a59SGreg Roach break; 5592c066a59SGreg Roach case '_HSIB': 5602c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_half_sibling[$fact->tag()], $fact->record()->sex()); 5612c066a59SGreg Roach break; 5622c066a59SGreg Roach case '_CHIL': 5632c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_child[$fact->tag()], $fact->record()->sex()); 5642c066a59SGreg Roach break; 5652c066a59SGreg Roach } 5662c066a59SGreg Roach } 5672c066a59SGreg Roach } 5682c066a59SGreg Roach } 5692c066a59SGreg Roach 5702c066a59SGreg Roach // add child’s marriage 5712c066a59SGreg Roach if (str_contains($SHOW_RELATIVES_EVENTS, '_MARR' . str_replace('_HSIB', '_SIBL', $option))) { 5722c066a59SGreg Roach foreach ($child->spouseFamilies() as $sfamily) { 5732c066a59SGreg Roach foreach ($sfamily->facts(['MARR']) as $fact) { 5742c066a59SGreg Roach if ($this->includeFact($fact, $min_date, $max_date)) { 5752c066a59SGreg Roach switch ($option) { 5762c066a59SGreg Roach case '_GCHI': 5772c066a59SGreg Roach switch ($relation) { 5782c066a59SGreg Roach case 'dau': 5792c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $marriage_of_a_grandchild1, $child->sex()); 5802c066a59SGreg Roach break; 5812c066a59SGreg Roach case 'son': 5822c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $marriage_of_a_grandchild2, $child->sex()); 5832c066a59SGreg Roach break; 5842c066a59SGreg Roach case 'chi': 5852c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $marriage_of_a_grandchild, $child->sex()); 5862c066a59SGreg Roach break; 5872c066a59SGreg Roach } 5882c066a59SGreg Roach break; 5892c066a59SGreg Roach case '_SIBL': 5902c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $marriage_of_a_sibling, $child->sex()); 5912c066a59SGreg Roach break; 5922c066a59SGreg Roach case '_HSIB': 5932c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $marriage_of_a_half_sibling, $child->sex()); 5942c066a59SGreg Roach break; 5952c066a59SGreg Roach case '_CHIL': 5962c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $marriage_of_a_child, $child->sex()); 5972c066a59SGreg Roach break; 5982c066a59SGreg Roach } 5992c066a59SGreg Roach } 6002c066a59SGreg Roach } 6012c066a59SGreg Roach } 6022c066a59SGreg Roach } 6032c066a59SGreg Roach } 6042c066a59SGreg Roach 6052c066a59SGreg Roach return $facts; 6062c066a59SGreg Roach } 6072c066a59SGreg Roach 6082c066a59SGreg Roach /** 6092c066a59SGreg Roach * Get the events of parents and grandparents. 6102c066a59SGreg Roach * 6112c066a59SGreg Roach * @param Individual $person 6122c066a59SGreg Roach * @param int $sosa 6132c066a59SGreg Roach * @param Date $min_date 6142c066a59SGreg Roach * @param Date $max_date 6152c066a59SGreg Roach * 6162c066a59SGreg Roach * @return Collection<int,Fact> 6172c066a59SGreg Roach */ 6182c066a59SGreg Roach private function parentFacts(Individual $person, int $sosa, Date $min_date, Date $max_date): Collection 6192c066a59SGreg Roach { 6202c066a59SGreg Roach $SHOW_RELATIVES_EVENTS = $person->tree()->getPreference('SHOW_RELATIVES_EVENTS'); 6212c066a59SGreg Roach 6222c066a59SGreg Roach $death_of_a_parent = [ 6232c066a59SGreg Roach 'INDI:DEAT' => [ 6242c066a59SGreg Roach 'M' => I18N::translate('Death of a father'), 6252c066a59SGreg Roach 'F' => I18N::translate('Death of a mother'), 6262c066a59SGreg Roach 'U' => I18N::translate('Death of a parent'), 6272c066a59SGreg Roach ], 6282c066a59SGreg Roach 'INDI:BURI' => [ 6292c066a59SGreg Roach 'M' => I18N::translate('Burial of a father'), 6302c066a59SGreg Roach 'F' => I18N::translate('Burial of a mother'), 6312c066a59SGreg Roach 'U' => I18N::translate('Burial of a parent'), 6322c066a59SGreg Roach ], 6332c066a59SGreg Roach 'INDI:CREM' => [ 6342c066a59SGreg Roach 'M' => I18N::translate('Cremation of a father'), 6352c066a59SGreg Roach 'F' => I18N::translate('Cremation of a mother'), 6362c066a59SGreg Roach 'U' => I18N::translate('Cremation of a parent'), 6372c066a59SGreg Roach ], 6382c066a59SGreg Roach ]; 6392c066a59SGreg Roach 6402c066a59SGreg Roach $death_of_a_grandparent = [ 6412c066a59SGreg Roach 'INDI:DEAT' => [ 6422c066a59SGreg Roach 'M' => I18N::translate('Death of a grandfather'), 6432c066a59SGreg Roach 'F' => I18N::translate('Death of a grandmother'), 6442c066a59SGreg Roach 'U' => I18N::translate('Death of a grandparent'), 6452c066a59SGreg Roach ], 6462c066a59SGreg Roach 'INDI:BURI' => [ 6472c066a59SGreg Roach 'M' => I18N::translate('Burial of a grandfather'), 6482c066a59SGreg Roach 'F' => I18N::translate('Burial of a grandmother'), 6492c066a59SGreg Roach 'U' => I18N::translate('Burial of a grandparent'), 6502c066a59SGreg Roach ], 6512c066a59SGreg Roach 'INDI:CREM' => [ 6522c066a59SGreg Roach 'M' => I18N::translate('Cremation of a grandfather'), 6532c066a59SGreg Roach 'F' => I18N::translate('Cremation of a grandmother'), 6542c066a59SGreg Roach 'U' => I18N::translate('Cremation of a grandparent'), 6552c066a59SGreg Roach ], 6562c066a59SGreg Roach ]; 6572c066a59SGreg Roach 6582c066a59SGreg Roach $death_of_a_maternal_grandparent = [ 6592c066a59SGreg Roach 'INDI:DEAT' => [ 6602c066a59SGreg Roach 'M' => I18N::translate('Death of a maternal grandfather'), 6612c066a59SGreg Roach 'F' => I18N::translate('Death of a maternal grandmother'), 6622c066a59SGreg Roach 'U' => I18N::translate('Death of a grandparent'), 6632c066a59SGreg Roach ], 6642c066a59SGreg Roach 'INDI:BURI' => [ 6652c066a59SGreg Roach 'M' => I18N::translate('Burial of a maternal grandfather'), 6662c066a59SGreg Roach 'F' => I18N::translate('Burial of a maternal grandmother'), 6672c066a59SGreg Roach 'U' => I18N::translate('Burial of a grandparent'), 6682c066a59SGreg Roach ], 6692c066a59SGreg Roach 'INDI:CREM' => [ 6702c066a59SGreg Roach 'M' => I18N::translate('Cremation of a maternal grandfather'), 6712c066a59SGreg Roach 'F' => I18N::translate('Cremation of a maternal grandmother'), 6722c066a59SGreg Roach 'U' => I18N::translate('Cremation of a grandparent'), 6732c066a59SGreg Roach ], 6742c066a59SGreg Roach ]; 6752c066a59SGreg Roach 6762c066a59SGreg Roach $death_of_a_paternal_grandparent = [ 6772c066a59SGreg Roach 'INDI:DEAT' => [ 6782c066a59SGreg Roach 'M' => I18N::translate('Death of a paternal grandfather'), 6792c066a59SGreg Roach 'F' => I18N::translate('Death of a paternal grandmother'), 6802c066a59SGreg Roach 'U' => I18N::translate('Death of a grandparent'), 6812c066a59SGreg Roach ], 6822c066a59SGreg Roach 'INDI:BURI' => [ 6832c066a59SGreg Roach 'M' => I18N::translate('Burial of a paternal grandfather'), 6842c066a59SGreg Roach 'F' => I18N::translate('Burial of a paternal grandmother'), 6852c066a59SGreg Roach 'U' => I18N::translate('Burial of a grandparent'), 6862c066a59SGreg Roach ], 6872c066a59SGreg Roach 'INDI:CREM' => [ 6882c066a59SGreg Roach 'M' => I18N::translate('Cremation of a paternal grandfather'), 6892c066a59SGreg Roach 'F' => I18N::translate('Cremation of a paternal grandmother'), 6902c066a59SGreg Roach 'U' => I18N::translate('Cremation of a grandparent'), 6912c066a59SGreg Roach ], 6922c066a59SGreg Roach ]; 6932c066a59SGreg Roach 6942c066a59SGreg Roach $marriage_of_a_parent = [ 6952c066a59SGreg Roach 'M' => I18N::translate('Marriage of a father'), 6962c066a59SGreg Roach 'F' => I18N::translate('Marriage of a mother'), 6972c066a59SGreg Roach 'U' => I18N::translate('Marriage of a parent'), 6982c066a59SGreg Roach ]; 6992c066a59SGreg Roach 7002c066a59SGreg Roach $facts = new Collection(); 7012c066a59SGreg Roach 7022c066a59SGreg Roach if ($sosa === 1) { 7032c066a59SGreg Roach foreach ($person->childFamilies() as $family) { 7042c066a59SGreg Roach // Add siblings 7052c066a59SGreg Roach foreach ($this->childFacts($person, $family, '_SIBL', '', $min_date, $max_date) as $fact) { 7062c066a59SGreg Roach $facts[] = $fact; 7072c066a59SGreg Roach } 7082c066a59SGreg Roach foreach ($family->spouses() as $spouse) { 7092c066a59SGreg Roach foreach ($spouse->spouseFamilies() as $sfamily) { 7102c066a59SGreg Roach if ($family !== $sfamily) { 7112c066a59SGreg Roach // Add half-siblings 7122c066a59SGreg Roach foreach ($this->childFacts($person, $sfamily, '_HSIB', '', $min_date, $max_date) as $fact) { 7132c066a59SGreg Roach $facts[] = $fact; 7142c066a59SGreg Roach } 7152c066a59SGreg Roach } 7162c066a59SGreg Roach } 7172c066a59SGreg Roach // Add grandparents 7182c066a59SGreg Roach foreach ($this->parentFacts($spouse, $spouse->sex() === 'F' ? 3 : 2, $min_date, $max_date) as $fact) { 7192c066a59SGreg Roach $facts[] = $fact; 7202c066a59SGreg Roach } 7212c066a59SGreg Roach } 7222c066a59SGreg Roach } 7232c066a59SGreg Roach 7242c066a59SGreg Roach if (str_contains($SHOW_RELATIVES_EVENTS, '_MARR_PARE')) { 7252c066a59SGreg Roach // add father/mother marriages 7262c066a59SGreg Roach foreach ($person->childFamilies() as $sfamily) { 7272c066a59SGreg Roach foreach ($sfamily->facts(['MARR']) as $fact) { 7282c066a59SGreg Roach if ($this->includeFact($fact, $min_date, $max_date)) { 7292c066a59SGreg Roach // marriage of parents (to each other) 7302c066a59SGreg Roach $facts[] = $this->convertEvent($fact, ['U' => I18N::translate('Marriage of parents')], 'U'); 7312c066a59SGreg Roach } 7322c066a59SGreg Roach } 7332c066a59SGreg Roach } 7342c066a59SGreg Roach foreach ($person->childStepFamilies() as $sfamily) { 7352c066a59SGreg Roach foreach ($sfamily->facts(['MARR']) as $fact) { 7362c066a59SGreg Roach if ($this->includeFact($fact, $min_date, $max_date)) { 7372c066a59SGreg Roach // marriage of a parent (to another spouse) 7382c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $marriage_of_a_parent, 'U'); 7392c066a59SGreg Roach } 7402c066a59SGreg Roach } 7412c066a59SGreg Roach } 7422c066a59SGreg Roach } 7432c066a59SGreg Roach } 7442c066a59SGreg Roach 7452c066a59SGreg Roach foreach ($person->childFamilies() as $family) { 7462c066a59SGreg Roach foreach ($family->spouses() as $parent) { 7472c066a59SGreg Roach if (str_contains($SHOW_RELATIVES_EVENTS, '_DEAT' . ($sosa === 1 ? '_PARE' : '_GPAR'))) { 7482c066a59SGreg Roach foreach ($parent->facts(['DEAT', 'BURI', 'CREM']) as $fact) { 7492c066a59SGreg Roach // Show death of parent when it happened prior to birth 7502c066a59SGreg Roach if ($sosa === 1 && Date::compare($fact->date(), $min_date) < 0 || $this->includeFact($fact, $min_date, $max_date)) { 7512c066a59SGreg Roach switch ($sosa) { 7522c066a59SGreg Roach case 1: 7532c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_parent[$fact->tag()], $fact->record()->sex()); 7542c066a59SGreg Roach break; 7552c066a59SGreg Roach case 2: 7562c066a59SGreg Roach case 3: 7572c066a59SGreg Roach switch ($person->sex()) { 7582c066a59SGreg Roach case 'M': 7592c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_paternal_grandparent[$fact->tag()], $fact->record()->sex()); 7602c066a59SGreg Roach break; 7612c066a59SGreg Roach case 'F': 7622c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_maternal_grandparent[$fact->tag()], $fact->record()->sex()); 7632c066a59SGreg Roach break; 7642c066a59SGreg Roach default: 7652c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_grandparent[$fact->tag()], $fact->record()->sex()); 7662c066a59SGreg Roach break; 7672c066a59SGreg Roach } 7682c066a59SGreg Roach } 7692c066a59SGreg Roach } 7702c066a59SGreg Roach } 7712c066a59SGreg Roach } 7722c066a59SGreg Roach } 7732c066a59SGreg Roach } 7742c066a59SGreg Roach 7752c066a59SGreg Roach return $facts; 7762c066a59SGreg Roach } 7772c066a59SGreg Roach 7782c066a59SGreg Roach /** 7792c066a59SGreg Roach * Spouse facts that are shown on an individual’s page. 7802c066a59SGreg Roach * 7812c066a59SGreg Roach * @param Individual $individual Show events that occurred during the lifetime of this individual 7822c066a59SGreg Roach * @param Individual $spouse Show events of this individual 7832c066a59SGreg Roach * @param Date $min_date 7842c066a59SGreg Roach * @param Date $max_date 7852c066a59SGreg Roach * 7862c066a59SGreg Roach * @return Collection<int,Fact> 7872c066a59SGreg Roach */ 7882c066a59SGreg Roach private function spouseFacts(Individual $individual, Individual $spouse, Date $min_date, Date $max_date): Collection 7892c066a59SGreg Roach { 7902c066a59SGreg Roach $SHOW_RELATIVES_EVENTS = $individual->tree()->getPreference('SHOW_RELATIVES_EVENTS'); 7912c066a59SGreg Roach 7922c066a59SGreg Roach $death_of_a_spouse = [ 7932c066a59SGreg Roach 'INDI:DEAT' => [ 7942c066a59SGreg Roach 'M' => I18N::translate('Death of a husband'), 7952c066a59SGreg Roach 'F' => I18N::translate('Death of a wife'), 7962c066a59SGreg Roach 'U' => I18N::translate('Death of a spouse'), 7972c066a59SGreg Roach ], 7982c066a59SGreg Roach 'INDI:BURI' => [ 7992c066a59SGreg Roach 'M' => I18N::translate('Burial of a husband'), 8002c066a59SGreg Roach 'F' => I18N::translate('Burial of a wife'), 8012c066a59SGreg Roach 'U' => I18N::translate('Burial of a spouse'), 8022c066a59SGreg Roach ], 8032c066a59SGreg Roach 'INDI:CREM' => [ 8042c066a59SGreg Roach 'M' => I18N::translate('Cremation of a husband'), 8052c066a59SGreg Roach 'F' => I18N::translate('Cremation of a wife'), 8062c066a59SGreg Roach 'U' => I18N::translate('Cremation of a spouse'), 8072c066a59SGreg Roach ], 8082c066a59SGreg Roach ]; 8092c066a59SGreg Roach 8102c066a59SGreg Roach $facts = new Collection(); 8112c066a59SGreg Roach 8122c066a59SGreg Roach if (str_contains($SHOW_RELATIVES_EVENTS, '_DEAT_SPOU')) { 8132c066a59SGreg Roach foreach ($spouse->facts(['DEAT', 'BURI', 'CREM']) as $fact) { 8142c066a59SGreg Roach if ($this->includeFact($fact, $min_date, $max_date)) { 8152c066a59SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_spouse[$fact->tag()], $fact->record()->sex()); 8162c066a59SGreg Roach } 8172c066a59SGreg Roach } 8182c066a59SGreg Roach } 8192c066a59SGreg Roach 8202c066a59SGreg Roach return $facts; 8212c066a59SGreg Roach } 8222c066a59SGreg Roach 8232c066a59SGreg Roach /** 8242c066a59SGreg Roach * Does a relative event occur within a date range (i.e. the individual's lifetime)? 8252c066a59SGreg Roach * 8262c066a59SGreg Roach * @param Fact $fact 8272c066a59SGreg Roach * @param Date $min_date 8282c066a59SGreg Roach * @param Date $max_date 8292c066a59SGreg Roach * 8302c066a59SGreg Roach * @return bool 8312c066a59SGreg Roach */ 8322c066a59SGreg Roach private function includeFact(Fact $fact, Date $min_date, Date $max_date): bool 8332c066a59SGreg Roach { 8342c066a59SGreg Roach $fact_date = $fact->date(); 8352c066a59SGreg Roach 8362c066a59SGreg Roach return $fact_date->isOK() && Date::compare($min_date, $fact_date) <= 0 && Date::compare($fact_date, $max_date) <= 0; 8372c066a59SGreg Roach } 8382c066a59SGreg Roach 8392c066a59SGreg Roach /** 8402c066a59SGreg Roach * Convert an event into a special "event of a close relative". 8412c066a59SGreg Roach * 8422c066a59SGreg Roach * @param Fact $fact 8432c066a59SGreg Roach * @param array<string> $types 8442c066a59SGreg Roach * @param string $sex 8452c066a59SGreg Roach * 8462c066a59SGreg Roach * @return Fact 8472c066a59SGreg Roach */ 8482c066a59SGreg Roach private function convertEvent(Fact $fact, array $types, string $sex): Fact 8492c066a59SGreg Roach { 8502c066a59SGreg Roach $type = $types[$sex] ?? $types['U']; 8512c066a59SGreg Roach 8522c066a59SGreg Roach $gedcom = $fact->gedcom(); 8532c066a59SGreg Roach $gedcom = preg_replace('/\n2 TYPE .*/', '', $gedcom); 8542c066a59SGreg Roach $gedcom = preg_replace('/^1 .*/', "1 EVEN CLOSE_RELATIVE\n2 TYPE " . $type, $gedcom); 8552c066a59SGreg Roach 8562c066a59SGreg Roach $converted = new Fact($gedcom, $fact->record(), $fact->id()); 8572c066a59SGreg Roach 8582c066a59SGreg Roach if ($fact->isPendingAddition()) { 8592c066a59SGreg Roach $converted->setPendingAddition(); 8602c066a59SGreg Roach } 8612c066a59SGreg Roach 8622c066a59SGreg Roach if ($fact->isPendingDeletion()) { 8632c066a59SGreg Roach $converted->setPendingDeletion(); 8642c066a59SGreg Roach } 8652c066a59SGreg Roach 8662c066a59SGreg Roach return $converted; 8672c066a59SGreg Roach } 8682c066a59SGreg Roach} 869