13763c3f2SGreg Roach<?php 23763c3f2SGreg Roach/** 33763c3f2SGreg Roach * webtrees: online genealogy 48fcd0d32SGreg Roach * Copyright (C) 2019 webtrees development team 53763c3f2SGreg Roach * This program is free software: you can redistribute it and/or modify 63763c3f2SGreg Roach * it under the terms of the GNU General Public License as published by 73763c3f2SGreg Roach * the Free Software Foundation, either version 3 of the License, or 83763c3f2SGreg Roach * (at your option) any later version. 93763c3f2SGreg Roach * This program is distributed in the hope that it will be useful, 103763c3f2SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 113763c3f2SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 123763c3f2SGreg Roach * GNU General Public License for more details. 133763c3f2SGreg Roach * You should have received a copy of the GNU General Public License 143763c3f2SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>. 153763c3f2SGreg Roach */ 16e7f56f2aSGreg Roachdeclare(strict_types=1); 17e7f56f2aSGreg Roach 1876692c8bSGreg Roachnamespace Fisharebest\Webtrees\Module; 1976692c8bSGreg Roach 2063276d8fSGreg Roachuse Fisharebest\Webtrees\Auth; 210e62c4b8SGreg Roachuse Fisharebest\Webtrees\Date; 220e62c4b8SGreg Roachuse Fisharebest\Webtrees\Fact; 230e62c4b8SGreg Roachuse Fisharebest\Webtrees\Family; 243d7a8a4cSGreg Roachuse Fisharebest\Webtrees\Functions\Functions; 258d0ebef0SGreg Roachuse Fisharebest\Webtrees\Gedcom; 260e62c4b8SGreg Roachuse Fisharebest\Webtrees\I18N; 270e62c4b8SGreg Roachuse Fisharebest\Webtrees\Individual; 284ca7e03cSGreg Roachuse Fisharebest\Webtrees\Services\ModuleService; 2917c50b57SGreg Roachuse Illuminate\Support\Collection; 303763c3f2SGreg Roach 313763c3f2SGreg Roach/** 323763c3f2SGreg Roach * Class IndividualFactsTabModule 333763c3f2SGreg Roach */ 3437eb8894SGreg Roachclass IndividualFactsTabModule extends AbstractModule implements ModuleTabInterface 35c1010edaSGreg Roach{ 3649a243cbSGreg Roach use ModuleTabTrait; 3749a243cbSGreg Roach 38961ec755SGreg Roach /** 394ca7e03cSGreg Roach * @var ModuleService 404ca7e03cSGreg Roach */ 414ca7e03cSGreg Roach private $module_service; 424ca7e03cSGreg Roach 434ca7e03cSGreg Roach /** 444ca7e03cSGreg Roach * UserWelcomeModule constructor. 454ca7e03cSGreg Roach * 464ca7e03cSGreg Roach * @param ModuleService $module_service 474ca7e03cSGreg Roach */ 485bdbe281SGreg Roach public function __construct(ModuleService $module_service) 495bdbe281SGreg Roach { 504ca7e03cSGreg Roach $this->module_service = $module_service; 514ca7e03cSGreg Roach } 524ca7e03cSGreg Roach 534ca7e03cSGreg Roach /** 54961ec755SGreg Roach * How should this module be labelled on tabs, menus, etc.? 55961ec755SGreg Roach * 56961ec755SGreg Roach * @return string 57961ec755SGreg Roach */ 5849a243cbSGreg Roach public function title(): string 59c1010edaSGreg Roach { 60bbb76c12SGreg Roach /* I18N: Name of a module/tab on the individual page. */ 61bbb76c12SGreg Roach return I18N::translate('Facts and events'); 623763c3f2SGreg Roach } 633763c3f2SGreg Roach 64961ec755SGreg Roach /** 65961ec755SGreg Roach * A sentence describing what this module does. 66961ec755SGreg Roach * 67961ec755SGreg Roach * @return string 68961ec755SGreg Roach */ 6949a243cbSGreg Roach public function description(): string 70c1010edaSGreg Roach { 71bbb76c12SGreg Roach /* I18N: Description of the “Facts and events” module */ 72bbb76c12SGreg Roach return I18N::translate('A tab showing the facts and events of an individual.'); 733763c3f2SGreg Roach } 743763c3f2SGreg Roach 7549a243cbSGreg Roach /** 7649a243cbSGreg Roach * The default position for this tab. It can be changed in the control panel. 7749a243cbSGreg Roach * 7849a243cbSGreg Roach * @return int 7949a243cbSGreg Roach */ 80cbf4b7faSGreg Roach public function defaultTabOrder(): int 81cbf4b7faSGreg Roach { 82353b36abSGreg Roach return 2; 833763c3f2SGreg Roach } 843763c3f2SGreg Roach 853763c3f2SGreg Roach /** {@inheritdoc} */ 868f53f488SRico Sonntag public function isGrayedOut(Individual $individual): bool 87c1010edaSGreg Roach { 883763c3f2SGreg Roach return false; 893763c3f2SGreg Roach } 903763c3f2SGreg Roach 913763c3f2SGreg Roach /** {@inheritdoc} */ 929b34404bSGreg Roach public function getTabContent(Individual $individual): string 93c1010edaSGreg Roach { 94ee727175SGreg Roach // Only include events of close relatives that are between birth and death 95ee727175SGreg Roach $min_date = $individual->getEstimatedBirthDate(); 96ee727175SGreg Roach $max_date = $individual->getEstimatedDeathDate(); 97ee727175SGreg Roach 9813abd6f3SGreg Roach $indifacts = []; 993763c3f2SGreg Roach // The individual’s own facts 10030158ae7SGreg Roach foreach ($individual->facts() as $fact) { 1013763c3f2SGreg Roach switch ($fact->getTag()) { 1023763c3f2SGreg Roach case 'SEX': 1033763c3f2SGreg Roach case 'NAME': 1043763c3f2SGreg Roach case 'SOUR': 1053763c3f2SGreg Roach case 'OBJE': 1063763c3f2SGreg Roach case 'NOTE': 1073763c3f2SGreg Roach case 'FAMC': 1083763c3f2SGreg Roach case 'FAMS': 1093763c3f2SGreg Roach break; 11049a243cbSGreg Roach 1113763c3f2SGreg Roach default: 112*8b9cfadbSGreg Roach $extra_info_module = $this->module_service->findByComponent('sidebar', $individual->tree(), Auth::user()) 11349a243cbSGreg Roach ->filter(function (ModuleInterface $module): bool { 11449a243cbSGreg Roach return $module instanceof ExtraInformationModule; 115*8b9cfadbSGreg Roach }); 11649a243cbSGreg Roach 117*8b9cfadbSGreg Roach if ($extra_info_module instanceof ExtraInformationModule && !$extra_info_module->showFact($fact)) { 1183763c3f2SGreg Roach $indifacts[] = $fact; 1193763c3f2SGreg Roach } 1203763c3f2SGreg Roach break; 1213763c3f2SGreg Roach } 1223763c3f2SGreg Roach } 1233763c3f2SGreg Roach 1243763c3f2SGreg Roach // Add spouse-family facts 125225e381fSGreg Roach foreach ($individual->getSpouseFamilies() as $family) { 12630158ae7SGreg Roach foreach ($family->facts() as $fact) { 1273763c3f2SGreg Roach switch ($fact->getTag()) { 1283763c3f2SGreg Roach case 'SOUR': 1293763c3f2SGreg Roach case 'NOTE': 1303763c3f2SGreg Roach case 'OBJE': 1313763c3f2SGreg Roach case 'CHAN': 1323763c3f2SGreg Roach case '_UID': 1333763c3f2SGreg Roach case 'RIN': 1343763c3f2SGreg Roach case 'HUSB': 1353763c3f2SGreg Roach case 'WIFE': 1363763c3f2SGreg Roach case 'CHIL': 1373763c3f2SGreg Roach break; 1383763c3f2SGreg Roach default: 1393763c3f2SGreg Roach $indifacts[] = $fact; 1403763c3f2SGreg Roach break; 1413763c3f2SGreg Roach } 1423763c3f2SGreg Roach } 143ee727175SGreg Roach 144225e381fSGreg Roach $spouse = $family->getSpouse($individual); 145ee727175SGreg Roach 146ee727175SGreg Roach if ($spouse instanceof Individual) { 147*8b9cfadbSGreg Roach $spouse_facts = $this->spouseFacts($individual, $spouse, $min_date, $max_date); 148ee727175SGreg Roach $indifacts = array_merge($indifacts, $spouse_facts); 1493763c3f2SGreg Roach } 1503763c3f2SGreg Roach 151*8b9cfadbSGreg Roach $child_facts = $this->childFacts($individual, $family, '_CHIL', '', $min_date, $max_date); 152ee727175SGreg Roach $indifacts = array_merge($indifacts, $child_facts); 1533763c3f2SGreg Roach } 154225e381fSGreg Roach 155*8b9cfadbSGreg Roach $parent_facts = $this->parentFacts($individual, 1, $min_date, $max_date); 156*8b9cfadbSGreg Roach $associate_facts = $this->associateFacts($individual); 157*8b9cfadbSGreg Roach $historical_facts = $this->historicalFacts($individual); 158225e381fSGreg Roach 159ee727175SGreg Roach $indifacts = array_merge($indifacts, $parent_facts, $associate_facts, $historical_facts); 1603763c3f2SGreg Roach 1613d7a8a4cSGreg Roach Functions::sortFacts($indifacts); 1623763c3f2SGreg Roach 163a8cd57e1SGreg Roach return view('modules/personal_facts/tab', [ 164225e381fSGreg Roach 'can_edit' => $individual->canEdit(), 165ee727175SGreg Roach 'has_historical_facts' => !empty($historical_facts), 166225e381fSGreg Roach 'individual' => $individual, 167225e381fSGreg Roach 'facts' => $indifacts, 168225e381fSGreg Roach ]); 1693763c3f2SGreg Roach } 1703763c3f2SGreg Roach 171ee727175SGreg Roach /** 172ee727175SGreg Roach * Does a relative event occur within a date range (i.e. the individual's lifetime)? 173ee727175SGreg Roach * 174ee727175SGreg Roach * @param Fact $fact 175ee727175SGreg Roach * @param Date $min_date 176ee727175SGreg Roach * @param Date $max_date 177ee727175SGreg Roach * 178ee727175SGreg Roach * @return bool 179ee727175SGreg Roach */ 180*8b9cfadbSGreg Roach private function includeFact(Fact $fact, Date $min_date, Date $max_date): bool 181b3b1d905SGreg Roach { 1822decada7SGreg Roach $fact_date = $fact->date(); 183ee727175SGreg Roach 184ee727175SGreg Roach return $fact_date->isOK() && Date::compare($min_date, $fact_date) <= 0 && Date::compare($fact_date, $max_date) <= 0; 185ee727175SGreg Roach } 186ee727175SGreg Roach 1873763c3f2SGreg Roach /** {@inheritdoc} */ 1888f53f488SRico Sonntag public function hasTabContent(Individual $individual): bool 189c1010edaSGreg Roach { 1903763c3f2SGreg Roach return true; 1913763c3f2SGreg Roach } 1923763c3f2SGreg Roach 1933763c3f2SGreg Roach /** {@inheritdoc} */ 1948f53f488SRico Sonntag public function canLoadAjax(): bool 195c1010edaSGreg Roach { 19615d603e7SGreg Roach return false; 1973763c3f2SGreg Roach } 1983763c3f2SGreg Roach 1993763c3f2SGreg Roach /** 2003763c3f2SGreg Roach * Spouse facts that are shown on an individual’s page. 2013763c3f2SGreg Roach * 2023763c3f2SGreg Roach * @param Individual $individual Show events that occured during the lifetime of this individual 2033763c3f2SGreg Roach * @param Individual $spouse Show events of this individual 204ee727175SGreg Roach * @param Date $min_date 205ee727175SGreg Roach * @param Date $max_date 2063763c3f2SGreg Roach * 2073763c3f2SGreg Roach * @return Fact[] 2083763c3f2SGreg Roach */ 209*8b9cfadbSGreg Roach private function spouseFacts(Individual $individual, Individual $spouse, Date $min_date, Date $max_date): array 210c1010edaSGreg Roach { 211f4afa648SGreg Roach $SHOW_RELATIVES_EVENTS = $individual->tree()->getPreference('SHOW_RELATIVES_EVENTS'); 2123763c3f2SGreg Roach 21313abd6f3SGreg Roach $facts = []; 2143763c3f2SGreg Roach if (strstr($SHOW_RELATIVES_EVENTS, '_DEAT_SPOU')) { 2158d0ebef0SGreg Roach foreach ($spouse->facts(Gedcom::DEATH_EVENTS) as $fact) { 216*8b9cfadbSGreg Roach if ($this->includeFact($fact, $min_date, $max_date)) { 2173763c3f2SGreg Roach // Convert the event to a close relatives event. 2183763c3f2SGreg Roach $rela_fact = clone($fact); 2193763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_SPOU'); 2203763c3f2SGreg Roach $facts[] = $rela_fact; 2213763c3f2SGreg Roach } 2223763c3f2SGreg Roach } 2233763c3f2SGreg Roach } 2243763c3f2SGreg Roach 2253763c3f2SGreg Roach return $facts; 2263763c3f2SGreg Roach } 2273763c3f2SGreg Roach 2283763c3f2SGreg Roach /** 2293763c3f2SGreg Roach * Get the events of children and grandchildren. 2303763c3f2SGreg Roach * 2313763c3f2SGreg Roach * @param Individual $person 2323763c3f2SGreg Roach * @param Family $family 2333763c3f2SGreg Roach * @param string $option 2343763c3f2SGreg Roach * @param string $relation 235ee727175SGreg Roach * @param Date $min_date 236ee727175SGreg Roach * @param Date $max_date 2373763c3f2SGreg Roach * 2383763c3f2SGreg Roach * @return Fact[] 2393763c3f2SGreg Roach */ 240*8b9cfadbSGreg Roach private function childFacts(Individual $person, Family $family, $option, $relation, Date $min_date, Date $max_date): array 241c1010edaSGreg Roach { 242f4afa648SGreg Roach $SHOW_RELATIVES_EVENTS = $person->tree()->getPreference('SHOW_RELATIVES_EVENTS'); 2433763c3f2SGreg Roach 24413abd6f3SGreg Roach $facts = []; 2453763c3f2SGreg Roach 2463763c3f2SGreg Roach // Deal with recursion. 2473763c3f2SGreg Roach switch ($option) { 2483763c3f2SGreg Roach case '_CHIL': 2493763c3f2SGreg Roach // Add grandchildren 2503763c3f2SGreg Roach foreach ($family->getChildren() as $child) { 2513763c3f2SGreg Roach foreach ($child->getSpouseFamilies() as $cfamily) { 2523763c3f2SGreg Roach switch ($child->getSex()) { 2533763c3f2SGreg Roach case 'M': 254*8b9cfadbSGreg Roach foreach ($this->childFacts($person, $cfamily, '_GCHI', 'son', $min_date, $max_date) as $fact) { 2553763c3f2SGreg Roach $facts[] = $fact; 2563763c3f2SGreg Roach } 2573763c3f2SGreg Roach break; 2583763c3f2SGreg Roach case 'F': 259*8b9cfadbSGreg Roach foreach ($this->childFacts($person, $cfamily, '_GCHI', 'dau', $min_date, $max_date) as $fact) { 2603763c3f2SGreg Roach $facts[] = $fact; 2613763c3f2SGreg Roach } 2623763c3f2SGreg Roach break; 2633763c3f2SGreg Roach default: 264*8b9cfadbSGreg Roach foreach ($this->childFacts($person, $cfamily, '_GCHI', 'chi', $min_date, $max_date) as $fact) { 2653763c3f2SGreg Roach $facts[] = $fact; 2663763c3f2SGreg Roach } 2673763c3f2SGreg Roach break; 2683763c3f2SGreg Roach } 2693763c3f2SGreg Roach } 2703763c3f2SGreg Roach } 2713763c3f2SGreg Roach break; 2723763c3f2SGreg Roach } 2733763c3f2SGreg Roach 2743763c3f2SGreg Roach // For each child in the family 2753763c3f2SGreg Roach foreach ($family->getChildren() as $child) { 276c0935879SGreg Roach if ($child->xref() == $person->xref()) { 2773763c3f2SGreg Roach // We are not our own sibling! 2783763c3f2SGreg Roach continue; 2793763c3f2SGreg Roach } 2803763c3f2SGreg Roach // add child’s birth 2813763c3f2SGreg Roach if (strpos($SHOW_RELATIVES_EVENTS, '_BIRT' . str_replace('_HSIB', '_SIBL', $option)) !== false) { 2828d0ebef0SGreg Roach foreach ($child->facts(Gedcom::BIRTH_EVENTS) as $fact) { 2833763c3f2SGreg Roach // Always show _BIRT_CHIL, even if the dates are not known 284*8b9cfadbSGreg Roach if ($option == '_CHIL' || $this->includeFact($fact, $min_date, $max_date)) { 2853763c3f2SGreg Roach if ($option == '_GCHI' && $relation == 'dau') { 2863763c3f2SGreg Roach // Convert the event to a close relatives event. 2873763c3f2SGreg Roach $rela_fact = clone($fact); 2883763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_GCH1'); 2893763c3f2SGreg Roach $facts[] = $rela_fact; 2903763c3f2SGreg Roach } elseif ($option == '_GCHI' && $relation == 'son') { 2913763c3f2SGreg Roach // Convert the event to a close relatives event. 2923763c3f2SGreg Roach $rela_fact = clone($fact); 2933763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_GCH2'); 2943763c3f2SGreg Roach $facts[] = $rela_fact; 2953763c3f2SGreg Roach } else { 2963763c3f2SGreg Roach // Convert the event to a close relatives event. 2973763c3f2SGreg Roach $rela_fact = clone($fact); 2983763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . $option); 2993763c3f2SGreg Roach $facts[] = $rela_fact; 3003763c3f2SGreg Roach } 3013763c3f2SGreg Roach } 3023763c3f2SGreg Roach } 3033763c3f2SGreg Roach } 3043763c3f2SGreg Roach // add child’s death 3053763c3f2SGreg Roach if (strpos($SHOW_RELATIVES_EVENTS, '_DEAT' . str_replace('_HSIB', '_SIBL', $option)) !== false) { 3068d0ebef0SGreg Roach foreach ($child->facts(Gedcom::DEATH_EVENTS) as $fact) { 307*8b9cfadbSGreg Roach if ($this->includeFact($fact, $min_date, $max_date)) { 3083763c3f2SGreg Roach if ($option == '_GCHI' && $relation == 'dau') { 3093763c3f2SGreg Roach // Convert the event to a close relatives event. 3103763c3f2SGreg Roach $rela_fact = clone($fact); 3113763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_GCH1'); 3123763c3f2SGreg Roach $facts[] = $rela_fact; 3133763c3f2SGreg Roach } elseif ($option == '_GCHI' && $relation == 'son') { 3143763c3f2SGreg Roach // Convert the event to a close relatives event. 3153763c3f2SGreg Roach $rela_fact = clone($fact); 3163763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_GCH2'); 3173763c3f2SGreg Roach $facts[] = $rela_fact; 3183763c3f2SGreg Roach } else { 3193763c3f2SGreg Roach // Convert the event to a close relatives event. 3203763c3f2SGreg Roach $rela_fact = clone($fact); 3213763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . $option); 3223763c3f2SGreg Roach $facts[] = $rela_fact; 3233763c3f2SGreg Roach } 3243763c3f2SGreg Roach } 3253763c3f2SGreg Roach } 3263763c3f2SGreg Roach } 3273763c3f2SGreg Roach // add child’s marriage 3283763c3f2SGreg Roach if (strstr($SHOW_RELATIVES_EVENTS, '_MARR' . str_replace('_HSIB', '_SIBL', $option))) { 3293763c3f2SGreg Roach foreach ($child->getSpouseFamilies() as $sfamily) { 3308d0ebef0SGreg Roach foreach ($sfamily->facts(['MARR']) as $fact) { 331*8b9cfadbSGreg Roach if ($this->includeFact($fact, $min_date, $max_date)) { 3323763c3f2SGreg Roach if ($option == '_GCHI' && $relation == 'dau') { 3333763c3f2SGreg Roach // Convert the event to a close relatives event. 3343763c3f2SGreg Roach $rela_fact = clone($fact); 3353763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_GCH1'); 3363763c3f2SGreg Roach $facts[] = $rela_fact; 3373763c3f2SGreg Roach } elseif ($option == '_GCHI' && $relation == 'son') { 3383763c3f2SGreg Roach // Convert the event to a close relatives event. 3393763c3f2SGreg Roach $rela_fact = clone($fact); 3403763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_GCH2'); 3413763c3f2SGreg Roach $facts[] = $rela_fact; 3423763c3f2SGreg Roach } else { 3433763c3f2SGreg Roach // Convert the event to a close relatives event. 3443763c3f2SGreg Roach $rela_fact = clone($fact); 3453763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . $option); 3463763c3f2SGreg Roach $facts[] = $rela_fact; 3473763c3f2SGreg Roach } 3483763c3f2SGreg Roach } 3493763c3f2SGreg Roach } 3503763c3f2SGreg Roach } 3513763c3f2SGreg Roach } 3523763c3f2SGreg Roach } 3533763c3f2SGreg Roach 3543763c3f2SGreg Roach return $facts; 3553763c3f2SGreg Roach } 3563763c3f2SGreg Roach 3573763c3f2SGreg Roach /** 3583763c3f2SGreg Roach * Get the events of parents and grandparents. 3593763c3f2SGreg Roach * 3603763c3f2SGreg Roach * @param Individual $person 361cbc1590aSGreg Roach * @param int $sosa 362ee727175SGreg Roach * @param Date $min_date 363ee727175SGreg Roach * @param Date $max_date 3643763c3f2SGreg Roach * 3653763c3f2SGreg Roach * @return Fact[] 3663763c3f2SGreg Roach */ 367*8b9cfadbSGreg Roach private function parentFacts(Individual $person, $sosa, Date $min_date, Date $max_date): array 368c1010edaSGreg Roach { 369f4afa648SGreg Roach $SHOW_RELATIVES_EVENTS = $person->tree()->getPreference('SHOW_RELATIVES_EVENTS'); 3703763c3f2SGreg Roach 37113abd6f3SGreg Roach $facts = []; 3723763c3f2SGreg Roach 3733763c3f2SGreg Roach if ($sosa == 1) { 3743763c3f2SGreg Roach foreach ($person->getChildFamilies() as $family) { 3753763c3f2SGreg Roach // Add siblings 376*8b9cfadbSGreg Roach foreach ($this->childFacts($person, $family, '_SIBL', '', $min_date, $max_date) as $fact) { 3773763c3f2SGreg Roach $facts[] = $fact; 3783763c3f2SGreg Roach } 3793763c3f2SGreg Roach foreach ($family->getSpouses() as $spouse) { 3803763c3f2SGreg Roach foreach ($spouse->getSpouseFamilies() as $sfamily) { 3813763c3f2SGreg Roach if ($family !== $sfamily) { 3823763c3f2SGreg Roach // Add half-siblings 383*8b9cfadbSGreg Roach foreach ($this->childFacts($person, $sfamily, '_HSIB', '', $min_date, $max_date) as $fact) { 3843763c3f2SGreg Roach $facts[] = $fact; 3853763c3f2SGreg Roach } 3863763c3f2SGreg Roach } 3873763c3f2SGreg Roach } 3883763c3f2SGreg Roach // Add grandparents 389*8b9cfadbSGreg Roach foreach ($this->parentFacts($spouse, $spouse->getSex() == 'F' ? 3 : 2, $min_date, $max_date) as $fact) { 3903763c3f2SGreg Roach $facts[] = $fact; 3913763c3f2SGreg Roach } 3923763c3f2SGreg Roach } 3933763c3f2SGreg Roach } 3943763c3f2SGreg Roach 3953763c3f2SGreg Roach if (strstr($SHOW_RELATIVES_EVENTS, '_MARR_PARE')) { 3963763c3f2SGreg Roach // add father/mother marriages 3973763c3f2SGreg Roach foreach ($person->getChildFamilies() as $sfamily) { 3988d0ebef0SGreg Roach foreach ($sfamily->facts(['MARR']) as $fact) { 399*8b9cfadbSGreg Roach if ($this->includeFact($fact, $min_date, $max_date)) { 4003763c3f2SGreg Roach // marriage of parents (to each other) 4013763c3f2SGreg Roach $rela_fact = clone($fact); 4023763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_FAMC'); 4033763c3f2SGreg Roach $facts[] = $rela_fact; 4043763c3f2SGreg Roach } 4053763c3f2SGreg Roach } 4063763c3f2SGreg Roach } 4073763c3f2SGreg Roach foreach ($person->getChildStepFamilies() as $sfamily) { 4088d0ebef0SGreg Roach foreach ($sfamily->facts(['MARR']) as $fact) { 409*8b9cfadbSGreg Roach if ($this->includeFact($fact, $min_date, $max_date)) { 4103763c3f2SGreg Roach // marriage of a parent (to another spouse) 4113763c3f2SGreg Roach // Convert the event to a close relatives event 4123763c3f2SGreg Roach $rela_fact = clone($fact); 4133763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_PARE'); 4143763c3f2SGreg Roach $facts[] = $rela_fact; 4153763c3f2SGreg Roach } 4163763c3f2SGreg Roach } 4173763c3f2SGreg Roach } 4183763c3f2SGreg Roach } 4193763c3f2SGreg Roach } 4203763c3f2SGreg Roach 4213763c3f2SGreg Roach foreach ($person->getChildFamilies() as $family) { 4223763c3f2SGreg Roach foreach ($family->getSpouses() as $parent) { 4233763c3f2SGreg Roach if (strstr($SHOW_RELATIVES_EVENTS, '_DEAT' . ($sosa == 1 ? '_PARE' : '_GPAR'))) { 4248d0ebef0SGreg Roach foreach ($parent->facts(Gedcom::DEATH_EVENTS) as $fact) { 425*8b9cfadbSGreg Roach if ($this->includeFact($fact, $min_date, $max_date)) { 4263763c3f2SGreg Roach switch ($sosa) { 4273763c3f2SGreg Roach case 1: 4283763c3f2SGreg Roach // Convert the event to a close relatives event. 4293763c3f2SGreg Roach $rela_fact = clone($fact); 4303763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_PARE'); 4313763c3f2SGreg Roach $facts[] = $rela_fact; 4323763c3f2SGreg Roach break; 4333763c3f2SGreg Roach case 2: 4343763c3f2SGreg Roach // Convert the event to a close relatives event 4353763c3f2SGreg Roach $rela_fact = clone($fact); 4363763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_GPA1'); 4373763c3f2SGreg Roach $facts[] = $rela_fact; 4383763c3f2SGreg Roach break; 4393763c3f2SGreg Roach case 3: 4403763c3f2SGreg Roach // Convert the event to a close relatives event 4413763c3f2SGreg Roach $rela_fact = clone($fact); 4423763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_GPA2'); 4433763c3f2SGreg Roach $facts[] = $rela_fact; 4443763c3f2SGreg Roach break; 4453763c3f2SGreg Roach } 4463763c3f2SGreg Roach } 4473763c3f2SGreg Roach } 4483763c3f2SGreg Roach } 4493763c3f2SGreg Roach } 4503763c3f2SGreg Roach } 4513763c3f2SGreg Roach 4523763c3f2SGreg Roach return $facts; 4533763c3f2SGreg Roach } 4543763c3f2SGreg Roach 4553763c3f2SGreg Roach /** 4563763c3f2SGreg Roach * Get any historical events. 4573763c3f2SGreg Roach * 45817c50b57SGreg Roach * @param Individual $individual 4593763c3f2SGreg Roach * 4603763c3f2SGreg Roach * @return Fact[] 4613763c3f2SGreg Roach */ 4624ca7e03cSGreg Roach private function historicalFacts(Individual $individual): array 463c1010edaSGreg Roach { 4644ca7e03cSGreg Roach return $this->module_service->findByInterface(ModuleHistoricEventsInterface::class) 46517c50b57SGreg Roach ->map(function (ModuleHistoricEventsInterface $module) use ($individual): Collection { 46617c50b57SGreg Roach return $module->historicEventsForIndividual($individual); 46717c50b57SGreg Roach }) 46817c50b57SGreg Roach ->flatten() 46917c50b57SGreg Roach ->all(); 4703763c3f2SGreg Roach } 4713763c3f2SGreg Roach 4723763c3f2SGreg Roach /** 4733763c3f2SGreg Roach * Get the events of associates. 4743763c3f2SGreg Roach * 4753763c3f2SGreg Roach * @param Individual $person 4763763c3f2SGreg Roach * 4773763c3f2SGreg Roach * @return Fact[] 4783763c3f2SGreg Roach */ 479*8b9cfadbSGreg Roach private function associateFacts(Individual $person): array 480c1010edaSGreg Roach { 48113abd6f3SGreg Roach $facts = []; 4823763c3f2SGreg Roach 483ee727175SGreg Roach /** @var Individual[] $associates */ 4843763c3f2SGreg Roach $associates = array_merge( 4853763c3f2SGreg Roach $person->linkedIndividuals('ASSO'), 4863763c3f2SGreg Roach $person->linkedIndividuals('_ASSO'), 4873763c3f2SGreg Roach $person->linkedFamilies('ASSO'), 4883763c3f2SGreg Roach $person->linkedFamilies('_ASSO') 4893763c3f2SGreg Roach ); 4903763c3f2SGreg Roach foreach ($associates as $associate) { 49130158ae7SGreg Roach foreach ($associate->facts() as $fact) { 4923425616eSGreg Roach $arec = $fact->attribute('_ASSO'); 4933763c3f2SGreg Roach if (!$arec) { 4943425616eSGreg Roach $arec = $fact->attribute('ASSO'); 4953763c3f2SGreg Roach } 496c0935879SGreg Roach if ($arec && trim($arec, '@') === $person->xref()) { 4973763c3f2SGreg Roach // Extract the important details from the fact 4983763c3f2SGreg Roach $factrec = '1 ' . $fact->getTag(); 499138ca96cSGreg Roach if (preg_match('/\n2 DATE .*/', $fact->gedcom(), $match)) { 5003763c3f2SGreg Roach $factrec .= $match[0]; 5013763c3f2SGreg Roach } 502138ca96cSGreg Roach if (preg_match('/\n2 PLAC .*/', $fact->gedcom(), $match)) { 5033763c3f2SGreg Roach $factrec .= $match[0]; 5043763c3f2SGreg Roach } 5053763c3f2SGreg Roach if ($associate instanceof Family) { 5063763c3f2SGreg Roach foreach ($associate->getSpouses() as $spouse) { 507c0935879SGreg Roach $factrec .= "\n2 _ASSO @" . $spouse->xref() . '@'; 5083763c3f2SGreg Roach } 5093763c3f2SGreg Roach } else { 510c0935879SGreg Roach $factrec .= "\n2 _ASSO @" . $associate->xref() . '@'; 5113763c3f2SGreg Roach } 5123763c3f2SGreg Roach $facts[] = new Fact($factrec, $associate, 'asso'); 5133763c3f2SGreg Roach } 5143763c3f2SGreg Roach } 5153763c3f2SGreg Roach } 5163763c3f2SGreg Roach 5173763c3f2SGreg Roach return $facts; 5183763c3f2SGreg Roach } 5193763c3f2SGreg Roach} 520