13763c3f2SGreg Roach<?php 23976b470SGreg Roach 33763c3f2SGreg Roach/** 43763c3f2SGreg Roach * webtrees: online genealogy 58fcd0d32SGreg Roach * Copyright (C) 2019 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 1318eaf8709SGreg Roach 1323763c3f2SGreg Roach // The individual’s own facts 13339ca88baSGreg Roach $indifacts = $individual->facts() 1340b5fd0a6SGreg Roach ->filter(static function (Fact $fact) use ($exclude_facts): bool { 13539ca88baSGreg Roach return !$exclude_facts->contains($fact->getTag()); 13639ca88baSGreg Roach }); 1373763c3f2SGreg Roach 1383763c3f2SGreg Roach // Add spouse-family facts 13939ca88baSGreg Roach foreach ($individual->spouseFamilies() as $family) { 14030158ae7SGreg Roach foreach ($family->facts() as $fact) { 1418eaf8709SGreg Roach if (!$exclude_facts->contains($fact->getTag()) && $fact->getTag() !== 'CHAN') { 14239ca88baSGreg Roach $indifacts->push($fact); 1433763c3f2SGreg Roach } 1443763c3f2SGreg Roach } 145ee727175SGreg Roach 14639ca88baSGreg Roach $spouse = $family->spouse($individual); 147ee727175SGreg Roach 148ee727175SGreg Roach if ($spouse instanceof Individual) { 1498b9cfadbSGreg Roach $spouse_facts = $this->spouseFacts($individual, $spouse, $min_date, $max_date); 15039ca88baSGreg Roach $indifacts = $indifacts->merge($spouse_facts); 1513763c3f2SGreg Roach } 1523763c3f2SGreg Roach 1538b9cfadbSGreg Roach $child_facts = $this->childFacts($individual, $family, '_CHIL', '', $min_date, $max_date); 15439ca88baSGreg Roach $indifacts = $indifacts->merge($child_facts); 1553763c3f2SGreg Roach } 156225e381fSGreg Roach 1578b9cfadbSGreg Roach $parent_facts = $this->parentFacts($individual, 1, $min_date, $max_date); 1588b9cfadbSGreg Roach $associate_facts = $this->associateFacts($individual); 1598b9cfadbSGreg Roach $historical_facts = $this->historicalFacts($individual); 160225e381fSGreg Roach 16139ca88baSGreg Roach $indifacts = $indifacts 16239ca88baSGreg Roach ->merge($parent_facts) 16339ca88baSGreg Roach ->merge($associate_facts) 16439ca88baSGreg Roach ->merge($historical_facts); 1653763c3f2SGreg Roach 166580a4d11SGreg Roach $indifacts = Fact::sortFacts($indifacts); 1673763c3f2SGreg Roach 168a8cd57e1SGreg Roach return view('modules/personal_facts/tab', [ 169225e381fSGreg Roach 'can_edit' => $individual->canEdit(), 1702adcbd9aSGreg Roach 'clipboard_facts' => $this->clipboard_service->pastableFacts($individual, $exclude_facts), 171ddeb3354SGreg Roach 'has_historical_facts' => $historical_facts !== [], 172225e381fSGreg Roach 'individual' => $individual, 173225e381fSGreg Roach 'facts' => $indifacts, 174225e381fSGreg Roach ]); 1753763c3f2SGreg Roach } 1763763c3f2SGreg Roach 177ee727175SGreg Roach /** 178ee727175SGreg Roach * Does a relative event occur within a date range (i.e. the individual's lifetime)? 179ee727175SGreg Roach * 180ee727175SGreg Roach * @param Fact $fact 181ee727175SGreg Roach * @param Date $min_date 182ee727175SGreg Roach * @param Date $max_date 183ee727175SGreg Roach * 184ee727175SGreg Roach * @return bool 185ee727175SGreg Roach */ 1868b9cfadbSGreg Roach private function includeFact(Fact $fact, Date $min_date, Date $max_date): bool 187b3b1d905SGreg Roach { 1882decada7SGreg Roach $fact_date = $fact->date(); 189ee727175SGreg Roach 190ee727175SGreg Roach return $fact_date->isOK() && Date::compare($min_date, $fact_date) <= 0 && Date::compare($fact_date, $max_date) <= 0; 191ee727175SGreg Roach } 192ee727175SGreg Roach 1933caaa4d2SGreg Roach /** 1943caaa4d2SGreg Roach * Is this tab empty? If so, we don't always need to display it. 1953caaa4d2SGreg Roach * 1963caaa4d2SGreg Roach * @param Individual $individual 1973caaa4d2SGreg Roach * 1983caaa4d2SGreg Roach * @return bool 1993caaa4d2SGreg Roach */ 2008f53f488SRico Sonntag public function hasTabContent(Individual $individual): bool 201c1010edaSGreg Roach { 2023763c3f2SGreg Roach return true; 2033763c3f2SGreg Roach } 2043763c3f2SGreg Roach 2053caaa4d2SGreg Roach /** 2063caaa4d2SGreg Roach * Can this tab load asynchronously? 2073caaa4d2SGreg Roach * 2083caaa4d2SGreg Roach * @return bool 2093caaa4d2SGreg Roach */ 2108f53f488SRico Sonntag public function canLoadAjax(): bool 211c1010edaSGreg Roach { 21215d603e7SGreg Roach return false; 2133763c3f2SGreg Roach } 2143763c3f2SGreg Roach 2153763c3f2SGreg Roach /** 216*7bf6ca81SGreg Roach * Convert an event into a special "event of a close relative". 217*7bf6ca81SGreg Roach * 218*7bf6ca81SGreg Roach * @param Fact $fact 219*7bf6ca81SGreg Roach * @param $type 220*7bf6ca81SGreg Roach * 221*7bf6ca81SGreg Roach * @return Fact 222*7bf6ca81SGreg Roach */ 223*7bf6ca81SGreg Roach private function convertEvent(Fact $fact, $type): Fact { 224*7bf6ca81SGreg Roach $gedcom = $fact->gedcom(); 225*7bf6ca81SGreg Roach $gedcom = preg_replace('/\n2 TYPE .*/', '', $gedcom); 226*7bf6ca81SGreg Roach $gedcom = preg_replace('/^1 .*/', "1 EVEN CLOSE_RELATIVE\n2 TYPE " . $type, $gedcom); 227*7bf6ca81SGreg Roach 228*7bf6ca81SGreg Roach return new Fact($gedcom, $fact->record(), $fact->id()); 229*7bf6ca81SGreg Roach } 230*7bf6ca81SGreg Roach 231*7bf6ca81SGreg 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 245*7bf6ca81SGreg Roach $death_of_a_spouse = [ 246*7bf6ca81SGreg Roach 'DEAT' => [ 247*7bf6ca81SGreg Roach 'M' => I18N::translate('Death of a husband'), 248*7bf6ca81SGreg Roach 'F' => I18N::translate('Death of a wife'), 249*7bf6ca81SGreg Roach 'U' => I18N::translate('Death of a spouse'), 250*7bf6ca81SGreg Roach ], 251*7bf6ca81SGreg Roach 'BURI' => [ 252*7bf6ca81SGreg Roach 'M' => I18N::translate('Burial of a husband'), 253*7bf6ca81SGreg Roach 'F' => I18N::translate('Burial of a wife'), 254*7bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a spouse'), 255*7bf6ca81SGreg Roach ], 256*7bf6ca81SGreg Roach 'CREM' => [ 257*7bf6ca81SGreg Roach 'M' => I18N::translate('Cremation of a husband'), 258*7bf6ca81SGreg Roach 'F' => I18N::translate('Cremation of a wife'), 259*7bf6ca81SGreg Roach 'U' => I18N::translate('Cremation of a spouse'), 260*7bf6ca81SGreg Roach ], 261*7bf6ca81SGreg Roach ]; 262*7bf6ca81SGreg Roach 26313abd6f3SGreg Roach $facts = []; 264*7bf6ca81SGreg Roach 265*7bf6ca81SGreg Roach if (strpos($SHOW_RELATIVES_EVENTS, '_DEAT_SPOU') !== false) { 266*7bf6ca81SGreg Roach foreach ($spouse->facts(['DEAT', 'BURI', 'CREM']) as $fact) { 2678b9cfadbSGreg Roach if ($this->includeFact($fact, $min_date, $max_date)) { 268*7bf6ca81SGreg 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 292*7bf6ca81SGreg Roach $birth_of_a_child = [ 293*7bf6ca81SGreg Roach 'BIRT' => [ 294*7bf6ca81SGreg Roach 'M' => I18N::translate('Birth of a son'), 295*7bf6ca81SGreg Roach 'F' => I18N::translate('Birth of a daughter'), 296*7bf6ca81SGreg Roach 'U' => I18N::translate('Birth of a child'), 297*7bf6ca81SGreg Roach ], 298*7bf6ca81SGreg Roach 'CHR' => [ 299*7bf6ca81SGreg Roach 'M' => I18N::translate('Christening of a son'), 300*7bf6ca81SGreg Roach 'F' => I18N::translate('Christening of a daughter'), 301*7bf6ca81SGreg Roach 'U' => I18N::translate('Christening of a child'), 302*7bf6ca81SGreg Roach ], 303*7bf6ca81SGreg Roach 'BAPM' => [ 304*7bf6ca81SGreg Roach 'M' => I18N::translate('Baptism of a son'), 305*7bf6ca81SGreg Roach 'F' => I18N::translate('Baptism of a daughter'), 306*7bf6ca81SGreg Roach 'U' => I18N::translate('Baptism of a child'), 307*7bf6ca81SGreg Roach ], 308*7bf6ca81SGreg Roach 'ADOP' => [ 309*7bf6ca81SGreg Roach 'M' => I18N::translate('Adoption of a son'), 310*7bf6ca81SGreg Roach 'F' => I18N::translate('Adoption of a daughter'), 311*7bf6ca81SGreg Roach 'U' => I18N::translate('Adoption of a child'), 312*7bf6ca81SGreg Roach ], 313*7bf6ca81SGreg Roach ]; 314*7bf6ca81SGreg Roach 315*7bf6ca81SGreg Roach $birth_of_a_sibling = [ 316*7bf6ca81SGreg Roach 'BIRT' => [ 317*7bf6ca81SGreg Roach 'M' => I18N::translate('Birth of a brother'), 318*7bf6ca81SGreg Roach 'F' => I18N::translate('Birth of a sister'), 319*7bf6ca81SGreg Roach 'U' => I18N::translate('Birth of a sibling'), 320*7bf6ca81SGreg Roach ], 321*7bf6ca81SGreg Roach 'CHR' => [ 322*7bf6ca81SGreg Roach 'M' => I18N::translate('Christening of a brother'), 323*7bf6ca81SGreg Roach 'F' => I18N::translate('Christening of a sister'), 324*7bf6ca81SGreg Roach 'U' => I18N::translate('Christening of a sibling'), 325*7bf6ca81SGreg Roach ], 326*7bf6ca81SGreg Roach 'BAPM' => [ 327*7bf6ca81SGreg Roach 'M' => I18N::translate('Baptism of a brother'), 328*7bf6ca81SGreg Roach 'F' => I18N::translate('Baptism of a sister'), 329*7bf6ca81SGreg Roach 'U' => I18N::translate('Baptism of a sibling'), 330*7bf6ca81SGreg Roach ], 331*7bf6ca81SGreg Roach 'ADOP' => [ 332*7bf6ca81SGreg Roach 'M' => I18N::translate('Adoption of a brother'), 333*7bf6ca81SGreg Roach 'F' => I18N::translate('Adoption of a sister'), 334*7bf6ca81SGreg Roach 'U' => I18N::translate('Adoption of a sibling'), 335*7bf6ca81SGreg Roach ], 336*7bf6ca81SGreg Roach ]; 337*7bf6ca81SGreg Roach 338*7bf6ca81SGreg Roach $birth_of_a_half_sibling = [ 339*7bf6ca81SGreg Roach 'BIRT' => [ 340*7bf6ca81SGreg Roach 'M' => I18N::translate('Birth of a half-brother'), 341*7bf6ca81SGreg Roach 'F' => I18N::translate('Birth of a half-sister'), 342*7bf6ca81SGreg Roach 'U' => I18N::translate('Birth of a half-sibling'), 343*7bf6ca81SGreg Roach ], 344*7bf6ca81SGreg Roach 'CHR' => [ 345*7bf6ca81SGreg Roach 'M' => I18N::translate('Christening of a half-brother'), 346*7bf6ca81SGreg Roach 'F' => I18N::translate('Christening of a half-sister'), 347*7bf6ca81SGreg Roach 'U' => I18N::translate('Christening of a half-sibling'), 348*7bf6ca81SGreg Roach ], 349*7bf6ca81SGreg Roach 'BAPM' => [ 350*7bf6ca81SGreg Roach 'M' => I18N::translate('Baptism of a half-brother'), 351*7bf6ca81SGreg Roach 'F' => I18N::translate('Baptism of a half-sister'), 352*7bf6ca81SGreg Roach 'U' => I18N::translate('Baptism of a half-sibling'), 353*7bf6ca81SGreg Roach ], 354*7bf6ca81SGreg Roach 'ADOP' => [ 355*7bf6ca81SGreg Roach 'M' => I18N::translate('Adoption of a half-brother'), 356*7bf6ca81SGreg Roach 'F' => I18N::translate('Adoption of a half-sister'), 357*7bf6ca81SGreg Roach 'U' => I18N::translate('Adoption of a half-sibling'), 358*7bf6ca81SGreg Roach ], 359*7bf6ca81SGreg Roach ]; 360*7bf6ca81SGreg Roach 361*7bf6ca81SGreg Roach $birth_of_a_grandchild = [ 362*7bf6ca81SGreg Roach 'BIRT' => [ 363*7bf6ca81SGreg Roach 'M' => I18N::translate('Birth of a grandson'), 364*7bf6ca81SGreg Roach 'F' => I18N::translate('Birth of a granddaughter'), 365*7bf6ca81SGreg Roach 'U' => I18N::translate('Birth of a grandchild'), 366*7bf6ca81SGreg Roach ], 367*7bf6ca81SGreg Roach 'CHR' => [ 368*7bf6ca81SGreg Roach 'M' => I18N::translate('Christening of a grandson'), 369*7bf6ca81SGreg Roach 'F' => I18N::translate('Christening of a granddaughter'), 370*7bf6ca81SGreg Roach 'U' => I18N::translate('Christening of a grandchild'), 371*7bf6ca81SGreg Roach ], 372*7bf6ca81SGreg Roach 'BAPM' => [ 373*7bf6ca81SGreg Roach 'M' => I18N::translate('Baptism of a grandson'), 374*7bf6ca81SGreg Roach 'F' => I18N::translate('Baptism of a granddaughter'), 375*7bf6ca81SGreg Roach 'U' => I18N::translate('Baptism of a grandchild'), 376*7bf6ca81SGreg Roach ], 377*7bf6ca81SGreg Roach 'ADOP' => [ 378*7bf6ca81SGreg Roach 'M' => I18N::translate('Adoption of a grandson'), 379*7bf6ca81SGreg Roach 'F' => I18N::translate('Adoption of a granddaughter'), 380*7bf6ca81SGreg Roach 'U' => I18N::translate('Adoption of a grandchild'), 381*7bf6ca81SGreg Roach ], 382*7bf6ca81SGreg Roach ]; 383*7bf6ca81SGreg Roach 384*7bf6ca81SGreg Roach $birth_of_a_grandchild1 = [ 385*7bf6ca81SGreg Roach 'BIRT' => [ 386*7bf6ca81SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Birth of a grandson'), 387*7bf6ca81SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Birth of a granddaughter'), 388*7bf6ca81SGreg Roach 'U' => I18N::translate('Birth of a grandchild'), 389*7bf6ca81SGreg Roach ], 390*7bf6ca81SGreg Roach 'CHR' => [ 391*7bf6ca81SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Christening of a grandson'), 392*7bf6ca81SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Christening of a granddaughter'), 393*7bf6ca81SGreg Roach 'U' => I18N::translate('Christening of a grandchild'), 394*7bf6ca81SGreg Roach ], 395*7bf6ca81SGreg Roach 'BAPM' => [ 396*7bf6ca81SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Baptism of a grandson'), 397*7bf6ca81SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Baptism of a granddaughter'), 398*7bf6ca81SGreg Roach 'U' => I18N::translate('Baptism of a grandchild'), 399*7bf6ca81SGreg Roach ], 400*7bf6ca81SGreg Roach 'ADOP' => [ 401*7bf6ca81SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Adoption of a grandson'), 402*7bf6ca81SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Adoption of a granddaughter'), 403*7bf6ca81SGreg Roach 'U' => I18N::translate('Adoption of a grandchild'), 404*7bf6ca81SGreg Roach ], 405*7bf6ca81SGreg Roach ]; 406*7bf6ca81SGreg Roach 407*7bf6ca81SGreg Roach $birth_of_a_grandchild2 = [ 408*7bf6ca81SGreg Roach 'BIRT' => [ 409*7bf6ca81SGreg Roach 'M' => I18N::translateContext('son‘s son', 'Birth of a grandson'), 410*7bf6ca81SGreg Roach 'F' => I18N::translateContext('son‘s daughter', 'Birth of a granddaughter'), 411*7bf6ca81SGreg Roach 'U' => I18N::translate('Birth of a grandchild'), 412*7bf6ca81SGreg Roach ], 413*7bf6ca81SGreg Roach 'CHR' => [ 414*7bf6ca81SGreg Roach 'M' => I18N::translateContext('son‘s son', 'Christening of a grandson'), 415*7bf6ca81SGreg Roach 'F' => I18N::translateContext('son‘s daughter', 'Christening of a granddaughter'), 416*7bf6ca81SGreg Roach 'U' => I18N::translate('Christening of a grandchild'), 417*7bf6ca81SGreg Roach ], 418*7bf6ca81SGreg Roach 'BAPM' => [ 419*7bf6ca81SGreg Roach 'M' => I18N::translateContext('son‘s son', 'Baptism of a grandson'), 420*7bf6ca81SGreg Roach 'F' => I18N::translateContext('son‘s daughter', 'Baptism of a granddaughter'), 421*7bf6ca81SGreg Roach 'U' => I18N::translate('Baptism of a grandchild'), 422*7bf6ca81SGreg Roach ], 423*7bf6ca81SGreg Roach 'ADOP' => [ 424*7bf6ca81SGreg Roach 'M' => I18N::translateContext('son‘s son', 'Adoption of a grandson'), 425*7bf6ca81SGreg Roach 'F' => I18N::translateContext('son‘s daughter', 'Adoption of a granddaughter'), 426*7bf6ca81SGreg Roach 'U' => I18N::translate('Adoption of a grandchild'), 427*7bf6ca81SGreg Roach ], 428*7bf6ca81SGreg Roach ]; 429*7bf6ca81SGreg Roach 430*7bf6ca81SGreg Roach $death_of_a_child = [ 431*7bf6ca81SGreg Roach 'DEAT' => [ 432*7bf6ca81SGreg Roach 'M' => I18N::translate('Death of a son'), 433*7bf6ca81SGreg Roach 'F' => I18N::translate('Death of a daughter'), 434*7bf6ca81SGreg Roach 'U' => I18N::translate('Death of a child'), 435*7bf6ca81SGreg Roach ], 436*7bf6ca81SGreg Roach 'BURI' => [ 437*7bf6ca81SGreg Roach 'M' => I18N::translate('Burial of a son'), 438*7bf6ca81SGreg Roach 'F' => I18N::translate('Burial of a daughter'), 439*7bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a child'), 440*7bf6ca81SGreg Roach ], 441*7bf6ca81SGreg Roach 'CREM' => [ 442*7bf6ca81SGreg Roach 'M' => I18N::translate('Cremation of a son'), 443*7bf6ca81SGreg Roach 'F' => I18N::translate('Cremation of a daughter'), 444*7bf6ca81SGreg Roach 'U' => I18N::translate('Cremation of a child'), 445*7bf6ca81SGreg Roach ], 446*7bf6ca81SGreg Roach ]; 447*7bf6ca81SGreg Roach 448*7bf6ca81SGreg Roach $death_of_a_sibling = [ 449*7bf6ca81SGreg Roach 'DEAT' => [ 450*7bf6ca81SGreg Roach 'M' => I18N::translate('Death of a brother'), 451*7bf6ca81SGreg Roach 'F' => I18N::translate('Death of a sister'), 452*7bf6ca81SGreg Roach 'U' => I18N::translate('Death of a sibling'), 453*7bf6ca81SGreg Roach ], 454*7bf6ca81SGreg Roach 'BURI' => [ 455*7bf6ca81SGreg Roach 'M' => I18N::translate('Burial of a brother'), 456*7bf6ca81SGreg Roach 'F' => I18N::translate('Burial of a sister'), 457*7bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a sibling'), 458*7bf6ca81SGreg Roach ], 459*7bf6ca81SGreg Roach 'CREM' => [ 460*7bf6ca81SGreg Roach 'M' => I18N::translate('Cremation of a brother'), 461*7bf6ca81SGreg Roach 'F' => I18N::translate('Cremation of a sister'), 462*7bf6ca81SGreg Roach 'U' => I18N::translate('Cremation of a sibling'), 463*7bf6ca81SGreg Roach ], 464*7bf6ca81SGreg Roach ]; 465*7bf6ca81SGreg Roach 466*7bf6ca81SGreg Roach $death_of_a_half_sibling = [ 467*7bf6ca81SGreg Roach 'DEAT' => [ 468*7bf6ca81SGreg Roach 'M' => I18N::translate('Death of a half-brother'), 469*7bf6ca81SGreg Roach 'F' => I18N::translate('Death of a half-sister'), 470*7bf6ca81SGreg Roach 'U' => I18N::translate('Death of a half-sibling'), 471*7bf6ca81SGreg Roach ], 472*7bf6ca81SGreg Roach 'BURI' => [ 473*7bf6ca81SGreg Roach 'M' => I18N::translate('Burial of a half-brother'), 474*7bf6ca81SGreg Roach 'F' => I18N::translate('Burial of a half-sister'), 475*7bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a half-sibling'), 476*7bf6ca81SGreg Roach ], 477*7bf6ca81SGreg Roach 'CREM' => [ 478*7bf6ca81SGreg Roach 'M' => I18N::translate('Cremation of a half-brother'), 479*7bf6ca81SGreg Roach 'F' => I18N::translate('Cremation of a half-sister'), 480*7bf6ca81SGreg Roach 'U' => I18N::translate('Cremation of a half-sibling'), 481*7bf6ca81SGreg Roach ], 482*7bf6ca81SGreg Roach ]; 483*7bf6ca81SGreg Roach 484*7bf6ca81SGreg Roach $death_of_a_grandchild = [ 485*7bf6ca81SGreg Roach 'DEAT' => [ 486*7bf6ca81SGreg Roach 'M' => I18N::translate('Death of a grandson'), 487*7bf6ca81SGreg Roach 'F' => I18N::translate('Death of a granddaughter'), 488*7bf6ca81SGreg Roach 'U' => I18N::translate('Death of a grandchild'), 489*7bf6ca81SGreg Roach ], 490*7bf6ca81SGreg Roach 'BURI' => [ 491*7bf6ca81SGreg Roach 'M' => I18N::translate('Burial of a grandson'), 492*7bf6ca81SGreg Roach 'F' => I18N::translate('Burial of a granddaughter'), 493*7bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a grandchild'), 494*7bf6ca81SGreg Roach ], 495*7bf6ca81SGreg Roach 'CREM' => [ 496*7bf6ca81SGreg Roach 'M' => I18N::translate('Cremation of a grandson'), 497*7bf6ca81SGreg Roach 'F' => I18N::translate('Cremation of a granddaughter'), 498*7bf6ca81SGreg Roach 'U' => I18N::translate('Baptism of a grandchild'), 499*7bf6ca81SGreg Roach ], 500*7bf6ca81SGreg Roach ]; 501*7bf6ca81SGreg Roach 502*7bf6ca81SGreg Roach $death_of_a_grandchild1 = [ 503*7bf6ca81SGreg Roach 'DEAT' => [ 504*7bf6ca81SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Death of a grandson'), 505*7bf6ca81SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Death of a granddaughter'), 506*7bf6ca81SGreg Roach 'U' => I18N::translate('Death of a grandchild'), 507*7bf6ca81SGreg Roach ], 508*7bf6ca81SGreg Roach 'BURI' => [ 509*7bf6ca81SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Burial of a grandson'), 510*7bf6ca81SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Burial of a granddaughter'), 511*7bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a grandchild'), 512*7bf6ca81SGreg Roach ], 513*7bf6ca81SGreg Roach 'CREM' => [ 514*7bf6ca81SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Cremation of a grandson'), 515*7bf6ca81SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Cremation of a granddaughter'), 516*7bf6ca81SGreg Roach 'U' => I18N::translate('Baptism of a grandchild'), 517*7bf6ca81SGreg Roach ], 518*7bf6ca81SGreg Roach ]; 519*7bf6ca81SGreg Roach 520*7bf6ca81SGreg Roach $death_of_a_grandchild2 = [ 521*7bf6ca81SGreg Roach 'DEAT' => [ 522*7bf6ca81SGreg Roach 'M' => I18N::translateContext('son‘s son', 'Death of a grandson'), 523*7bf6ca81SGreg Roach 'F' => I18N::translateContext('son‘s daughter', 'Death of a granddaughter'), 524*7bf6ca81SGreg Roach 'U' => I18N::translate('Death of a grandchild'), 525*7bf6ca81SGreg Roach ], 526*7bf6ca81SGreg Roach 'BURI' => [ 527*7bf6ca81SGreg Roach 'M' => I18N::translateContext('son‘s son', 'Burial of a grandson'), 528*7bf6ca81SGreg Roach 'F' => I18N::translateContext('son‘s daughter', 'Burial of a granddaughter'), 529*7bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a grandchild'), 530*7bf6ca81SGreg Roach ], 531*7bf6ca81SGreg Roach 'CREM' => [ 532*7bf6ca81SGreg Roach 'M' => I18N::translateContext('son‘s son', 'Cremation of a grandson'), 533*7bf6ca81SGreg Roach 'F' => I18N::translateContext('son‘s daughter', 'Cremation of a granddaughter'), 534*7bf6ca81SGreg Roach 'U' => I18N::translate('Cremation of a grandchild'), 535*7bf6ca81SGreg Roach ], 536*7bf6ca81SGreg Roach ]; 537*7bf6ca81SGreg Roach 538*7bf6ca81SGreg Roach $marriage_of_a_child = [ 539*7bf6ca81SGreg Roach 'M' => I18N::translate('Marriage of a son'), 540*7bf6ca81SGreg Roach 'F' => I18N::translate('Marriage of a daughter'), 541*7bf6ca81SGreg Roach 'U' => I18N::translate('Marriage of a child'), 542*7bf6ca81SGreg Roach ]; 543*7bf6ca81SGreg Roach 544*7bf6ca81SGreg Roach $marriage_of_a_grandchild = [ 545*7bf6ca81SGreg Roach 'M' => I18N::translate('Marriage of a grandson'), 546*7bf6ca81SGreg Roach 'F' => I18N::translate('Marriage of a granddaughter'), 547*7bf6ca81SGreg Roach 'U' => I18N::translate('Marriage of a grandchild'), 548*7bf6ca81SGreg Roach ]; 549*7bf6ca81SGreg Roach 550*7bf6ca81SGreg Roach $marriage_of_a_grandchild1 = [ 551*7bf6ca81SGreg Roach 'M' => I18N::translateContext('daughter’s son', 'Marriage of a grandson'), 552*7bf6ca81SGreg Roach 'F' => I18N::translateContext('daughter’s daughter', 'Marriage of a granddaughter'), 553*7bf6ca81SGreg Roach 'U' => I18N::translate('Marriage of a grandchild'), 554*7bf6ca81SGreg Roach ]; 555*7bf6ca81SGreg Roach 556*7bf6ca81SGreg Roach $marriage_of_a_grandchild2 = [ 557*7bf6ca81SGreg Roach 'M' => I18N::translateContext('son‘s son', 'Marriage of a grandson'), 558*7bf6ca81SGreg Roach 'F' => I18N::translateContext('son‘s daughter', 'Marriage of a granddaughter'), 559*7bf6ca81SGreg Roach 'U' => I18N::translate('Marriage of a grandchild'), 560*7bf6ca81SGreg Roach ]; 561*7bf6ca81SGreg Roach 562*7bf6ca81SGreg Roach $marriage_of_a_sibling = [ 563*7bf6ca81SGreg Roach 'M' => I18N::translate('Marriage of a brother'), 564*7bf6ca81SGreg Roach 'F' => I18N::translate('Marriage of a sister'), 565*7bf6ca81SGreg Roach 'U' => I18N::translate('Marriage of a sibling'), 566*7bf6ca81SGreg Roach ]; 567*7bf6ca81SGreg Roach 568*7bf6ca81SGreg Roach $marriage_of_a_half_sibling = [ 569*7bf6ca81SGreg Roach 'M' => I18N::translate('Marriage of a half-brother'), 570*7bf6ca81SGreg Roach 'F' => I18N::translate('Marriage of a half-sister'), 571*7bf6ca81SGreg Roach 'U' => I18N::translate('Marriage of a half-sibling'), 572*7bf6ca81SGreg Roach ]; 573*7bf6ca81SGreg 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) { 612*7bf6ca81SGreg 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)) { 615*7bf6ca81SGreg Roach switch ($option) { 616*7bf6ca81SGreg Roach case '_GCHI': 617*7bf6ca81SGreg Roach switch ($relation) { 618*7bf6ca81SGreg Roach case 'dau': 619*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $birth_of_a_grandchild1[$fact->getTag()][$fact->record()->sex()]); 620*7bf6ca81SGreg Roach break; 621*7bf6ca81SGreg Roach case 'son': 622*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $birth_of_a_grandchild2[$fact->getTag()][$fact->record()->sex()]); 623*7bf6ca81SGreg Roach break; 624*7bf6ca81SGreg Roach case 'chil': 625*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $birth_of_a_grandchild[$fact->getTag()][$fact->record()->sex()]); 626*7bf6ca81SGreg Roach break; 627*7bf6ca81SGreg Roach } 628*7bf6ca81SGreg Roach break; 629*7bf6ca81SGreg Roach case '_SIBL': 630*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $birth_of_a_sibling[$fact->getTag()][$fact->record()->sex()]); 631*7bf6ca81SGreg Roach break; 632*7bf6ca81SGreg Roach case '_HSIB': 633*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $birth_of_a_half_sibling[$fact->getTag()][$fact->record()->sex()]); 634*7bf6ca81SGreg Roach break; 635*7bf6ca81SGreg Roach case '_CHIL': 636*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $birth_of_a_child[$fact->getTag()][$fact->record()->sex()]); 637*7bf6ca81SGreg 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) { 644*7bf6ca81SGreg Roach foreach ($child->facts(['DEAT', 'BURI', 'CREM']) as $fact) { 6458b9cfadbSGreg Roach if ($this->includeFact($fact, $min_date, $max_date)) { 646*7bf6ca81SGreg Roach switch ($option) { 647*7bf6ca81SGreg Roach case '_GCHI': 648*7bf6ca81SGreg Roach switch ($relation) { 649*7bf6ca81SGreg Roach case 'dau': 650*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_grandchild1[$fact->getTag()][$fact->record()->sex()]); 651*7bf6ca81SGreg Roach break; 652*7bf6ca81SGreg Roach case 'son': 653*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_grandchild2[$fact->getTag()][$fact->record()->sex()]); 654*7bf6ca81SGreg Roach break; 655*7bf6ca81SGreg Roach case 'chi': 656*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_grandchild[$fact->getTag()][$fact->record()->sex()]); 657*7bf6ca81SGreg Roach break; 658*7bf6ca81SGreg Roach } 659*7bf6ca81SGreg Roach break; 660*7bf6ca81SGreg Roach case '_SIBL': 661*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_sibling[$fact->getTag()][$fact->record()->sex()]); 662*7bf6ca81SGreg Roach break; 663*7bf6ca81SGreg Roach case '_HSIB': 664*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_half_sibling[$fact->getTag()][$fact->record()->sex()]); 665*7bf6ca81SGreg Roach break; 666*7bf6ca81SGreg Roach case 'CHIL': 667*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_child[$fact->getTag()][$fact->record()->sex()]); 668*7bf6ca81SGreg Roach break; 6693763c3f2SGreg Roach } 6703763c3f2SGreg Roach } 6713763c3f2SGreg Roach } 6723763c3f2SGreg Roach } 673*7bf6ca81SGreg Roach 6743763c3f2SGreg Roach // add child’s marriage 675*7bf6ca81SGreg 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)) { 679*7bf6ca81SGreg Roach switch ($option) { 680*7bf6ca81SGreg Roach case '_GCHI': 681*7bf6ca81SGreg Roach switch ($relation) { 682*7bf6ca81SGreg Roach case 'dau': 683*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $marriage_of_a_grandchild1['F']); 684*7bf6ca81SGreg Roach break; 685*7bf6ca81SGreg Roach case 'son': 686*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $marriage_of_a_grandchild2['M']); 687*7bf6ca81SGreg Roach break; 688*7bf6ca81SGreg Roach case 'chi': 689*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $marriage_of_a_grandchild['U']); 690*7bf6ca81SGreg Roach break; 691*7bf6ca81SGreg Roach } 692*7bf6ca81SGreg Roach break; 693*7bf6ca81SGreg Roach case '_SIBL': 694*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $marriage_of_a_sibling['U']); 695*7bf6ca81SGreg Roach break; 696*7bf6ca81SGreg Roach case '_HSIB': 697*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $marriage_of_a_half_sibling['U']); 698*7bf6ca81SGreg Roach break; 699*7bf6ca81SGreg Roach case '_CHIL': 700*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $marriage_of_a_child['U']); 701*7bf6ca81SGreg 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 */ 7228b9cfadbSGreg Roach private function parentFacts(Individual $person, $sosa, Date $min_date, Date $max_date): array 723c1010edaSGreg Roach { 724f4afa648SGreg Roach $SHOW_RELATIVES_EVENTS = $person->tree()->getPreference('SHOW_RELATIVES_EVENTS'); 7253763c3f2SGreg Roach 726*7bf6ca81SGreg Roach $death_of_a_parent = [ 727*7bf6ca81SGreg Roach 'DEAT' => [ 728*7bf6ca81SGreg Roach 'M' => I18N::translate('Death of a father'), 729*7bf6ca81SGreg Roach 'F' => I18N::translate('Death of a mother'), 730*7bf6ca81SGreg Roach 'U' => I18N::translate('Death of a parent'), 731*7bf6ca81SGreg Roach ], 732*7bf6ca81SGreg Roach 'BURI' => [ 733*7bf6ca81SGreg Roach 'M' => I18N::translate('Burial of a father'), 734*7bf6ca81SGreg Roach 'F' => I18N::translate('Burial of a mother'), 735*7bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a parent'), 736*7bf6ca81SGreg Roach ], 737*7bf6ca81SGreg Roach 'CREM' => [ 738*7bf6ca81SGreg Roach 'M' => I18N::translate('Cremation of a father'), 739*7bf6ca81SGreg Roach 'F' => I18N::translate('Cremation of a mother'), 740*7bf6ca81SGreg Roach 'U' => I18N::translate('Cremation of a parent'), 741*7bf6ca81SGreg Roach ], 742*7bf6ca81SGreg Roach ]; 743*7bf6ca81SGreg Roach 744*7bf6ca81SGreg Roach $death_of_a_grandparent = [ 745*7bf6ca81SGreg Roach 'DEAT' => [ 746*7bf6ca81SGreg Roach 'M' => I18N::translate('Death of a grandfather'), 747*7bf6ca81SGreg Roach 'F' => I18N::translate('Death of a grandmother'), 748*7bf6ca81SGreg Roach 'U' => I18N::translate('Death of a grandparent'), 749*7bf6ca81SGreg Roach ], 750*7bf6ca81SGreg Roach 'BURI' => [ 751*7bf6ca81SGreg Roach 'M' => I18N::translate('Burial of a grandfather'), 752*7bf6ca81SGreg Roach 'F' => I18N::translate('Burial of a grandmother'), 753*7bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a grandparent'), 754*7bf6ca81SGreg Roach ], 755*7bf6ca81SGreg Roach 'CREM' => [ 756*7bf6ca81SGreg Roach 'M' => I18N::translate('Cremation of a grandfather'), 757*7bf6ca81SGreg Roach 'F' => I18N::translate('Cremation of a grandmother'), 758*7bf6ca81SGreg Roach 'U' => I18N::translate('Baptism of a grandparent'), 759*7bf6ca81SGreg Roach ], 760*7bf6ca81SGreg Roach ]; 761*7bf6ca81SGreg Roach 762*7bf6ca81SGreg Roach $death_of_a_maternal_grandparent = [ 763*7bf6ca81SGreg Roach 'DEAT' => [ 764*7bf6ca81SGreg Roach 'M' => I18N::translateContext('mother’s father', 'Death of a grandfather'), 765*7bf6ca81SGreg Roach 'F' => I18N::translateContext('mother’s mother', 'Death of a grandmother'), 766*7bf6ca81SGreg Roach 'U' => I18N::translate('Death of a grandparent'), 767*7bf6ca81SGreg Roach ], 768*7bf6ca81SGreg Roach 'BURI' => [ 769*7bf6ca81SGreg Roach 'M' => I18N::translateContext('mother’s father', 'Burial of a grandfather'), 770*7bf6ca81SGreg Roach 'F' => I18N::translateContext('mother’s mother', 'Burial of a grandmother'), 771*7bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a grandparent'), 772*7bf6ca81SGreg Roach ], 773*7bf6ca81SGreg Roach 'CREM' => [ 774*7bf6ca81SGreg Roach 'M' => I18N::translateContext('mother’s father', 'Cremation of a grandfather'), 775*7bf6ca81SGreg Roach 'F' => I18N::translateContext('mother’s mother', 'Cremation of a grandmother'), 776*7bf6ca81SGreg Roach 'U' => I18N::translate('Baptism of a grandparent'), 777*7bf6ca81SGreg Roach ], 778*7bf6ca81SGreg Roach ]; 779*7bf6ca81SGreg Roach 780*7bf6ca81SGreg Roach $death_of_a_paternal_grandparent = [ 781*7bf6ca81SGreg Roach 'DEAT' => [ 782*7bf6ca81SGreg Roach 'M' => I18N::translateContext('father‘s father', 'Death of a grandfather'), 783*7bf6ca81SGreg Roach 'F' => I18N::translateContext('father‘s mother', 'Death of a grandmother'), 784*7bf6ca81SGreg Roach 'U' => I18N::translate('Death of a grandparent'), 785*7bf6ca81SGreg Roach ], 786*7bf6ca81SGreg Roach 'BURI' => [ 787*7bf6ca81SGreg Roach 'M' => I18N::translateContext('father‘s father', 'Burial of a grandfather'), 788*7bf6ca81SGreg Roach 'F' => I18N::translateContext('father‘s mother', 'Burial of a grandmother'), 789*7bf6ca81SGreg Roach 'U' => I18N::translate('Burial of a grandparent'), 790*7bf6ca81SGreg Roach ], 791*7bf6ca81SGreg Roach 'CREM' => [ 792*7bf6ca81SGreg Roach 'M' => I18N::translateContext('father‘s father', 'Cremation of a grandfather'), 793*7bf6ca81SGreg Roach 'F' => I18N::translateContext('father‘s mother', 'Cremation of a grandmother'), 794*7bf6ca81SGreg Roach 'U' => I18N::translate('Cremation of a grandparent'), 795*7bf6ca81SGreg Roach ], 796*7bf6ca81SGreg Roach ]; 797*7bf6ca81SGreg Roach 798*7bf6ca81SGreg Roach $marriage_of_a_parent = [ 799*7bf6ca81SGreg Roach 'M' => I18N::translate('Marriage of a father'), 800*7bf6ca81SGreg Roach 'F' => I18N::translate('Marriage of a mother'), 801*7bf6ca81SGreg Roach 'U' => I18N::translate('Marriage of a parent'), 802*7bf6ca81SGreg Roach ]; 803*7bf6ca81SGreg Roach 80413abd6f3SGreg Roach $facts = []; 8053763c3f2SGreg Roach 8063763c3f2SGreg 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 828*7bf6ca81SGreg 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) 834*7bf6ca81SGreg 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) 842*7bf6ca81SGreg 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) { 851*7bf6ca81SGreg Roach if (strpos($SHOW_RELATIVES_EVENTS, '_DEAT' . ($sosa === 1 ? '_PARE' : '_GPAR')) !== false) { 852*7bf6ca81SGreg 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: 856*7bf6ca81SGreg 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: 860*7bf6ca81SGreg Roach switch ($parent->sex()) { 861*7bf6ca81SGreg Roach case 'M': 862*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_paternal_grandparent[$fact->getTag()][$fact->record()->sex()]); 8633763c3f2SGreg Roach break; 864*7bf6ca81SGreg Roach case 'F': 865*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_maternal_grandparent[$fact->getTag()][$fact->record()->sex()]); 866*7bf6ca81SGreg Roach break; 867*7bf6ca81SGreg Roach default: 868*7bf6ca81SGreg Roach $facts[] = $this->convertEvent($fact, $death_of_a_grandparent[$fact->getTag()][$fact->record()->sex()]); 869*7bf6ca81SGreg Roach break; 870*7bf6ca81SGreg 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 9213763c3f2SGreg 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