13763c3f2SGreg Roach<?php 23976b470SGreg Roach 33763c3f2SGreg Roach/** 43763c3f2SGreg Roach * webtrees: online genealogy 57fe676e5SGreg Roach * Copyright (C) 2020 webtrees development team 63763c3f2SGreg Roach * This program is free software: you can redistribute it and/or modify 73763c3f2SGreg Roach * it under the terms of the GNU General Public License as published by 83763c3f2SGreg Roach * the Free Software Foundation, either version 3 of the License, or 93763c3f2SGreg Roach * (at your option) any later version. 103763c3f2SGreg Roach * This program is distributed in the hope that it will be useful, 113763c3f2SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 123763c3f2SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 133763c3f2SGreg Roach * GNU General Public License for more details. 143763c3f2SGreg Roach * You should have received a copy of the GNU General Public License 153763c3f2SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>. 163763c3f2SGreg Roach */ 17fcfa147eSGreg Roach 18e7f56f2aSGreg Roachdeclare(strict_types=1); 19e7f56f2aSGreg Roach 2076692c8bSGreg Roachnamespace Fisharebest\Webtrees\Module; 2176692c8bSGreg Roach 2263276d8fSGreg Roachuse Fisharebest\Webtrees\Auth; 230e62c4b8SGreg Roachuse Fisharebest\Webtrees\Date; 240e62c4b8SGreg Roachuse Fisharebest\Webtrees\Fact; 250e62c4b8SGreg Roachuse Fisharebest\Webtrees\Family; 268d0ebef0SGreg Roachuse Fisharebest\Webtrees\Gedcom; 270e62c4b8SGreg Roachuse Fisharebest\Webtrees\I18N; 280e62c4b8SGreg Roachuse Fisharebest\Webtrees\Individual; 292adcbd9aSGreg Roachuse Fisharebest\Webtrees\Services\ClipboardService; 304ca7e03cSGreg Roachuse Fisharebest\Webtrees\Services\ModuleService; 3117c50b57SGreg Roachuse Illuminate\Support\Collection; 323763c3f2SGreg Roach 333763c3f2SGreg Roach/** 343763c3f2SGreg Roach * Class IndividualFactsTabModule 353763c3f2SGreg Roach */ 3637eb8894SGreg Roachclass IndividualFactsTabModule extends AbstractModule implements ModuleTabInterface 37c1010edaSGreg Roach{ 3849a243cbSGreg Roach use ModuleTabTrait; 3949a243cbSGreg Roach 402adcbd9aSGreg Roach /** @var ModuleService */ 414ca7e03cSGreg Roach private $module_service; 424ca7e03cSGreg Roach 432adcbd9aSGreg Roach /** @var ClipboardService */ 442adcbd9aSGreg Roach private $clipboard_service; 452adcbd9aSGreg Roach 464ca7e03cSGreg Roach /** 474ca7e03cSGreg Roach * UserWelcomeModule constructor. 484ca7e03cSGreg Roach * 494ca7e03cSGreg Roach * @param ModuleService $module_service 502adcbd9aSGreg Roach * @param ClipboardService $clipboard_service 514ca7e03cSGreg Roach */ 522adcbd9aSGreg Roach public function __construct(ModuleService $module_service, ClipboardService $clipboard_service) 535bdbe281SGreg Roach { 544ca7e03cSGreg Roach $this->module_service = $module_service; 552adcbd9aSGreg Roach $this->clipboard_service = $clipboard_service; 564ca7e03cSGreg Roach } 574ca7e03cSGreg Roach 584ca7e03cSGreg Roach /** 590cfd6963SGreg Roach * How should this module be identified in the control panel, etc.? 60961ec755SGreg Roach * 61961ec755SGreg Roach * @return string 62961ec755SGreg Roach */ 6349a243cbSGreg Roach public function title(): string 64c1010edaSGreg Roach { 65bbb76c12SGreg Roach /* I18N: Name of a module/tab on the individual page. */ 66bbb76c12SGreg Roach return I18N::translate('Facts and events'); 673763c3f2SGreg Roach } 683763c3f2SGreg Roach 69961ec755SGreg Roach /** 70961ec755SGreg Roach * A sentence describing what this module does. 71961ec755SGreg Roach * 72961ec755SGreg Roach * @return string 73961ec755SGreg Roach */ 7449a243cbSGreg Roach public function description(): string 75c1010edaSGreg Roach { 76bbb76c12SGreg Roach /* I18N: Description of the “Facts and events” module */ 77bbb76c12SGreg Roach return I18N::translate('A tab showing the facts and events of an individual.'); 783763c3f2SGreg Roach } 793763c3f2SGreg Roach 8049a243cbSGreg Roach /** 8149a243cbSGreg Roach * The default position for this tab. It can be changed in the control panel. 8249a243cbSGreg Roach * 8349a243cbSGreg Roach * @return int 8449a243cbSGreg Roach */ 85cbf4b7faSGreg Roach public function defaultTabOrder(): int 86cbf4b7faSGreg Roach { 87fb7a0427SGreg Roach return 1; 883763c3f2SGreg Roach } 893763c3f2SGreg Roach 903caaa4d2SGreg Roach /** 913caaa4d2SGreg Roach * A greyed out tab has no actual content, but may perhaps have 923caaa4d2SGreg Roach * options to create content. 933caaa4d2SGreg Roach * 943caaa4d2SGreg Roach * @param Individual $individual 953caaa4d2SGreg Roach * 963caaa4d2SGreg Roach * @return bool 973caaa4d2SGreg Roach */ 988f53f488SRico Sonntag public function isGrayedOut(Individual $individual): bool 99c1010edaSGreg Roach { 1003763c3f2SGreg Roach return false; 1013763c3f2SGreg Roach } 1023763c3f2SGreg Roach 1033caaa4d2SGreg Roach /** 1043caaa4d2SGreg Roach * Generate the HTML content of this tab. 1053caaa4d2SGreg Roach * 1063caaa4d2SGreg Roach * @param Individual $individual 1073caaa4d2SGreg Roach * 1083caaa4d2SGreg Roach * @return string 1093caaa4d2SGreg Roach */ 1109b34404bSGreg Roach public function getTabContent(Individual $individual): string 111c1010edaSGreg Roach { 112ee727175SGreg Roach // Only include events of close relatives that are between birth and death 113ee727175SGreg Roach $min_date = $individual->getEstimatedBirthDate(); 114ee727175SGreg Roach $max_date = $individual->getEstimatedDeathDate(); 115ee727175SGreg Roach 1168eaf8709SGreg Roach // Which facts and events are handled by other modules? 1178eaf8709SGreg Roach $sidebar_facts = $this->module_service 11887cca37cSGreg Roach ->findByComponent(ModuleSidebarInterface::class, $individual->tree(), Auth::user()) 1190b5fd0a6SGreg Roach ->map(static function (ModuleSidebarInterface $sidebar): Collection { 1208eaf8709SGreg Roach return $sidebar->supportedFacts(); 1218eaf8709SGreg Roach }); 1228eaf8709SGreg Roach 1238eaf8709SGreg Roach $tab_facts = $this->module_service 12487cca37cSGreg Roach ->findByComponent(ModuleTabInterface::class, $individual->tree(), Auth::user()) 1250b5fd0a6SGreg Roach ->map(static function (ModuleTabInterface $sidebar): Collection { 1268eaf8709SGreg Roach return $sidebar->supportedFacts(); 1278eaf8709SGreg Roach }); 1288eaf8709SGreg Roach 1298eaf8709SGreg Roach $exclude_facts = $sidebar_facts->merge($tab_facts)->flatten(); 1308eaf8709SGreg Roach 1313763c3f2SGreg Roach // The individual’s own facts 13239ca88baSGreg Roach $indifacts = $individual->facts() 1330b5fd0a6SGreg Roach ->filter(static function (Fact $fact) use ($exclude_facts): bool { 1347fe676e5SGreg Roach return !$exclude_facts->contains($fact->getTag()); 13539ca88baSGreg Roach }); 1363763c3f2SGreg Roach 1373763c3f2SGreg Roach // Add spouse-family facts 13839ca88baSGreg Roach foreach ($individual->spouseFamilies() as $family) { 13930158ae7SGreg Roach foreach ($family->facts() as $fact) { 1407fe676e5SGreg Roach if (!$exclude_facts->contains($fact->getTag()) && $fact->getTag() !== 'CHAN') { 14139ca88baSGreg Roach $indifacts->push($fact); 1423763c3f2SGreg Roach } 1433763c3f2SGreg Roach } 144ee727175SGreg Roach 14539ca88baSGreg Roach $spouse = $family->spouse($individual); 146ee727175SGreg Roach 147ee727175SGreg Roach if ($spouse instanceof Individual) { 1488b9cfadbSGreg Roach $spouse_facts = $this->spouseFacts($individual, $spouse, $min_date, $max_date); 14939ca88baSGreg Roach $indifacts = $indifacts->merge($spouse_facts); 1503763c3f2SGreg Roach } 1513763c3f2SGreg Roach 1528b9cfadbSGreg Roach $child_facts = $this->childFacts($individual, $family, '_CHIL', '', $min_date, $max_date); 15339ca88baSGreg Roach $indifacts = $indifacts->merge($child_facts); 1543763c3f2SGreg Roach } 155225e381fSGreg Roach 1568b9cfadbSGreg Roach $parent_facts = $this->parentFacts($individual, 1, $min_date, $max_date); 1578b9cfadbSGreg Roach $associate_facts = $this->associateFacts($individual); 1588b9cfadbSGreg Roach $historical_facts = $this->historicalFacts($individual); 159225e381fSGreg Roach 16039ca88baSGreg Roach $indifacts = $indifacts 16139ca88baSGreg Roach ->merge($parent_facts) 16239ca88baSGreg Roach ->merge($associate_facts) 16339ca88baSGreg Roach ->merge($historical_facts); 1643763c3f2SGreg Roach 165580a4d11SGreg Roach $indifacts = Fact::sortFacts($indifacts); 1663763c3f2SGreg Roach 167a8cd57e1SGreg Roach return view('modules/personal_facts/tab', [ 168225e381fSGreg Roach 'can_edit' => $individual->canEdit(), 169*cd233803SGreg Roach 'clipboard_facts' => $this->clipboard_service->pastableFacts($individual, new Collection()), 170ddeb3354SGreg Roach 'has_historical_facts' => $historical_facts !== [], 171225e381fSGreg Roach 'individual' => $individual, 172225e381fSGreg Roach 'facts' => $indifacts, 173225e381fSGreg Roach ]); 1743763c3f2SGreg Roach } 1753763c3f2SGreg Roach 176ee727175SGreg Roach /** 177ee727175SGreg Roach * Does a relative event occur within a date range (i.e. the individual's lifetime)? 178ee727175SGreg Roach * 179ee727175SGreg Roach * @param Fact $fact 180ee727175SGreg Roach * @param Date $min_date 181ee727175SGreg Roach * @param Date $max_date 182ee727175SGreg Roach * 183ee727175SGreg Roach * @return bool 184ee727175SGreg Roach */ 1858b9cfadbSGreg Roach private function includeFact(Fact $fact, Date $min_date, Date $max_date): bool 186b3b1d905SGreg Roach { 1872decada7SGreg Roach $fact_date = $fact->date(); 188ee727175SGreg Roach 189ee727175SGreg Roach return $fact_date->isOK() && Date::compare($min_date, $fact_date) <= 0 && Date::compare($fact_date, $max_date) <= 0; 190ee727175SGreg Roach } 191ee727175SGreg Roach 1923caaa4d2SGreg Roach /** 1933caaa4d2SGreg Roach * Is this tab empty? If so, we don't always need to display it. 1943caaa4d2SGreg Roach * 1953caaa4d2SGreg Roach * @param Individual $individual 1963caaa4d2SGreg Roach * 1973caaa4d2SGreg Roach * @return bool 1983caaa4d2SGreg Roach */ 1998f53f488SRico Sonntag public function hasTabContent(Individual $individual): bool 200c1010edaSGreg Roach { 2013763c3f2SGreg Roach return true; 2023763c3f2SGreg Roach } 2033763c3f2SGreg Roach 2043caaa4d2SGreg Roach /** 2053caaa4d2SGreg Roach * Can this tab load asynchronously? 2063caaa4d2SGreg Roach * 2073caaa4d2SGreg Roach * @return bool 2083caaa4d2SGreg Roach */ 2098f53f488SRico Sonntag public function canLoadAjax(): bool 210c1010edaSGreg Roach { 21115d603e7SGreg Roach return false; 2123763c3f2SGreg Roach } 2133763c3f2SGreg Roach 2143763c3f2SGreg Roach /** 2157bf6ca81SGreg Roach * Convert an event into a special "event of a close relative". 2167bf6ca81SGreg Roach * 2177bf6ca81SGreg Roach * @param Fact $fact 2189e65d053SGreg Roach * @param string $type 2197bf6ca81SGreg Roach * 2207bf6ca81SGreg Roach * @return Fact 2217bf6ca81SGreg Roach */ 2229e65d053SGreg Roach private function convertEvent(Fact $fact, string $type): Fact 22399ed8541SGreg Roach { 2247bf6ca81SGreg Roach $gedcom = $fact->gedcom(); 2257bf6ca81SGreg Roach $gedcom = preg_replace('/\n2 TYPE .*/', '', $gedcom); 2267bf6ca81SGreg Roach $gedcom = preg_replace('/^1 .*/', "1 EVEN CLOSE_RELATIVE\n2 TYPE " . $type, $gedcom); 2277bf6ca81SGreg Roach 2287bf6ca81SGreg Roach return new Fact($gedcom, $fact->record(), $fact->id()); 2297bf6ca81SGreg Roach } 2307bf6ca81SGreg Roach 2317bf6ca81SGreg Roach /** 2323763c3f2SGreg Roach * Spouse facts that are shown on an individual’s page. 2333763c3f2SGreg Roach * 2343763c3f2SGreg Roach * @param Individual $individual Show events that occured during the lifetime of this individual 2353763c3f2SGreg Roach * @param Individual $spouse Show events of this individual 236ee727175SGreg Roach * @param Date $min_date 237ee727175SGreg Roach * @param Date $max_date 2383763c3f2SGreg Roach * 2393763c3f2SGreg Roach * @return Fact[] 2403763c3f2SGreg Roach */ 2418b9cfadbSGreg Roach private function spouseFacts(Individual $individual, Individual $spouse, Date $min_date, Date $max_date): array 242c1010edaSGreg Roach { 243f4afa648SGreg Roach $SHOW_RELATIVES_EVENTS = $individual->tree()->getPreference('SHOW_RELATIVES_EVENTS'); 2443763c3f2SGreg Roach 2457bf6ca81SGreg Roach $death_of_a_spouse = [ 2467bf6ca81SGreg Roach 'DEAT' => [ 2477bf6ca81SGreg Roach 'M' => I18N::translate('Death of a husband'), 2487bf6ca81SGreg Roach 'F' => I18N::translate('Death of a wife'), 2497bf6ca81SGreg Roach 'U' => I18N::translate('Death of a spouse'), 2507bf6ca81SGreg Roach ], 2517bf6ca81SGreg Roach 'BURI' => [ 2527bf6ca81SGreg Roach 'M' => I18N::translate('Burial of a husband'), 2537bf6ca81SGreg Roach 'F' => I18N::translate('Burial of a wife'), 2547bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a spouse'), 2557bf6ca81SGreg Roach ], 2567bf6ca81SGreg Roach 'CREM' => [ 2577bf6ca81SGreg Roach 'M' => I18N::translate('Cremation of a husband'), 2587bf6ca81SGreg Roach 'F' => I18N::translate('Cremation of a wife'), 2597bf6ca81SGreg Roach 'U' => I18N::translate('Cremation of a spouse'), 2607bf6ca81SGreg Roach ], 2617bf6ca81SGreg Roach ]; 2627bf6ca81SGreg Roach 26313abd6f3SGreg Roach $facts = []; 2647bf6ca81SGreg Roach 2657bf6ca81SGreg Roach if (strpos($SHOW_RELATIVES_EVENTS, '_DEAT_SPOU') !== false) { 2667bf6ca81SGreg Roach foreach ($spouse->facts(['DEAT', 'BURI', 'CREM']) as $fact) { 2678b9cfadbSGreg Roach if ($this->includeFact($fact, $min_date, $max_date)) { 2687fe676e5SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_spouse[$fact->getTag()][$fact->record()->sex()]); 2693763c3f2SGreg Roach } 2703763c3f2SGreg Roach } 2713763c3f2SGreg Roach } 2723763c3f2SGreg Roach 2733763c3f2SGreg Roach return $facts; 2743763c3f2SGreg Roach } 2753763c3f2SGreg Roach 2763763c3f2SGreg Roach /** 2773763c3f2SGreg Roach * Get the events of children and grandchildren. 2783763c3f2SGreg Roach * 2793763c3f2SGreg Roach * @param Individual $person 2803763c3f2SGreg Roach * @param Family $family 2813763c3f2SGreg Roach * @param string $option 2823763c3f2SGreg Roach * @param string $relation 283ee727175SGreg Roach * @param Date $min_date 284ee727175SGreg Roach * @param Date $max_date 2853763c3f2SGreg Roach * 2863763c3f2SGreg Roach * @return Fact[] 2873763c3f2SGreg Roach */ 2888b9cfadbSGreg Roach private function childFacts(Individual $person, Family $family, $option, $relation, Date $min_date, Date $max_date): array 289c1010edaSGreg Roach { 290f4afa648SGreg Roach $SHOW_RELATIVES_EVENTS = $person->tree()->getPreference('SHOW_RELATIVES_EVENTS'); 2913763c3f2SGreg Roach 2927bf6ca81SGreg Roach $birth_of_a_child = [ 2937bf6ca81SGreg Roach 'BIRT' => [ 2947bf6ca81SGreg Roach 'M' => I18N::translate('Birth of a son'), 2957bf6ca81SGreg Roach 'F' => I18N::translate('Birth of a daughter'), 2967bf6ca81SGreg Roach 'U' => I18N::translate('Birth of a child'), 2977bf6ca81SGreg Roach ], 2987bf6ca81SGreg Roach 'CHR' => [ 2997bf6ca81SGreg Roach 'M' => I18N::translate('Christening of a son'), 3007bf6ca81SGreg Roach 'F' => I18N::translate('Christening of a daughter'), 3017bf6ca81SGreg Roach 'U' => I18N::translate('Christening of a child'), 3027bf6ca81SGreg Roach ], 3037bf6ca81SGreg Roach 'BAPM' => [ 3047bf6ca81SGreg Roach 'M' => I18N::translate('Baptism of a son'), 3057bf6ca81SGreg Roach 'F' => I18N::translate('Baptism of a daughter'), 3067bf6ca81SGreg Roach 'U' => I18N::translate('Baptism of a child'), 3077bf6ca81SGreg Roach ], 3087bf6ca81SGreg Roach 'ADOP' => [ 3097bf6ca81SGreg Roach 'M' => I18N::translate('Adoption of a son'), 3107bf6ca81SGreg Roach 'F' => I18N::translate('Adoption of a daughter'), 3117bf6ca81SGreg Roach 'U' => I18N::translate('Adoption of a child'), 3127bf6ca81SGreg Roach ], 3137bf6ca81SGreg Roach ]; 3147bf6ca81SGreg Roach 3157bf6ca81SGreg Roach $birth_of_a_sibling = [ 3167bf6ca81SGreg Roach 'BIRT' => [ 3177bf6ca81SGreg Roach 'M' => I18N::translate('Birth of a brother'), 3187bf6ca81SGreg Roach 'F' => I18N::translate('Birth of a sister'), 3197bf6ca81SGreg Roach 'U' => I18N::translate('Birth of a sibling'), 3207bf6ca81SGreg Roach ], 3217bf6ca81SGreg Roach 'CHR' => [ 3227bf6ca81SGreg Roach 'M' => I18N::translate('Christening of a brother'), 3237bf6ca81SGreg Roach 'F' => I18N::translate('Christening of a sister'), 3247bf6ca81SGreg Roach 'U' => I18N::translate('Christening of a sibling'), 3257bf6ca81SGreg Roach ], 3267bf6ca81SGreg Roach 'BAPM' => [ 3277bf6ca81SGreg Roach 'M' => I18N::translate('Baptism of a brother'), 3287bf6ca81SGreg Roach 'F' => I18N::translate('Baptism of a sister'), 3297bf6ca81SGreg Roach 'U' => I18N::translate('Baptism of a sibling'), 3307bf6ca81SGreg Roach ], 3317bf6ca81SGreg Roach 'ADOP' => [ 3327bf6ca81SGreg Roach 'M' => I18N::translate('Adoption of a brother'), 3337bf6ca81SGreg Roach 'F' => I18N::translate('Adoption of a sister'), 3347bf6ca81SGreg Roach 'U' => I18N::translate('Adoption of a sibling'), 3357bf6ca81SGreg Roach ], 3367bf6ca81SGreg Roach ]; 3377bf6ca81SGreg Roach 3387bf6ca81SGreg Roach $birth_of_a_half_sibling = [ 3397bf6ca81SGreg Roach 'BIRT' => [ 3407bf6ca81SGreg Roach 'M' => I18N::translate('Birth of a half-brother'), 3417bf6ca81SGreg Roach 'F' => I18N::translate('Birth of a half-sister'), 3427bf6ca81SGreg Roach 'U' => I18N::translate('Birth of a half-sibling'), 3437bf6ca81SGreg Roach ], 3447bf6ca81SGreg Roach 'CHR' => [ 3457bf6ca81SGreg Roach 'M' => I18N::translate('Christening of a half-brother'), 3467bf6ca81SGreg Roach 'F' => I18N::translate('Christening of a half-sister'), 3477bf6ca81SGreg Roach 'U' => I18N::translate('Christening of a half-sibling'), 3487bf6ca81SGreg Roach ], 3497bf6ca81SGreg Roach 'BAPM' => [ 3507bf6ca81SGreg Roach 'M' => I18N::translate('Baptism of a half-brother'), 3517bf6ca81SGreg Roach 'F' => I18N::translate('Baptism of a half-sister'), 3527bf6ca81SGreg Roach 'U' => I18N::translate('Baptism of a half-sibling'), 3537bf6ca81SGreg Roach ], 3547bf6ca81SGreg Roach 'ADOP' => [ 3557bf6ca81SGreg Roach 'M' => I18N::translate('Adoption of a half-brother'), 3567bf6ca81SGreg Roach 'F' => I18N::translate('Adoption of a half-sister'), 3577bf6ca81SGreg Roach 'U' => I18N::translate('Adoption of a half-sibling'), 3587bf6ca81SGreg Roach ], 3597bf6ca81SGreg Roach ]; 3607bf6ca81SGreg Roach 3617bf6ca81SGreg Roach $birth_of_a_grandchild = [ 3627bf6ca81SGreg Roach 'BIRT' => [ 3637bf6ca81SGreg Roach 'M' => I18N::translate('Birth of a grandson'), 3647bf6ca81SGreg Roach 'F' => I18N::translate('Birth of a granddaughter'), 3657bf6ca81SGreg Roach 'U' => I18N::translate('Birth of a grandchild'), 3667bf6ca81SGreg Roach ], 3677bf6ca81SGreg Roach 'CHR' => [ 3687bf6ca81SGreg Roach 'M' => I18N::translate('Christening of a grandson'), 3697bf6ca81SGreg Roach 'F' => I18N::translate('Christening of a granddaughter'), 3707bf6ca81SGreg Roach 'U' => I18N::translate('Christening of a grandchild'), 3717bf6ca81SGreg Roach ], 3727bf6ca81SGreg Roach 'BAPM' => [ 3737bf6ca81SGreg Roach 'M' => I18N::translate('Baptism of a grandson'), 3747bf6ca81SGreg Roach 'F' => I18N::translate('Baptism of a granddaughter'), 3757bf6ca81SGreg Roach 'U' => I18N::translate('Baptism of a grandchild'), 3767bf6ca81SGreg Roach ], 3777bf6ca81SGreg Roach 'ADOP' => [ 3787bf6ca81SGreg Roach 'M' => I18N::translate('Adoption of a grandson'), 3797bf6ca81SGreg Roach 'F' => I18N::translate('Adoption of a granddaughter'), 3807bf6ca81SGreg Roach 'U' => I18N::translate('Adoption of a grandchild'), 3817bf6ca81SGreg Roach ], 3827bf6ca81SGreg Roach ]; 3837bf6ca81SGreg Roach 3847bf6ca81SGreg Roach $birth_of_a_grandchild1 = [ 3857bf6ca81SGreg Roach 'BIRT' => [ 3867bf6ca81SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Birth of a grandson'), 3877bf6ca81SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Birth of a granddaughter'), 3887bf6ca81SGreg Roach 'U' => I18N::translate('Birth of a grandchild'), 3897bf6ca81SGreg Roach ], 3907bf6ca81SGreg Roach 'CHR' => [ 3917bf6ca81SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Christening of a grandson'), 3927bf6ca81SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Christening of a granddaughter'), 3937bf6ca81SGreg Roach 'U' => I18N::translate('Christening of a grandchild'), 3947bf6ca81SGreg Roach ], 3957bf6ca81SGreg Roach 'BAPM' => [ 3967bf6ca81SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Baptism of a grandson'), 3977bf6ca81SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Baptism of a granddaughter'), 3987bf6ca81SGreg Roach 'U' => I18N::translate('Baptism of a grandchild'), 3997bf6ca81SGreg Roach ], 4007bf6ca81SGreg Roach 'ADOP' => [ 4017bf6ca81SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Adoption of a grandson'), 4027bf6ca81SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Adoption of a granddaughter'), 4037bf6ca81SGreg Roach 'U' => I18N::translate('Adoption of a grandchild'), 4047bf6ca81SGreg Roach ], 4057bf6ca81SGreg Roach ]; 4067bf6ca81SGreg Roach 4077bf6ca81SGreg Roach $birth_of_a_grandchild2 = [ 4087bf6ca81SGreg Roach 'BIRT' => [ 4093d394ce7SGreg Roach 'M' => I18N::translateContext('son’s son', 'Birth of a grandson'), 4103d394ce7SGreg Roach 'F' => I18N::translateContext('son’s daughter', 'Birth of a granddaughter'), 4117bf6ca81SGreg Roach 'U' => I18N::translate('Birth of a grandchild'), 4127bf6ca81SGreg Roach ], 4137bf6ca81SGreg Roach 'CHR' => [ 4143d394ce7SGreg Roach 'M' => I18N::translateContext('son’s son', 'Christening of a grandson'), 4153d394ce7SGreg Roach 'F' => I18N::translateContext('son’s daughter', 'Christening of a granddaughter'), 4167bf6ca81SGreg Roach 'U' => I18N::translate('Christening of a grandchild'), 4177bf6ca81SGreg Roach ], 4187bf6ca81SGreg Roach 'BAPM' => [ 4193d394ce7SGreg Roach 'M' => I18N::translateContext('son’s son', 'Baptism of a grandson'), 4203d394ce7SGreg Roach 'F' => I18N::translateContext('son’s daughter', 'Baptism of a granddaughter'), 4217bf6ca81SGreg Roach 'U' => I18N::translate('Baptism of a grandchild'), 4227bf6ca81SGreg Roach ], 4237bf6ca81SGreg Roach 'ADOP' => [ 4243d394ce7SGreg Roach 'M' => I18N::translateContext('son’s son', 'Adoption of a grandson'), 4253d394ce7SGreg Roach 'F' => I18N::translateContext('son’s daughter', 'Adoption of a granddaughter'), 4267bf6ca81SGreg Roach 'U' => I18N::translate('Adoption of a grandchild'), 4277bf6ca81SGreg Roach ], 4287bf6ca81SGreg Roach ]; 4297bf6ca81SGreg Roach 4307bf6ca81SGreg Roach $death_of_a_child = [ 4317bf6ca81SGreg Roach 'DEAT' => [ 4327bf6ca81SGreg Roach 'M' => I18N::translate('Death of a son'), 4337bf6ca81SGreg Roach 'F' => I18N::translate('Death of a daughter'), 4347bf6ca81SGreg Roach 'U' => I18N::translate('Death of a child'), 4357bf6ca81SGreg Roach ], 4367bf6ca81SGreg Roach 'BURI' => [ 4377bf6ca81SGreg Roach 'M' => I18N::translate('Burial of a son'), 4387bf6ca81SGreg Roach 'F' => I18N::translate('Burial of a daughter'), 4397bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a child'), 4407bf6ca81SGreg Roach ], 4417bf6ca81SGreg Roach 'CREM' => [ 4427bf6ca81SGreg Roach 'M' => I18N::translate('Cremation of a son'), 4437bf6ca81SGreg Roach 'F' => I18N::translate('Cremation of a daughter'), 4447bf6ca81SGreg Roach 'U' => I18N::translate('Cremation of a child'), 4457bf6ca81SGreg Roach ], 4467bf6ca81SGreg Roach ]; 4477bf6ca81SGreg Roach 4487bf6ca81SGreg Roach $death_of_a_sibling = [ 4497bf6ca81SGreg Roach 'DEAT' => [ 4507bf6ca81SGreg Roach 'M' => I18N::translate('Death of a brother'), 4517bf6ca81SGreg Roach 'F' => I18N::translate('Death of a sister'), 4527bf6ca81SGreg Roach 'U' => I18N::translate('Death of a sibling'), 4537bf6ca81SGreg Roach ], 4547bf6ca81SGreg Roach 'BURI' => [ 4557bf6ca81SGreg Roach 'M' => I18N::translate('Burial of a brother'), 4567bf6ca81SGreg Roach 'F' => I18N::translate('Burial of a sister'), 4577bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a sibling'), 4587bf6ca81SGreg Roach ], 4597bf6ca81SGreg Roach 'CREM' => [ 4607bf6ca81SGreg Roach 'M' => I18N::translate('Cremation of a brother'), 4617bf6ca81SGreg Roach 'F' => I18N::translate('Cremation of a sister'), 4627bf6ca81SGreg Roach 'U' => I18N::translate('Cremation of a sibling'), 4637bf6ca81SGreg Roach ], 4647bf6ca81SGreg Roach ]; 4657bf6ca81SGreg Roach 4667bf6ca81SGreg Roach $death_of_a_half_sibling = [ 4677bf6ca81SGreg Roach 'DEAT' => [ 4687bf6ca81SGreg Roach 'M' => I18N::translate('Death of a half-brother'), 4697bf6ca81SGreg Roach 'F' => I18N::translate('Death of a half-sister'), 4707bf6ca81SGreg Roach 'U' => I18N::translate('Death of a half-sibling'), 4717bf6ca81SGreg Roach ], 4727bf6ca81SGreg Roach 'BURI' => [ 4737bf6ca81SGreg Roach 'M' => I18N::translate('Burial of a half-brother'), 4747bf6ca81SGreg Roach 'F' => I18N::translate('Burial of a half-sister'), 4757bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a half-sibling'), 4767bf6ca81SGreg Roach ], 4777bf6ca81SGreg Roach 'CREM' => [ 4787bf6ca81SGreg Roach 'M' => I18N::translate('Cremation of a half-brother'), 4797bf6ca81SGreg Roach 'F' => I18N::translate('Cremation of a half-sister'), 4807bf6ca81SGreg Roach 'U' => I18N::translate('Cremation of a half-sibling'), 4817bf6ca81SGreg Roach ], 4827bf6ca81SGreg Roach ]; 4837bf6ca81SGreg Roach 4847bf6ca81SGreg Roach $death_of_a_grandchild = [ 4857bf6ca81SGreg Roach 'DEAT' => [ 4867bf6ca81SGreg Roach 'M' => I18N::translate('Death of a grandson'), 4877bf6ca81SGreg Roach 'F' => I18N::translate('Death of a granddaughter'), 4887bf6ca81SGreg Roach 'U' => I18N::translate('Death of a grandchild'), 4897bf6ca81SGreg Roach ], 4907bf6ca81SGreg Roach 'BURI' => [ 4917bf6ca81SGreg Roach 'M' => I18N::translate('Burial of a grandson'), 4927bf6ca81SGreg Roach 'F' => I18N::translate('Burial of a granddaughter'), 4937bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a grandchild'), 4947bf6ca81SGreg Roach ], 4957bf6ca81SGreg Roach 'CREM' => [ 4967bf6ca81SGreg Roach 'M' => I18N::translate('Cremation of a grandson'), 4977bf6ca81SGreg Roach 'F' => I18N::translate('Cremation of a granddaughter'), 4987bf6ca81SGreg Roach 'U' => I18N::translate('Baptism of a grandchild'), 4997bf6ca81SGreg Roach ], 5007bf6ca81SGreg Roach ]; 5017bf6ca81SGreg Roach 5027bf6ca81SGreg Roach $death_of_a_grandchild1 = [ 5037bf6ca81SGreg Roach 'DEAT' => [ 5047bf6ca81SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Death of a grandson'), 5057bf6ca81SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Death of a granddaughter'), 5067bf6ca81SGreg Roach 'U' => I18N::translate('Death of a grandchild'), 5077bf6ca81SGreg Roach ], 5087bf6ca81SGreg Roach 'BURI' => [ 5097bf6ca81SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Burial of a grandson'), 5107bf6ca81SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Burial of a granddaughter'), 5117bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a grandchild'), 5127bf6ca81SGreg Roach ], 5137bf6ca81SGreg Roach 'CREM' => [ 5147bf6ca81SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Cremation of a grandson'), 5157bf6ca81SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Cremation of a granddaughter'), 5167bf6ca81SGreg Roach 'U' => I18N::translate('Baptism of a grandchild'), 5177bf6ca81SGreg Roach ], 5187bf6ca81SGreg Roach ]; 5197bf6ca81SGreg Roach 5207bf6ca81SGreg Roach $death_of_a_grandchild2 = [ 5217bf6ca81SGreg Roach 'DEAT' => [ 5223d394ce7SGreg Roach 'M' => I18N::translateContext('son’s son', 'Death of a grandson'), 5233d394ce7SGreg Roach 'F' => I18N::translateContext('son’s daughter', 'Death of a granddaughter'), 5247bf6ca81SGreg Roach 'U' => I18N::translate('Death of a grandchild'), 5257bf6ca81SGreg Roach ], 5267bf6ca81SGreg Roach 'BURI' => [ 5273d394ce7SGreg Roach 'M' => I18N::translateContext('son’s son', 'Burial of a grandson'), 5283d394ce7SGreg Roach 'F' => I18N::translateContext('son’s daughter', 'Burial of a granddaughter'), 5297bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a grandchild'), 5307bf6ca81SGreg Roach ], 5317bf6ca81SGreg Roach 'CREM' => [ 5323d394ce7SGreg Roach 'M' => I18N::translateContext('son’s son', 'Cremation of a grandson'), 5333d394ce7SGreg Roach 'F' => I18N::translateContext('son’s daughter', 'Cremation of a granddaughter'), 5347bf6ca81SGreg Roach 'U' => I18N::translate('Cremation of a grandchild'), 5357bf6ca81SGreg Roach ], 5367bf6ca81SGreg Roach ]; 5377bf6ca81SGreg Roach 5387bf6ca81SGreg Roach $marriage_of_a_child = [ 5397bf6ca81SGreg Roach 'M' => I18N::translate('Marriage of a son'), 5407bf6ca81SGreg Roach 'F' => I18N::translate('Marriage of a daughter'), 5417bf6ca81SGreg Roach 'U' => I18N::translate('Marriage of a child'), 5427bf6ca81SGreg Roach ]; 5437bf6ca81SGreg Roach 5447bf6ca81SGreg Roach $marriage_of_a_grandchild = [ 5457bf6ca81SGreg Roach 'M' => I18N::translate('Marriage of a grandson'), 5467bf6ca81SGreg Roach 'F' => I18N::translate('Marriage of a granddaughter'), 5477bf6ca81SGreg Roach 'U' => I18N::translate('Marriage of a grandchild'), 5487bf6ca81SGreg Roach ]; 5497bf6ca81SGreg Roach 5507bf6ca81SGreg Roach $marriage_of_a_grandchild1 = [ 5517bf6ca81SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Marriage of a grandson'), 5527bf6ca81SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Marriage of a granddaughter'), 5537bf6ca81SGreg Roach 'U' => I18N::translate('Marriage of a grandchild'), 5547bf6ca81SGreg Roach ]; 5557bf6ca81SGreg Roach 5567bf6ca81SGreg Roach $marriage_of_a_grandchild2 = [ 5573d394ce7SGreg Roach 'M' => I18N::translateContext('son’s son', 'Marriage of a grandson'), 5583d394ce7SGreg Roach 'F' => I18N::translateContext('son’s daughter', 'Marriage of a granddaughter'), 5597bf6ca81SGreg Roach 'U' => I18N::translate('Marriage of a grandchild'), 5607bf6ca81SGreg Roach ]; 5617bf6ca81SGreg Roach 5627bf6ca81SGreg Roach $marriage_of_a_sibling = [ 5637bf6ca81SGreg Roach 'M' => I18N::translate('Marriage of a brother'), 5647bf6ca81SGreg Roach 'F' => I18N::translate('Marriage of a sister'), 5657bf6ca81SGreg Roach 'U' => I18N::translate('Marriage of a sibling'), 5667bf6ca81SGreg Roach ]; 5677bf6ca81SGreg Roach 5687bf6ca81SGreg Roach $marriage_of_a_half_sibling = [ 5697bf6ca81SGreg Roach 'M' => I18N::translate('Marriage of a half-brother'), 5707bf6ca81SGreg Roach 'F' => I18N::translate('Marriage of a half-sister'), 5717bf6ca81SGreg Roach 'U' => I18N::translate('Marriage of a half-sibling'), 5727bf6ca81SGreg Roach ]; 5737bf6ca81SGreg Roach 57413abd6f3SGreg Roach $facts = []; 5753763c3f2SGreg Roach 5763763c3f2SGreg Roach // Deal with recursion. 5773763c3f2SGreg Roach switch ($option) { 5783763c3f2SGreg Roach case '_CHIL': 5793763c3f2SGreg Roach // Add grandchildren 58039ca88baSGreg Roach foreach ($family->children() as $child) { 58139ca88baSGreg Roach foreach ($child->spouseFamilies() as $cfamily) { 58239ca88baSGreg Roach switch ($child->sex()) { 5833763c3f2SGreg Roach case 'M': 5848b9cfadbSGreg Roach foreach ($this->childFacts($person, $cfamily, '_GCHI', 'son', $min_date, $max_date) as $fact) { 5853763c3f2SGreg Roach $facts[] = $fact; 5863763c3f2SGreg Roach } 5873763c3f2SGreg Roach break; 5883763c3f2SGreg Roach case 'F': 5898b9cfadbSGreg Roach foreach ($this->childFacts($person, $cfamily, '_GCHI', 'dau', $min_date, $max_date) as $fact) { 5903763c3f2SGreg Roach $facts[] = $fact; 5913763c3f2SGreg Roach } 5923763c3f2SGreg Roach break; 5933763c3f2SGreg Roach default: 5948b9cfadbSGreg Roach foreach ($this->childFacts($person, $cfamily, '_GCHI', 'chi', $min_date, $max_date) as $fact) { 5953763c3f2SGreg Roach $facts[] = $fact; 5963763c3f2SGreg Roach } 5973763c3f2SGreg Roach break; 5983763c3f2SGreg Roach } 5993763c3f2SGreg Roach } 6003763c3f2SGreg Roach } 6013763c3f2SGreg Roach break; 6023763c3f2SGreg Roach } 6033763c3f2SGreg Roach 6043763c3f2SGreg Roach // For each child in the family 60539ca88baSGreg Roach foreach ($family->children() as $child) { 60622d65e5aSGreg Roach if ($child->xref() === $person->xref()) { 6073763c3f2SGreg Roach // We are not our own sibling! 6083763c3f2SGreg Roach continue; 6093763c3f2SGreg Roach } 6103763c3f2SGreg Roach // add child’s birth 6113763c3f2SGreg Roach if (strpos($SHOW_RELATIVES_EVENTS, '_BIRT' . str_replace('_HSIB', '_SIBL', $option)) !== false) { 6127bf6ca81SGreg Roach foreach ($child->facts(['BIRT', 'CHR', 'BAPM', 'ADOP']) as $fact) { 6133763c3f2SGreg Roach // Always show _BIRT_CHIL, even if the dates are not known 61422d65e5aSGreg Roach if ($option === '_CHIL' || $this->includeFact($fact, $min_date, $max_date)) { 6157bf6ca81SGreg Roach switch ($option) { 6167bf6ca81SGreg Roach case '_GCHI': 6177bf6ca81SGreg Roach switch ($relation) { 6187bf6ca81SGreg Roach case 'dau': 6197fe676e5SGreg Roach $facts[] = $this->convertEvent($fact, $birth_of_a_grandchild1[$fact->getTag()][$fact->record()->sex()]); 6207bf6ca81SGreg Roach break; 6217bf6ca81SGreg Roach case 'son': 6227fe676e5SGreg Roach $facts[] = $this->convertEvent($fact, $birth_of_a_grandchild2[$fact->getTag()][$fact->record()->sex()]); 6237bf6ca81SGreg Roach break; 6247bf6ca81SGreg Roach case 'chil': 6257fe676e5SGreg Roach $facts[] = $this->convertEvent($fact, $birth_of_a_grandchild[$fact->getTag()][$fact->record()->sex()]); 6267bf6ca81SGreg Roach break; 6277bf6ca81SGreg Roach } 6287bf6ca81SGreg Roach break; 6297bf6ca81SGreg Roach case '_SIBL': 6307fe676e5SGreg Roach $facts[] = $this->convertEvent($fact, $birth_of_a_sibling[$fact->getTag()][$fact->record()->sex()]); 6317bf6ca81SGreg Roach break; 6327bf6ca81SGreg Roach case '_HSIB': 6337fe676e5SGreg Roach $facts[] = $this->convertEvent($fact, $birth_of_a_half_sibling[$fact->getTag()][$fact->record()->sex()]); 6347bf6ca81SGreg Roach break; 6357bf6ca81SGreg Roach case '_CHIL': 6367fe676e5SGreg Roach $facts[] = $this->convertEvent($fact, $birth_of_a_child[$fact->getTag()][$fact->record()->sex()]); 6377bf6ca81SGreg Roach break; 6383763c3f2SGreg Roach } 6393763c3f2SGreg Roach } 6403763c3f2SGreg Roach } 6413763c3f2SGreg Roach } 6423763c3f2SGreg Roach // add child’s death 6433763c3f2SGreg Roach if (strpos($SHOW_RELATIVES_EVENTS, '_DEAT' . str_replace('_HSIB', '_SIBL', $option)) !== false) { 6447bf6ca81SGreg Roach foreach ($child->facts(['DEAT', 'BURI', 'CREM']) as $fact) { 6458b9cfadbSGreg Roach if ($this->includeFact($fact, $min_date, $max_date)) { 6467bf6ca81SGreg Roach switch ($option) { 6477bf6ca81SGreg Roach case '_GCHI': 6487bf6ca81SGreg Roach switch ($relation) { 6497bf6ca81SGreg Roach case 'dau': 6507fe676e5SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_grandchild1[$fact->getTag()][$fact->record()->sex()]); 6517bf6ca81SGreg Roach break; 6527bf6ca81SGreg Roach case 'son': 6537fe676e5SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_grandchild2[$fact->getTag()][$fact->record()->sex()]); 6547bf6ca81SGreg Roach break; 6557bf6ca81SGreg Roach case 'chi': 6567fe676e5SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_grandchild[$fact->getTag()][$fact->record()->sex()]); 6577bf6ca81SGreg Roach break; 6587bf6ca81SGreg Roach } 6597bf6ca81SGreg Roach break; 6607bf6ca81SGreg Roach case '_SIBL': 6617fe676e5SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_sibling[$fact->getTag()][$fact->record()->sex()]); 6627bf6ca81SGreg Roach break; 6637bf6ca81SGreg Roach case '_HSIB': 6647fe676e5SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_half_sibling[$fact->getTag()][$fact->record()->sex()]); 6657bf6ca81SGreg Roach break; 6667bf6ca81SGreg Roach case 'CHIL': 6677fe676e5SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_child[$fact->getTag()][$fact->record()->sex()]); 6687bf6ca81SGreg Roach break; 6693763c3f2SGreg Roach } 6703763c3f2SGreg Roach } 6713763c3f2SGreg Roach } 6723763c3f2SGreg Roach } 6737bf6ca81SGreg Roach 6743763c3f2SGreg Roach // add child’s marriage 6757bf6ca81SGreg Roach if (strpos($SHOW_RELATIVES_EVENTS, '_MARR' . str_replace('_HSIB', '_SIBL', $option)) !== false) { 67639ca88baSGreg Roach foreach ($child->spouseFamilies() as $sfamily) { 6778d0ebef0SGreg Roach foreach ($sfamily->facts(['MARR']) as $fact) { 6788b9cfadbSGreg Roach if ($this->includeFact($fact, $min_date, $max_date)) { 6797bf6ca81SGreg Roach switch ($option) { 6807bf6ca81SGreg Roach case '_GCHI': 6817bf6ca81SGreg Roach switch ($relation) { 6827bf6ca81SGreg Roach case 'dau': 6837bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $marriage_of_a_grandchild1['F']); 6847bf6ca81SGreg Roach break; 6857bf6ca81SGreg Roach case 'son': 6867bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $marriage_of_a_grandchild2['M']); 6877bf6ca81SGreg Roach break; 6887bf6ca81SGreg Roach case 'chi': 6897bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $marriage_of_a_grandchild['U']); 6907bf6ca81SGreg Roach break; 6917bf6ca81SGreg Roach } 6927bf6ca81SGreg Roach break; 6937bf6ca81SGreg Roach case '_SIBL': 6947bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $marriage_of_a_sibling['U']); 6957bf6ca81SGreg Roach break; 6967bf6ca81SGreg Roach case '_HSIB': 6977bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $marriage_of_a_half_sibling['U']); 6987bf6ca81SGreg Roach break; 6997bf6ca81SGreg Roach case '_CHIL': 7007bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $marriage_of_a_child['U']); 7017bf6ca81SGreg Roach break; 7023763c3f2SGreg Roach } 7033763c3f2SGreg Roach } 7043763c3f2SGreg Roach } 7053763c3f2SGreg Roach } 7063763c3f2SGreg Roach } 7073763c3f2SGreg Roach } 7083763c3f2SGreg Roach 7093763c3f2SGreg Roach return $facts; 7103763c3f2SGreg Roach } 7113763c3f2SGreg Roach 7123763c3f2SGreg Roach /** 7133763c3f2SGreg Roach * Get the events of parents and grandparents. 7143763c3f2SGreg Roach * 7153763c3f2SGreg Roach * @param Individual $person 716cbc1590aSGreg Roach * @param int $sosa 717ee727175SGreg Roach * @param Date $min_date 718ee727175SGreg Roach * @param Date $max_date 7193763c3f2SGreg Roach * 7203763c3f2SGreg Roach * @return Fact[] 7213763c3f2SGreg Roach */ 722054cfd06SGreg Roach private function parentFacts(Individual $person, int $sosa, Date $min_date, Date $max_date): array 723c1010edaSGreg Roach { 724f4afa648SGreg Roach $SHOW_RELATIVES_EVENTS = $person->tree()->getPreference('SHOW_RELATIVES_EVENTS'); 7253763c3f2SGreg Roach 7267bf6ca81SGreg Roach $death_of_a_parent = [ 7277bf6ca81SGreg Roach 'DEAT' => [ 7287bf6ca81SGreg Roach 'M' => I18N::translate('Death of a father'), 7297bf6ca81SGreg Roach 'F' => I18N::translate('Death of a mother'), 7307bf6ca81SGreg Roach 'U' => I18N::translate('Death of a parent'), 7317bf6ca81SGreg Roach ], 7327bf6ca81SGreg Roach 'BURI' => [ 7337bf6ca81SGreg Roach 'M' => I18N::translate('Burial of a father'), 7347bf6ca81SGreg Roach 'F' => I18N::translate('Burial of a mother'), 7357bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a parent'), 7367bf6ca81SGreg Roach ], 7377bf6ca81SGreg Roach 'CREM' => [ 7387bf6ca81SGreg Roach 'M' => I18N::translate('Cremation of a father'), 7397bf6ca81SGreg Roach 'F' => I18N::translate('Cremation of a mother'), 7407bf6ca81SGreg Roach 'U' => I18N::translate('Cremation of a parent'), 7417bf6ca81SGreg Roach ], 7427bf6ca81SGreg Roach ]; 7437bf6ca81SGreg Roach 7447bf6ca81SGreg Roach $death_of_a_grandparent = [ 7457bf6ca81SGreg Roach 'DEAT' => [ 7467bf6ca81SGreg Roach 'M' => I18N::translate('Death of a grandfather'), 7477bf6ca81SGreg Roach 'F' => I18N::translate('Death of a grandmother'), 7487bf6ca81SGreg Roach 'U' => I18N::translate('Death of a grandparent'), 7497bf6ca81SGreg Roach ], 7507bf6ca81SGreg Roach 'BURI' => [ 7517bf6ca81SGreg Roach 'M' => I18N::translate('Burial of a grandfather'), 7527bf6ca81SGreg Roach 'F' => I18N::translate('Burial of a grandmother'), 7537bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a grandparent'), 7547bf6ca81SGreg Roach ], 7557bf6ca81SGreg Roach 'CREM' => [ 7567bf6ca81SGreg Roach 'M' => I18N::translate('Cremation of a grandfather'), 7577bf6ca81SGreg Roach 'F' => I18N::translate('Cremation of a grandmother'), 7580b73ecfcSGreg Roach 'U' => I18N::translate('Cremation of a grandparent'), 7597bf6ca81SGreg Roach ], 7607bf6ca81SGreg Roach ]; 7617bf6ca81SGreg Roach 7627bf6ca81SGreg Roach $death_of_a_maternal_grandparent = [ 7637bf6ca81SGreg Roach 'DEAT' => [ 7640b73ecfcSGreg Roach 'M' => I18N::translate('Death of a maternal grandfather'), 7650b73ecfcSGreg Roach 'F' => I18N::translate('Death of a maternal grandmother'), 7667bf6ca81SGreg Roach 'U' => I18N::translate('Death of a grandparent'), 7677bf6ca81SGreg Roach ], 7687bf6ca81SGreg Roach 'BURI' => [ 7690b73ecfcSGreg Roach 'M' => I18N::translate('Burial of a maternal grandfather'), 7700b73ecfcSGreg Roach 'F' => I18N::translate('Burial of a maternal grandmother'), 7717bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a grandparent'), 7727bf6ca81SGreg Roach ], 7737bf6ca81SGreg Roach 'CREM' => [ 7740b73ecfcSGreg Roach 'M' => I18N::translate('Cremation of a maternal grandfather'), 7750b73ecfcSGreg Roach 'F' => I18N::translate('Cremation of a maternal grandmother'), 7760b73ecfcSGreg Roach 'U' => I18N::translate('Cremation of a grandparent'), 7777bf6ca81SGreg Roach ], 7787bf6ca81SGreg Roach ]; 7797bf6ca81SGreg Roach 7807bf6ca81SGreg Roach $death_of_a_paternal_grandparent = [ 7817bf6ca81SGreg Roach 'DEAT' => [ 7820b73ecfcSGreg Roach 'M' => I18N::translate('Death of a paternal grandfather'), 7830b73ecfcSGreg Roach 'F' => I18N::translate('Death of a paternal grandmother'), 7847bf6ca81SGreg Roach 'U' => I18N::translate('Death of a grandparent'), 7857bf6ca81SGreg Roach ], 7867bf6ca81SGreg Roach 'BURI' => [ 7870b73ecfcSGreg Roach 'M' => I18N::translate('Burial of a paternal grandfather'), 7880b73ecfcSGreg Roach 'F' => I18N::translate('Burial of a paternal grandmother'), 7897bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a grandparent'), 7907bf6ca81SGreg Roach ], 7917bf6ca81SGreg Roach 'CREM' => [ 7920b73ecfcSGreg Roach 'M' => I18N::translate('Cremation of a paternal grandfather'), 7930b73ecfcSGreg Roach 'F' => I18N::translate('Cremation of a paternal grandmother'), 7947bf6ca81SGreg Roach 'U' => I18N::translate('Cremation of a grandparent'), 7957bf6ca81SGreg Roach ], 7967bf6ca81SGreg Roach ]; 7977bf6ca81SGreg Roach 7987bf6ca81SGreg Roach $marriage_of_a_parent = [ 7997bf6ca81SGreg Roach 'M' => I18N::translate('Marriage of a father'), 8007bf6ca81SGreg Roach 'F' => I18N::translate('Marriage of a mother'), 8017bf6ca81SGreg Roach 'U' => I18N::translate('Marriage of a parent'), 8027bf6ca81SGreg Roach ]; 8037bf6ca81SGreg Roach 80413abd6f3SGreg Roach $facts = []; 8053763c3f2SGreg Roach 8060b73ecfcSGreg Roach if ($sosa === 1) { 80739ca88baSGreg Roach foreach ($person->childFamilies() as $family) { 8083763c3f2SGreg Roach // Add siblings 8098b9cfadbSGreg Roach foreach ($this->childFacts($person, $family, '_SIBL', '', $min_date, $max_date) as $fact) { 8103763c3f2SGreg Roach $facts[] = $fact; 8113763c3f2SGreg Roach } 81239ca88baSGreg Roach foreach ($family->spouses() as $spouse) { 81339ca88baSGreg Roach foreach ($spouse->spouseFamilies() as $sfamily) { 8143763c3f2SGreg Roach if ($family !== $sfamily) { 8153763c3f2SGreg Roach // Add half-siblings 8168b9cfadbSGreg Roach foreach ($this->childFacts($person, $sfamily, '_HSIB', '', $min_date, $max_date) as $fact) { 8173763c3f2SGreg Roach $facts[] = $fact; 8183763c3f2SGreg Roach } 8193763c3f2SGreg Roach } 8203763c3f2SGreg Roach } 8213763c3f2SGreg Roach // Add grandparents 82222d65e5aSGreg Roach foreach ($this->parentFacts($spouse, $spouse->sex() === 'F' ? 3 : 2, $min_date, $max_date) as $fact) { 8233763c3f2SGreg Roach $facts[] = $fact; 8243763c3f2SGreg Roach } 8253763c3f2SGreg Roach } 8263763c3f2SGreg Roach } 8273763c3f2SGreg Roach 8287bf6ca81SGreg Roach if (strpos($SHOW_RELATIVES_EVENTS, '_MARR_PARE') !== false) { 8293763c3f2SGreg Roach // add father/mother marriages 83039ca88baSGreg Roach foreach ($person->childFamilies() as $sfamily) { 8318d0ebef0SGreg Roach foreach ($sfamily->facts(['MARR']) as $fact) { 8328b9cfadbSGreg Roach if ($this->includeFact($fact, $min_date, $max_date)) { 8333763c3f2SGreg Roach // marriage of parents (to each other) 8347bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, I18N::translate('Marriage of parents')); 8353763c3f2SGreg Roach } 8363763c3f2SGreg Roach } 8373763c3f2SGreg Roach } 83839ca88baSGreg Roach foreach ($person->childStepFamilies() as $sfamily) { 8398d0ebef0SGreg Roach foreach ($sfamily->facts(['MARR']) as $fact) { 8408b9cfadbSGreg Roach if ($this->includeFact($fact, $min_date, $max_date)) { 8413763c3f2SGreg Roach // marriage of a parent (to another spouse) 8427bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $marriage_of_a_parent['U']); 8433763c3f2SGreg Roach } 8443763c3f2SGreg Roach } 8453763c3f2SGreg Roach } 8463763c3f2SGreg Roach } 8473763c3f2SGreg Roach } 8483763c3f2SGreg Roach 84939ca88baSGreg Roach foreach ($person->childFamilies() as $family) { 85039ca88baSGreg Roach foreach ($family->spouses() as $parent) { 8517bf6ca81SGreg Roach if (strpos($SHOW_RELATIVES_EVENTS, '_DEAT' . ($sosa === 1 ? '_PARE' : '_GPAR')) !== false) { 8527bf6ca81SGreg Roach foreach ($parent->facts(['DEAT', 'BURI', 'CREM']) as $fact) { 8538b9cfadbSGreg Roach if ($this->includeFact($fact, $min_date, $max_date)) { 8543763c3f2SGreg Roach switch ($sosa) { 8553763c3f2SGreg Roach case 1: 8567fe676e5SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_parent[$fact->getTag()][$fact->record()->sex()]); 8573763c3f2SGreg Roach break; 8583763c3f2SGreg Roach case 2: 8593763c3f2SGreg Roach case 3: 86069c89463SGreg Roach switch ($person->sex()) { 8617bf6ca81SGreg Roach case 'M': 8627fe676e5SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_paternal_grandparent[$fact->getTag()][$fact->record()->sex()]); 8633763c3f2SGreg Roach break; 8647bf6ca81SGreg Roach case 'F': 8657fe676e5SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_maternal_grandparent[$fact->getTag()][$fact->record()->sex()]); 8667bf6ca81SGreg Roach break; 8677bf6ca81SGreg Roach default: 8687fe676e5SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_grandparent[$fact->getTag()][$fact->record()->sex()]); 8697bf6ca81SGreg Roach break; 8707bf6ca81SGreg Roach } 8713763c3f2SGreg Roach } 8723763c3f2SGreg Roach } 8733763c3f2SGreg Roach } 8743763c3f2SGreg Roach } 8753763c3f2SGreg Roach } 8763763c3f2SGreg Roach } 8773763c3f2SGreg Roach 8783763c3f2SGreg Roach return $facts; 8793763c3f2SGreg Roach } 8803763c3f2SGreg Roach 8813763c3f2SGreg Roach /** 8823763c3f2SGreg Roach * Get any historical events. 8833763c3f2SGreg Roach * 88417c50b57SGreg Roach * @param Individual $individual 8853763c3f2SGreg Roach * 8863763c3f2SGreg Roach * @return Fact[] 8873763c3f2SGreg Roach */ 8884ca7e03cSGreg Roach private function historicalFacts(Individual $individual): array 889c1010edaSGreg Roach { 8904ca7e03cSGreg Roach return $this->module_service->findByInterface(ModuleHistoricEventsInterface::class) 8910b5fd0a6SGreg Roach ->map(static function (ModuleHistoricEventsInterface $module) use ($individual): Collection { 89217c50b57SGreg Roach return $module->historicEventsForIndividual($individual); 89317c50b57SGreg Roach }) 89417c50b57SGreg Roach ->flatten() 89517c50b57SGreg Roach ->all(); 8963763c3f2SGreg Roach } 8973763c3f2SGreg Roach 8983763c3f2SGreg Roach /** 8993763c3f2SGreg Roach * Get the events of associates. 9003763c3f2SGreg Roach * 9013763c3f2SGreg Roach * @param Individual $person 9023763c3f2SGreg Roach * 9033763c3f2SGreg Roach * @return Fact[] 9043763c3f2SGreg Roach */ 9058b9cfadbSGreg Roach private function associateFacts(Individual $person): array 906c1010edaSGreg Roach { 90713abd6f3SGreg Roach $facts = []; 9083763c3f2SGreg Roach 909ee727175SGreg Roach /** @var Individual[] $associates */ 910907c1109SGreg Roach $asso1 = $person->linkedIndividuals('ASSO'); 911907c1109SGreg Roach $asso2 = $person->linkedIndividuals('_ASSO'); 912907c1109SGreg Roach $asso3 = $person->linkedFamilies('ASSO'); 913907c1109SGreg Roach $asso4 = $person->linkedFamilies('_ASSO'); 914907c1109SGreg Roach 915907c1109SGreg Roach $associates = $asso1->merge($asso2)->merge($asso3)->merge($asso4); 916907c1109SGreg Roach 9173763c3f2SGreg Roach foreach ($associates as $associate) { 91830158ae7SGreg Roach foreach ($associate->facts() as $fact) { 919907c1109SGreg Roach if (preg_match('/\n\d _?ASSO @' . $person->xref() . '@/', $fact->gedcom())) { 9203763c3f2SGreg Roach // Extract the important details from the fact 9217fe676e5SGreg Roach $factrec = '1 ' . $fact->getTag(); 922138ca96cSGreg Roach if (preg_match('/\n2 DATE .*/', $fact->gedcom(), $match)) { 9233763c3f2SGreg Roach $factrec .= $match[0]; 9243763c3f2SGreg Roach } 925138ca96cSGreg Roach if (preg_match('/\n2 PLAC .*/', $fact->gedcom(), $match)) { 9263763c3f2SGreg Roach $factrec .= $match[0]; 9273763c3f2SGreg Roach } 9283763c3f2SGreg Roach if ($associate instanceof Family) { 92939ca88baSGreg Roach foreach ($associate->spouses() as $spouse) { 930c0935879SGreg Roach $factrec .= "\n2 _ASSO @" . $spouse->xref() . '@'; 9313763c3f2SGreg Roach } 9323763c3f2SGreg Roach } else { 933c0935879SGreg Roach $factrec .= "\n2 _ASSO @" . $associate->xref() . '@'; 9343763c3f2SGreg Roach } 9353763c3f2SGreg Roach $facts[] = new Fact($factrec, $associate, 'asso'); 9363763c3f2SGreg Roach } 9373763c3f2SGreg Roach } 9383763c3f2SGreg Roach } 9393763c3f2SGreg Roach 9403763c3f2SGreg Roach return $facts; 9413763c3f2SGreg Roach } 9428eaf8709SGreg Roach 9438eaf8709SGreg Roach /** 9448eaf8709SGreg Roach * This module handles the following facts - so don't show them on the "Facts and events" tab. 9458eaf8709SGreg Roach * 946b5c8fd7eSGreg Roach * @return Collection<string> 9478eaf8709SGreg Roach */ 9488eaf8709SGreg Roach public function supportedFacts(): Collection 9498eaf8709SGreg Roach { 9508eaf8709SGreg Roach // We don't actually displaye these facts, but they are displayed 9518eaf8709SGreg Roach // outside the tabs/sidebar systems. This just forces them to be excluded here. 9528eaf8709SGreg Roach return new Collection(['NAME', 'SEX']); 9538eaf8709SGreg Roach } 9543763c3f2SGreg Roach} 955