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; 280e62c4b8SGreg Roachuse Fisharebest\Webtrees\Module; 290e62c4b8SGreg Roachuse Fisharebest\Webtrees\Site; 303763c3f2SGreg Roach 313763c3f2SGreg Roach/** 323763c3f2SGreg Roach * Class IndividualFactsTabModule 333763c3f2SGreg Roach */ 34*37eb8894SGreg Roachclass IndividualFactsTabModule extends AbstractModule implements ModuleTabInterface 35c1010edaSGreg Roach{ 3649a243cbSGreg Roach use ModuleTabTrait; 3749a243cbSGreg Roach 38961ec755SGreg Roach /** 39961ec755SGreg Roach * How should this module be labelled on tabs, menus, etc.? 40961ec755SGreg Roach * 41961ec755SGreg Roach * @return string 42961ec755SGreg Roach */ 4349a243cbSGreg Roach public function title(): string 44c1010edaSGreg Roach { 45bbb76c12SGreg Roach /* I18N: Name of a module/tab on the individual page. */ 46bbb76c12SGreg Roach return I18N::translate('Facts and events'); 473763c3f2SGreg Roach } 483763c3f2SGreg Roach 49961ec755SGreg Roach /** 50961ec755SGreg Roach * A sentence describing what this module does. 51961ec755SGreg Roach * 52961ec755SGreg Roach * @return string 53961ec755SGreg Roach */ 5449a243cbSGreg Roach public function description(): string 55c1010edaSGreg Roach { 56bbb76c12SGreg Roach /* I18N: Description of the “Facts and events” module */ 57bbb76c12SGreg Roach return I18N::translate('A tab showing the facts and events of an individual.'); 583763c3f2SGreg Roach } 593763c3f2SGreg Roach 6049a243cbSGreg Roach /** 6149a243cbSGreg Roach * The default position for this tab. It can be changed in the control panel. 6249a243cbSGreg Roach * 6349a243cbSGreg Roach * @return int 6449a243cbSGreg Roach */ 65cbf4b7faSGreg Roach public function defaultTabOrder(): int 66cbf4b7faSGreg Roach { 67353b36abSGreg Roach return 2; 683763c3f2SGreg Roach } 693763c3f2SGreg Roach 703763c3f2SGreg Roach /** {@inheritdoc} */ 718f53f488SRico Sonntag public function isGrayedOut(Individual $individual): bool 72c1010edaSGreg Roach { 733763c3f2SGreg Roach return false; 743763c3f2SGreg Roach } 753763c3f2SGreg Roach 763763c3f2SGreg Roach /** {@inheritdoc} */ 779b34404bSGreg Roach public function getTabContent(Individual $individual): string 78c1010edaSGreg Roach { 79ee727175SGreg Roach // Only include events of close relatives that are between birth and death 80ee727175SGreg Roach $min_date = $individual->getEstimatedBirthDate(); 81ee727175SGreg Roach $max_date = $individual->getEstimatedDeathDate(); 82ee727175SGreg Roach 8313abd6f3SGreg Roach $indifacts = []; 843763c3f2SGreg Roach // The individual’s own facts 8530158ae7SGreg Roach foreach ($individual->facts() as $fact) { 863763c3f2SGreg Roach switch ($fact->getTag()) { 873763c3f2SGreg Roach case 'SEX': 883763c3f2SGreg Roach case 'NAME': 893763c3f2SGreg Roach case 'SOUR': 903763c3f2SGreg Roach case 'OBJE': 913763c3f2SGreg Roach case 'NOTE': 923763c3f2SGreg Roach case 'FAMC': 933763c3f2SGreg Roach case 'FAMS': 943763c3f2SGreg Roach break; 9549a243cbSGreg Roach 963763c3f2SGreg Roach default: 9763276d8fSGreg Roach $use_extra_info_module = Module::findByComponent('sidebar', $individual->tree(), Auth::user()) 9849a243cbSGreg Roach ->filter(function (ModuleInterface $module): bool { 9949a243cbSGreg Roach return $module instanceof ExtraInformationModule; 10049a243cbSGreg Roach })->isNotEmpty(); 10149a243cbSGreg Roach 10249a243cbSGreg Roach if (!$use_extra_info_module || !ExtraInformationModule::showFact($fact)) { 1033763c3f2SGreg Roach $indifacts[] = $fact; 1043763c3f2SGreg Roach } 1053763c3f2SGreg Roach break; 1063763c3f2SGreg Roach } 1073763c3f2SGreg Roach } 1083763c3f2SGreg Roach 1093763c3f2SGreg Roach // Add spouse-family facts 110225e381fSGreg Roach foreach ($individual->getSpouseFamilies() as $family) { 11130158ae7SGreg Roach foreach ($family->facts() as $fact) { 1123763c3f2SGreg Roach switch ($fact->getTag()) { 1133763c3f2SGreg Roach case 'SOUR': 1143763c3f2SGreg Roach case 'NOTE': 1153763c3f2SGreg Roach case 'OBJE': 1163763c3f2SGreg Roach case 'CHAN': 1173763c3f2SGreg Roach case '_UID': 1183763c3f2SGreg Roach case 'RIN': 1193763c3f2SGreg Roach case 'HUSB': 1203763c3f2SGreg Roach case 'WIFE': 1213763c3f2SGreg Roach case 'CHIL': 1223763c3f2SGreg Roach break; 1233763c3f2SGreg Roach default: 1243763c3f2SGreg Roach $indifacts[] = $fact; 1253763c3f2SGreg Roach break; 1263763c3f2SGreg Roach } 1273763c3f2SGreg Roach } 128ee727175SGreg Roach 129225e381fSGreg Roach $spouse = $family->getSpouse($individual); 130ee727175SGreg Roach 131ee727175SGreg Roach if ($spouse instanceof Individual) { 132ee727175SGreg Roach $spouse_facts = self::spouseFacts($individual, $spouse, $min_date, $max_date); 133ee727175SGreg Roach $indifacts = array_merge($indifacts, $spouse_facts); 1343763c3f2SGreg Roach } 1353763c3f2SGreg Roach 136ee727175SGreg Roach $child_facts = self::childFacts($individual, $family, '_CHIL', '', $min_date, $max_date); 137ee727175SGreg Roach $indifacts = array_merge($indifacts, $child_facts); 1383763c3f2SGreg Roach } 139225e381fSGreg Roach 140ee727175SGreg Roach $parent_facts = self::parentFacts($individual, 1, $min_date, $max_date); 141ee727175SGreg Roach $associate_facts = self::associateFacts($individual); 142ee727175SGreg Roach $historical_facts = self::historicalFacts($individual, $min_date, $max_date); 143225e381fSGreg Roach 144ee727175SGreg Roach $indifacts = array_merge($indifacts, $parent_facts, $associate_facts, $historical_facts); 1453763c3f2SGreg Roach 1463d7a8a4cSGreg Roach Functions::sortFacts($indifacts); 1473763c3f2SGreg Roach 148a8cd57e1SGreg Roach return view('modules/personal_facts/tab', [ 149225e381fSGreg Roach 'can_edit' => $individual->canEdit(), 150ee727175SGreg Roach 'has_historical_facts' => !empty($historical_facts), 151225e381fSGreg Roach 'individual' => $individual, 152225e381fSGreg Roach 'facts' => $indifacts, 153225e381fSGreg Roach ]); 1543763c3f2SGreg Roach } 1553763c3f2SGreg Roach 156ee727175SGreg Roach /** 157ee727175SGreg Roach * Does a relative event occur within a date range (i.e. the individual's lifetime)? 158ee727175SGreg Roach * 159ee727175SGreg Roach * @param Fact $fact 160ee727175SGreg Roach * @param Date $min_date 161ee727175SGreg Roach * @param Date $max_date 162ee727175SGreg Roach * 163ee727175SGreg Roach * @return bool 164ee727175SGreg Roach */ 165b3b1d905SGreg Roach private static function includeFact(Fact $fact, Date $min_date, Date $max_date): bool 166b3b1d905SGreg Roach { 1672decada7SGreg Roach $fact_date = $fact->date(); 168ee727175SGreg Roach 169ee727175SGreg Roach return $fact_date->isOK() && Date::compare($min_date, $fact_date) <= 0 && Date::compare($fact_date, $max_date) <= 0; 170ee727175SGreg Roach } 171ee727175SGreg Roach 1723763c3f2SGreg Roach /** {@inheritdoc} */ 1738f53f488SRico Sonntag public function hasTabContent(Individual $individual): bool 174c1010edaSGreg Roach { 1753763c3f2SGreg Roach return true; 1763763c3f2SGreg Roach } 1773763c3f2SGreg Roach 1783763c3f2SGreg Roach /** {@inheritdoc} */ 1798f53f488SRico Sonntag public function canLoadAjax(): bool 180c1010edaSGreg Roach { 18115d603e7SGreg Roach return false; 1823763c3f2SGreg Roach } 1833763c3f2SGreg Roach 1843763c3f2SGreg Roach /** 1853763c3f2SGreg Roach * Spouse facts that are shown on an individual’s page. 1863763c3f2SGreg Roach * 1873763c3f2SGreg Roach * @param Individual $individual Show events that occured during the lifetime of this individual 1883763c3f2SGreg Roach * @param Individual $spouse Show events of this individual 189ee727175SGreg Roach * @param Date $min_date 190ee727175SGreg Roach * @param Date $max_date 1913763c3f2SGreg Roach * 1923763c3f2SGreg Roach * @return Fact[] 1933763c3f2SGreg Roach */ 194ee727175SGreg Roach private static function spouseFacts(Individual $individual, Individual $spouse, Date $min_date, Date $max_date): array 195c1010edaSGreg Roach { 196f4afa648SGreg Roach $SHOW_RELATIVES_EVENTS = $individual->tree()->getPreference('SHOW_RELATIVES_EVENTS'); 1973763c3f2SGreg Roach 19813abd6f3SGreg Roach $facts = []; 1993763c3f2SGreg Roach if (strstr($SHOW_RELATIVES_EVENTS, '_DEAT_SPOU')) { 2008d0ebef0SGreg Roach foreach ($spouse->facts(Gedcom::DEATH_EVENTS) as $fact) { 201ee727175SGreg Roach if (self::includeFact($fact, $min_date, $max_date)) { 2023763c3f2SGreg Roach // Convert the event to a close relatives event. 2033763c3f2SGreg Roach $rela_fact = clone($fact); 2043763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_SPOU'); 2053763c3f2SGreg Roach $facts[] = $rela_fact; 2063763c3f2SGreg Roach } 2073763c3f2SGreg Roach } 2083763c3f2SGreg Roach } 2093763c3f2SGreg Roach 2103763c3f2SGreg Roach return $facts; 2113763c3f2SGreg Roach } 2123763c3f2SGreg Roach 2133763c3f2SGreg Roach /** 2143763c3f2SGreg Roach * Get the events of children and grandchildren. 2153763c3f2SGreg Roach * 2163763c3f2SGreg Roach * @param Individual $person 2173763c3f2SGreg Roach * @param Family $family 2183763c3f2SGreg Roach * @param string $option 2193763c3f2SGreg Roach * @param string $relation 220ee727175SGreg Roach * @param Date $min_date 221ee727175SGreg Roach * @param Date $max_date 2223763c3f2SGreg Roach * 2233763c3f2SGreg Roach * @return Fact[] 2243763c3f2SGreg Roach */ 225ee727175SGreg Roach private static function childFacts(Individual $person, Family $family, $option, $relation, Date $min_date, Date $max_date): array 226c1010edaSGreg Roach { 227f4afa648SGreg Roach $SHOW_RELATIVES_EVENTS = $person->tree()->getPreference('SHOW_RELATIVES_EVENTS'); 2283763c3f2SGreg Roach 22913abd6f3SGreg Roach $facts = []; 2303763c3f2SGreg Roach 2313763c3f2SGreg Roach // Deal with recursion. 2323763c3f2SGreg Roach switch ($option) { 2333763c3f2SGreg Roach case '_CHIL': 2343763c3f2SGreg Roach // Add grandchildren 2353763c3f2SGreg Roach foreach ($family->getChildren() as $child) { 2363763c3f2SGreg Roach foreach ($child->getSpouseFamilies() as $cfamily) { 2373763c3f2SGreg Roach switch ($child->getSex()) { 2383763c3f2SGreg Roach case 'M': 239ee727175SGreg Roach foreach (self::childFacts($person, $cfamily, '_GCHI', 'son', $min_date, $max_date) as $fact) { 2403763c3f2SGreg Roach $facts[] = $fact; 2413763c3f2SGreg Roach } 2423763c3f2SGreg Roach break; 2433763c3f2SGreg Roach case 'F': 244ee727175SGreg Roach foreach (self::childFacts($person, $cfamily, '_GCHI', 'dau', $min_date, $max_date) as $fact) { 2453763c3f2SGreg Roach $facts[] = $fact; 2463763c3f2SGreg Roach } 2473763c3f2SGreg Roach break; 2483763c3f2SGreg Roach default: 249ee727175SGreg Roach foreach (self::childFacts($person, $cfamily, '_GCHI', 'chi', $min_date, $max_date) as $fact) { 2503763c3f2SGreg Roach $facts[] = $fact; 2513763c3f2SGreg Roach } 2523763c3f2SGreg Roach break; 2533763c3f2SGreg Roach } 2543763c3f2SGreg Roach } 2553763c3f2SGreg Roach } 2563763c3f2SGreg Roach break; 2573763c3f2SGreg Roach } 2583763c3f2SGreg Roach 2593763c3f2SGreg Roach // For each child in the family 2603763c3f2SGreg Roach foreach ($family->getChildren() as $child) { 261c0935879SGreg Roach if ($child->xref() == $person->xref()) { 2623763c3f2SGreg Roach // We are not our own sibling! 2633763c3f2SGreg Roach continue; 2643763c3f2SGreg Roach } 2653763c3f2SGreg Roach // add child’s birth 2663763c3f2SGreg Roach if (strpos($SHOW_RELATIVES_EVENTS, '_BIRT' . str_replace('_HSIB', '_SIBL', $option)) !== false) { 2678d0ebef0SGreg Roach foreach ($child->facts(Gedcom::BIRTH_EVENTS) as $fact) { 2683763c3f2SGreg Roach // Always show _BIRT_CHIL, even if the dates are not known 269ee727175SGreg Roach if ($option == '_CHIL' || self::includeFact($fact, $min_date, $max_date)) { 2703763c3f2SGreg Roach if ($option == '_GCHI' && $relation == 'dau') { 2713763c3f2SGreg Roach // Convert the event to a close relatives event. 2723763c3f2SGreg Roach $rela_fact = clone($fact); 2733763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_GCH1'); 2743763c3f2SGreg Roach $facts[] = $rela_fact; 2753763c3f2SGreg Roach } elseif ($option == '_GCHI' && $relation == 'son') { 2763763c3f2SGreg Roach // Convert the event to a close relatives event. 2773763c3f2SGreg Roach $rela_fact = clone($fact); 2783763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_GCH2'); 2793763c3f2SGreg Roach $facts[] = $rela_fact; 2803763c3f2SGreg Roach } else { 2813763c3f2SGreg Roach // Convert the event to a close relatives event. 2823763c3f2SGreg Roach $rela_fact = clone($fact); 2833763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . $option); 2843763c3f2SGreg Roach $facts[] = $rela_fact; 2853763c3f2SGreg Roach } 2863763c3f2SGreg Roach } 2873763c3f2SGreg Roach } 2883763c3f2SGreg Roach } 2893763c3f2SGreg Roach // add child’s death 2903763c3f2SGreg Roach if (strpos($SHOW_RELATIVES_EVENTS, '_DEAT' . str_replace('_HSIB', '_SIBL', $option)) !== false) { 2918d0ebef0SGreg Roach foreach ($child->facts(Gedcom::DEATH_EVENTS) as $fact) { 292ee727175SGreg Roach if (self::includeFact($fact, $min_date, $max_date)) { 2933763c3f2SGreg Roach if ($option == '_GCHI' && $relation == 'dau') { 2943763c3f2SGreg Roach // Convert the event to a close relatives event. 2953763c3f2SGreg Roach $rela_fact = clone($fact); 2963763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_GCH1'); 2973763c3f2SGreg Roach $facts[] = $rela_fact; 2983763c3f2SGreg Roach } elseif ($option == '_GCHI' && $relation == 'son') { 2993763c3f2SGreg Roach // Convert the event to a close relatives event. 3003763c3f2SGreg Roach $rela_fact = clone($fact); 3013763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_GCH2'); 3023763c3f2SGreg Roach $facts[] = $rela_fact; 3033763c3f2SGreg Roach } else { 3043763c3f2SGreg Roach // Convert the event to a close relatives event. 3053763c3f2SGreg Roach $rela_fact = clone($fact); 3063763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . $option); 3073763c3f2SGreg Roach $facts[] = $rela_fact; 3083763c3f2SGreg Roach } 3093763c3f2SGreg Roach } 3103763c3f2SGreg Roach } 3113763c3f2SGreg Roach } 3123763c3f2SGreg Roach // add child’s marriage 3133763c3f2SGreg Roach if (strstr($SHOW_RELATIVES_EVENTS, '_MARR' . str_replace('_HSIB', '_SIBL', $option))) { 3143763c3f2SGreg Roach foreach ($child->getSpouseFamilies() as $sfamily) { 3158d0ebef0SGreg Roach foreach ($sfamily->facts(['MARR']) as $fact) { 316ee727175SGreg Roach if (self::includeFact($fact, $min_date, $max_date)) { 3173763c3f2SGreg Roach if ($option == '_GCHI' && $relation == 'dau') { 3183763c3f2SGreg Roach // Convert the event to a close relatives event. 3193763c3f2SGreg Roach $rela_fact = clone($fact); 3203763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_GCH1'); 3213763c3f2SGreg Roach $facts[] = $rela_fact; 3223763c3f2SGreg Roach } elseif ($option == '_GCHI' && $relation == 'son') { 3233763c3f2SGreg Roach // Convert the event to a close relatives event. 3243763c3f2SGreg Roach $rela_fact = clone($fact); 3253763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_GCH2'); 3263763c3f2SGreg Roach $facts[] = $rela_fact; 3273763c3f2SGreg Roach } else { 3283763c3f2SGreg Roach // Convert the event to a close relatives event. 3293763c3f2SGreg Roach $rela_fact = clone($fact); 3303763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . $option); 3313763c3f2SGreg Roach $facts[] = $rela_fact; 3323763c3f2SGreg Roach } 3333763c3f2SGreg Roach } 3343763c3f2SGreg Roach } 3353763c3f2SGreg Roach } 3363763c3f2SGreg Roach } 3373763c3f2SGreg Roach } 3383763c3f2SGreg Roach 3393763c3f2SGreg Roach return $facts; 3403763c3f2SGreg Roach } 3413763c3f2SGreg Roach 3423763c3f2SGreg Roach /** 3433763c3f2SGreg Roach * Get the events of parents and grandparents. 3443763c3f2SGreg Roach * 3453763c3f2SGreg Roach * @param Individual $person 346cbc1590aSGreg Roach * @param int $sosa 347ee727175SGreg Roach * @param Date $min_date 348ee727175SGreg Roach * @param Date $max_date 3493763c3f2SGreg Roach * 3503763c3f2SGreg Roach * @return Fact[] 3513763c3f2SGreg Roach */ 352ee727175SGreg Roach private static function parentFacts(Individual $person, $sosa, Date $min_date, Date $max_date): array 353c1010edaSGreg Roach { 354f4afa648SGreg Roach $SHOW_RELATIVES_EVENTS = $person->tree()->getPreference('SHOW_RELATIVES_EVENTS'); 3553763c3f2SGreg Roach 35613abd6f3SGreg Roach $facts = []; 3573763c3f2SGreg Roach 3583763c3f2SGreg Roach if ($sosa == 1) { 3593763c3f2SGreg Roach foreach ($person->getChildFamilies() as $family) { 3603763c3f2SGreg Roach // Add siblings 361ee727175SGreg Roach foreach (self::childFacts($person, $family, '_SIBL', '', $min_date, $max_date) as $fact) { 3623763c3f2SGreg Roach $facts[] = $fact; 3633763c3f2SGreg Roach } 3643763c3f2SGreg Roach foreach ($family->getSpouses() as $spouse) { 3653763c3f2SGreg Roach foreach ($spouse->getSpouseFamilies() as $sfamily) { 3663763c3f2SGreg Roach if ($family !== $sfamily) { 3673763c3f2SGreg Roach // Add half-siblings 368ee727175SGreg Roach foreach (self::childFacts($person, $sfamily, '_HSIB', '', $min_date, $max_date) as $fact) { 3693763c3f2SGreg Roach $facts[] = $fact; 3703763c3f2SGreg Roach } 3713763c3f2SGreg Roach } 3723763c3f2SGreg Roach } 3733763c3f2SGreg Roach // Add grandparents 374ee727175SGreg Roach foreach (self::parentFacts($spouse, $spouse->getSex() == 'F' ? 3 : 2, $min_date, $max_date) as $fact) { 3753763c3f2SGreg Roach $facts[] = $fact; 3763763c3f2SGreg Roach } 3773763c3f2SGreg Roach } 3783763c3f2SGreg Roach } 3793763c3f2SGreg Roach 3803763c3f2SGreg Roach if (strstr($SHOW_RELATIVES_EVENTS, '_MARR_PARE')) { 3813763c3f2SGreg Roach // add father/mother marriages 3823763c3f2SGreg Roach foreach ($person->getChildFamilies() as $sfamily) { 3838d0ebef0SGreg Roach foreach ($sfamily->facts(['MARR']) as $fact) { 384ee727175SGreg Roach if (self::includeFact($fact, $min_date, $max_date)) { 3853763c3f2SGreg Roach // marriage of parents (to each other) 3863763c3f2SGreg Roach $rela_fact = clone($fact); 3873763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_FAMC'); 3883763c3f2SGreg Roach $facts[] = $rela_fact; 3893763c3f2SGreg Roach } 3903763c3f2SGreg Roach } 3913763c3f2SGreg Roach } 3923763c3f2SGreg Roach foreach ($person->getChildStepFamilies() as $sfamily) { 3938d0ebef0SGreg Roach foreach ($sfamily->facts(['MARR']) as $fact) { 394ee727175SGreg Roach if (self::includeFact($fact, $min_date, $max_date)) { 3953763c3f2SGreg Roach // marriage of a parent (to another spouse) 3963763c3f2SGreg Roach // Convert the event to a close relatives event 3973763c3f2SGreg Roach $rela_fact = clone($fact); 3983763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_PARE'); 3993763c3f2SGreg Roach $facts[] = $rela_fact; 4003763c3f2SGreg Roach } 4013763c3f2SGreg Roach } 4023763c3f2SGreg Roach } 4033763c3f2SGreg Roach } 4043763c3f2SGreg Roach } 4053763c3f2SGreg Roach 4063763c3f2SGreg Roach foreach ($person->getChildFamilies() as $family) { 4073763c3f2SGreg Roach foreach ($family->getSpouses() as $parent) { 4083763c3f2SGreg Roach if (strstr($SHOW_RELATIVES_EVENTS, '_DEAT' . ($sosa == 1 ? '_PARE' : '_GPAR'))) { 4098d0ebef0SGreg Roach foreach ($parent->facts(Gedcom::DEATH_EVENTS) as $fact) { 410ee727175SGreg Roach if (self::includeFact($fact, $min_date, $max_date)) { 4113763c3f2SGreg Roach switch ($sosa) { 4123763c3f2SGreg Roach case 1: 4133763c3f2SGreg Roach // Convert the event to a close relatives event. 4143763c3f2SGreg Roach $rela_fact = clone($fact); 4153763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_PARE'); 4163763c3f2SGreg Roach $facts[] = $rela_fact; 4173763c3f2SGreg Roach break; 4183763c3f2SGreg Roach case 2: 4193763c3f2SGreg Roach // Convert the event to a close relatives event 4203763c3f2SGreg Roach $rela_fact = clone($fact); 4213763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_GPA1'); 4223763c3f2SGreg Roach $facts[] = $rela_fact; 4233763c3f2SGreg Roach break; 4243763c3f2SGreg Roach case 3: 4253763c3f2SGreg Roach // Convert the event to a close relatives event 4263763c3f2SGreg Roach $rela_fact = clone($fact); 4273763c3f2SGreg Roach $rela_fact->setTag('_' . $fact->getTag() . '_GPA2'); 4283763c3f2SGreg Roach $facts[] = $rela_fact; 4293763c3f2SGreg Roach break; 4303763c3f2SGreg Roach } 4313763c3f2SGreg Roach } 4323763c3f2SGreg Roach } 4333763c3f2SGreg Roach } 4343763c3f2SGreg Roach } 4353763c3f2SGreg Roach } 4363763c3f2SGreg Roach 4373763c3f2SGreg Roach return $facts; 4383763c3f2SGreg Roach } 4393763c3f2SGreg Roach 4403763c3f2SGreg Roach /** 4413763c3f2SGreg Roach * Get any historical events. 4423763c3f2SGreg Roach * 4433763c3f2SGreg Roach * @param Individual $person 444ee727175SGreg Roach * @param Date $min_date 445ee727175SGreg Roach * @param Date $max_date 4463763c3f2SGreg Roach * 4473763c3f2SGreg Roach * @return Fact[] 4483763c3f2SGreg Roach */ 449ee727175SGreg Roach private static function historicalFacts(Individual $person, Date $min_date, Date $max_date): array 450c1010edaSGreg Roach { 45113abd6f3SGreg Roach $facts = []; 4523763c3f2SGreg Roach 4533763c3f2SGreg Roach if (file_exists(Site::getPreference('INDEX_DIRECTORY') . 'histo.' . WT_LOCALE . '.php')) { 45413abd6f3SGreg Roach $histo = []; 4553763c3f2SGreg Roach require Site::getPreference('INDEX_DIRECTORY') . 'histo.' . WT_LOCALE . '.php'; 4563763c3f2SGreg Roach foreach ($histo as $hist) { 4573763c3f2SGreg Roach $fact = new Fact($hist, $person, 'histo'); 458ee727175SGreg Roach 459ee727175SGreg Roach if (self::includeFact($fact, $min_date, $max_date)) { 4603763c3f2SGreg Roach $facts[] = $fact; 4613763c3f2SGreg Roach } 4623763c3f2SGreg Roach } 4633763c3f2SGreg Roach } 4643763c3f2SGreg Roach 4653763c3f2SGreg Roach return $facts; 4663763c3f2SGreg Roach } 4673763c3f2SGreg Roach 4683763c3f2SGreg Roach /** 4693763c3f2SGreg Roach * Get the events of associates. 4703763c3f2SGreg Roach * 4713763c3f2SGreg Roach * @param Individual $person 4723763c3f2SGreg Roach * 4733763c3f2SGreg Roach * @return Fact[] 4743763c3f2SGreg Roach */ 4758f53f488SRico Sonntag private static function associateFacts(Individual $person): array 476c1010edaSGreg Roach { 47713abd6f3SGreg Roach $facts = []; 4783763c3f2SGreg Roach 479ee727175SGreg Roach /** @var Individual[] $associates */ 4803763c3f2SGreg Roach $associates = array_merge( 4813763c3f2SGreg Roach $person->linkedIndividuals('ASSO'), 4823763c3f2SGreg Roach $person->linkedIndividuals('_ASSO'), 4833763c3f2SGreg Roach $person->linkedFamilies('ASSO'), 4843763c3f2SGreg Roach $person->linkedFamilies('_ASSO') 4853763c3f2SGreg Roach ); 4863763c3f2SGreg Roach foreach ($associates as $associate) { 48730158ae7SGreg Roach foreach ($associate->facts() as $fact) { 4883425616eSGreg Roach $arec = $fact->attribute('_ASSO'); 4893763c3f2SGreg Roach if (!$arec) { 4903425616eSGreg Roach $arec = $fact->attribute('ASSO'); 4913763c3f2SGreg Roach } 492c0935879SGreg Roach if ($arec && trim($arec, '@') === $person->xref()) { 4933763c3f2SGreg Roach // Extract the important details from the fact 4943763c3f2SGreg Roach $factrec = '1 ' . $fact->getTag(); 495138ca96cSGreg Roach if (preg_match('/\n2 DATE .*/', $fact->gedcom(), $match)) { 4963763c3f2SGreg Roach $factrec .= $match[0]; 4973763c3f2SGreg Roach } 498138ca96cSGreg Roach if (preg_match('/\n2 PLAC .*/', $fact->gedcom(), $match)) { 4993763c3f2SGreg Roach $factrec .= $match[0]; 5003763c3f2SGreg Roach } 5013763c3f2SGreg Roach if ($associate instanceof Family) { 5023763c3f2SGreg Roach foreach ($associate->getSpouses() as $spouse) { 503c0935879SGreg Roach $factrec .= "\n2 _ASSO @" . $spouse->xref() . '@'; 5043763c3f2SGreg Roach } 5053763c3f2SGreg Roach } else { 506c0935879SGreg Roach $factrec .= "\n2 _ASSO @" . $associate->xref() . '@'; 5073763c3f2SGreg Roach } 5083763c3f2SGreg Roach $facts[] = new Fact($factrec, $associate, 'asso'); 5093763c3f2SGreg Roach } 5103763c3f2SGreg Roach } 5113763c3f2SGreg Roach } 5123763c3f2SGreg Roach 5133763c3f2SGreg Roach return $facts; 5143763c3f2SGreg Roach } 5153763c3f2SGreg Roach} 516