xref: /webtrees/app/Module/IndividualFactsTabModule.php (revision e0486a06db0c3b0e065a465cc3d95c8b317be9a7)
13763c3f2SGreg Roach<?php
23763c3f2SGreg Roach/**
33763c3f2SGreg Roach * webtrees: online genealogy
46bdf7674SGreg Roach * Copyright (C) 2017 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 */
1676692c8bSGreg Roachnamespace Fisharebest\Webtrees\Module;
1776692c8bSGreg Roach
180e62c4b8SGreg Roachuse Fisharebest\Webtrees\Date;
190e62c4b8SGreg Roachuse Fisharebest\Webtrees\Fact;
200e62c4b8SGreg Roachuse Fisharebest\Webtrees\Family;
213d7a8a4cSGreg Roachuse Fisharebest\Webtrees\Functions\Functions;
223d7a8a4cSGreg Roachuse Fisharebest\Webtrees\Functions\FunctionsPrint;
233d7a8a4cSGreg Roachuse Fisharebest\Webtrees\Functions\FunctionsPrintFacts;
240e62c4b8SGreg Roachuse Fisharebest\Webtrees\I18N;
250e62c4b8SGreg Roachuse Fisharebest\Webtrees\Individual;
260e62c4b8SGreg Roachuse Fisharebest\Webtrees\Module;
270e62c4b8SGreg Roachuse Fisharebest\Webtrees\Site;
283763c3f2SGreg Roach
293763c3f2SGreg Roach/**
303763c3f2SGreg Roach * Class IndividualFactsTabModule
313763c3f2SGreg Roach */
32e2a378d3SGreg Roachclass IndividualFactsTabModule extends AbstractModule implements ModuleTabInterface {
333763c3f2SGreg Roach	/** {@inheritdoc} */
343763c3f2SGreg Roach	public function getTitle() {
353763c3f2SGreg Roach		return /* I18N: Name of a module/tab on the individual page. */ I18N::translate('Facts and events');
363763c3f2SGreg Roach	}
373763c3f2SGreg Roach
383763c3f2SGreg Roach	/** {@inheritdoc} */
393763c3f2SGreg Roach	public function getDescription() {
403763c3f2SGreg Roach		return /* I18N: Description of the “Facts and events” module */ I18N::translate('A tab showing the facts and events of an individual.');
413763c3f2SGreg Roach	}
423763c3f2SGreg Roach
433763c3f2SGreg Roach	/** {@inheritdoc} */
443763c3f2SGreg Roach	public function defaultTabOrder() {
453763c3f2SGreg Roach		return 10;
463763c3f2SGreg Roach	}
473763c3f2SGreg Roach
483763c3f2SGreg Roach	/** {@inheritdoc} */
493763c3f2SGreg Roach	public function isGrayedOut() {
503763c3f2SGreg Roach		return false;
513763c3f2SGreg Roach	}
523763c3f2SGreg Roach
533763c3f2SGreg Roach	/** {@inheritdoc} */
543763c3f2SGreg Roach	public function getTabContent() {
553763c3f2SGreg Roach		global $controller;
563763c3f2SGreg Roach		$EXPAND_HISTO_EVENTS = false;
573763c3f2SGreg Roach
5813abd6f3SGreg Roach		$indifacts = [];
593763c3f2SGreg Roach		// The individual’s own facts
603763c3f2SGreg Roach		foreach ($controller->record->getFacts() as $fact) {
613763c3f2SGreg Roach			switch ($fact->getTag()) {
623763c3f2SGreg Roach			case 'SEX':
633763c3f2SGreg Roach			case 'NAME':
643763c3f2SGreg Roach			case 'SOUR':
653763c3f2SGreg Roach			case 'OBJE':
663763c3f2SGreg Roach			case 'NOTE':
673763c3f2SGreg Roach			case 'FAMC':
683763c3f2SGreg Roach			case 'FAMS':
693763c3f2SGreg Roach				break;
703763c3f2SGreg Roach			default:
713763c3f2SGreg Roach				if (!array_key_exists('extra_info', Module::getActiveSidebars($controller->record->getTree())) || !ExtraInformationModule::showFact($fact)) {
723763c3f2SGreg Roach					$indifacts[] = $fact;
733763c3f2SGreg Roach				}
743763c3f2SGreg Roach				break;
753763c3f2SGreg Roach			}
763763c3f2SGreg Roach		}
773763c3f2SGreg Roach
783763c3f2SGreg Roach		// Add spouse-family facts
793763c3f2SGreg Roach		foreach ($controller->record->getSpouseFamilies() as $family) {
803763c3f2SGreg Roach			foreach ($family->getFacts() as $fact) {
813763c3f2SGreg Roach				switch ($fact->getTag()) {
823763c3f2SGreg Roach				case 'SOUR':
833763c3f2SGreg Roach				case 'NOTE':
843763c3f2SGreg Roach				case 'OBJE':
853763c3f2SGreg Roach				case 'CHAN':
863763c3f2SGreg Roach				case '_UID':
873763c3f2SGreg Roach				case 'RIN':
883763c3f2SGreg Roach				case 'HUSB':
893763c3f2SGreg Roach				case 'WIFE':
903763c3f2SGreg Roach				case 'CHIL':
913763c3f2SGreg Roach					break;
923763c3f2SGreg Roach				default:
933763c3f2SGreg Roach					$indifacts[] = $fact;
943763c3f2SGreg Roach					break;
953763c3f2SGreg Roach				}
963763c3f2SGreg Roach			}
973763c3f2SGreg Roach			$spouse = $family->getSpouse($controller->record);
983763c3f2SGreg Roach			if ($spouse) {
993763c3f2SGreg Roach				foreach (self::spouseFacts($controller->record, $spouse) as $fact) {
1003763c3f2SGreg Roach					$indifacts[] = $fact;
1013763c3f2SGreg Roach				}
1023763c3f2SGreg Roach			}
1033763c3f2SGreg Roach			foreach (self::childFacts($controller->record, $family, '_CHIL', '') as $fact) {
1043763c3f2SGreg Roach				$indifacts[] = $fact;
1053763c3f2SGreg Roach			}
1063763c3f2SGreg Roach		}
1073763c3f2SGreg Roach
1083763c3f2SGreg Roach		foreach (self::parentFacts($controller->record, 1) as $fact) {
1093763c3f2SGreg Roach			$indifacts[] = $fact;
1103763c3f2SGreg Roach		}
1113763c3f2SGreg Roach		foreach (self::historicalFacts($controller->record) as $fact) {
1123763c3f2SGreg Roach			$indifacts[] = $fact;
1133763c3f2SGreg Roach		}
1143763c3f2SGreg Roach		foreach (self::associateFacts($controller->record) as $fact) {
1153763c3f2SGreg Roach			$indifacts[] = $fact;
1163763c3f2SGreg Roach		}
1173763c3f2SGreg Roach
1183d7a8a4cSGreg Roach		Functions::sortFacts($indifacts);
1193763c3f2SGreg Roach
1203763c3f2SGreg Roach		ob_start();
121877e7017SGreg Roach		?>
122*e0486a06SGreg Roach		<table class="table wt-facts-table">
123877e7017SGreg Roach			<tbody>
124877e7017SGreg Roach				<tr>
125*e0486a06SGreg Roach					<td colspan="2">
126877e7017SGreg Roach						<?php if ($controller->record->getTree()->getPreference('SHOW_RELATIVES_EVENTS')) : ?>
127877e7017SGreg Roach						<label>
12823c362a9SGreg Roach							<input id="show-relatives-facts" type="checkbox">
12915d603e7SGreg Roach							<?= I18N::translate('Events of close relatives') ?>
130877e7017SGreg Roach						</label>
13115d603e7SGreg Roach						<?php endif ?>
132877e7017SGreg Roach						<?php if (file_exists(Site::getPreference('INDEX_DIRECTORY') . 'histo.' . WT_LOCALE . '.php')) : ?>
133877e7017SGreg Roach						<label>
13423c362a9SGreg Roach							<input id="show-historical-facts" type="checkbox">
13515d603e7SGreg Roach							<?= I18N::translate('Historical facts') ?>
136877e7017SGreg Roach						</label>
13715d603e7SGreg Roach						<?php endif ?>
138877e7017SGreg Roach					</td>
139877e7017SGreg Roach				</tr>
140877e7017SGreg Roach				<?php
141673157b0SGreg Roach
142dc46b574SDavid Drury		if (!$indifacts) {
143*e0486a06SGreg Roach			echo '<tr><td colspan="2">', I18N::translate('There are no facts for this individual.'), '</td></tr>';
144dc46b574SDavid Drury		}
1453763c3f2SGreg Roach
1463763c3f2SGreg Roach		foreach ($indifacts as $fact) {
1473d7a8a4cSGreg Roach			FunctionsPrintFacts::printFact($fact, $controller->record);
1483763c3f2SGreg Roach		}
1493763c3f2SGreg Roach
1503763c3f2SGreg Roach		//-- new fact link
1513763c3f2SGreg Roach		if ($controller->record->canEdit()) {
1523d7a8a4cSGreg Roach			FunctionsPrint::printAddNewFact($controller->record->getXref(), $indifacts, 'INDI');
1533763c3f2SGreg Roach		}
1543763c3f2SGreg Roach
155877e7017SGreg Roach		?>
156877e7017SGreg Roach			</tbody>
157877e7017SGreg Roach		</table>
158877e7017SGreg Roach		<script>
15915d603e7SGreg Roach			//persistent_toggle("show-relatives-facts", "tr.rela");
16015d603e7SGreg Roach			//persistent_toggle("show-historical-facts", "tr.histo");
161877e7017SGreg Roach		</script>
162877e7017SGreg Roach		<?php
1633763c3f2SGreg Roach
1643763c3f2SGreg Roach		return '<div id="' . $this->getName() . '_content">' . ob_get_clean() . '</div>';
1653763c3f2SGreg Roach	}
1663763c3f2SGreg Roach
1673763c3f2SGreg Roach	/** {@inheritdoc} */
1683763c3f2SGreg Roach	public function hasTabContent() {
1693763c3f2SGreg Roach		return true;
1703763c3f2SGreg Roach	}
1713763c3f2SGreg Roach
1723763c3f2SGreg Roach	/** {@inheritdoc} */
1733763c3f2SGreg Roach	public function canLoadAjax() {
17415d603e7SGreg Roach		return false;
1753763c3f2SGreg Roach	}
1763763c3f2SGreg Roach
1773763c3f2SGreg Roach	/** {@inheritdoc} */
1783763c3f2SGreg Roach	public function getPreLoadContent() {
1793763c3f2SGreg Roach		return '';
1803763c3f2SGreg Roach	}
1813763c3f2SGreg Roach
1823763c3f2SGreg Roach	/**
1833763c3f2SGreg Roach	 * Spouse facts that are shown on an individual’s page.
1843763c3f2SGreg Roach	 *
1853763c3f2SGreg Roach	 * @param Individual $individual Show events that occured during the lifetime of this individual
1863763c3f2SGreg Roach	 * @param Individual $spouse     Show events of this individual
1873763c3f2SGreg Roach	 *
1883763c3f2SGreg Roach	 * @return Fact[]
1893763c3f2SGreg Roach	 */
1903763c3f2SGreg Roach	private static function spouseFacts(Individual $individual, Individual $spouse) {
1913763c3f2SGreg Roach		$SHOW_RELATIVES_EVENTS = $individual->getTree()->getPreference('SHOW_RELATIVES_EVENTS');
1923763c3f2SGreg Roach
19313abd6f3SGreg Roach		$facts = [];
1943763c3f2SGreg Roach		if (strstr($SHOW_RELATIVES_EVENTS, '_DEAT_SPOU')) {
1953763c3f2SGreg Roach			// Only include events between birth and death
1963763c3f2SGreg Roach			$birt_date = $individual->getEstimatedBirthDate();
1973763c3f2SGreg Roach			$deat_date = $individual->getEstimatedDeathDate();
1983763c3f2SGreg Roach
1993763c3f2SGreg Roach			foreach ($spouse->getFacts(WT_EVENTS_DEAT) as $fact) {
2003763c3f2SGreg Roach
2013763c3f2SGreg Roach				$fact_date = $fact->getDate();
2023763c3f2SGreg Roach				if ($fact_date->isOK() && Date::compare($birt_date, $fact_date) <= 0 && Date::compare($fact_date, $deat_date) <= 0) {
2033763c3f2SGreg Roach					// Convert the event to a close relatives event.
2043763c3f2SGreg Roach					$rela_fact = clone($fact);
2053763c3f2SGreg Roach					$rela_fact->setTag('_' . $fact->getTag() . '_SPOU');
2063763c3f2SGreg Roach					$facts[] = $rela_fact;
2073763c3f2SGreg Roach				}
2083763c3f2SGreg Roach			}
2093763c3f2SGreg Roach		}
2103763c3f2SGreg Roach
2113763c3f2SGreg Roach		return $facts;
2123763c3f2SGreg Roach	}
2133763c3f2SGreg Roach
2143763c3f2SGreg Roach	/**
2153763c3f2SGreg Roach	 * Get the events of children and grandchildren.
2163763c3f2SGreg Roach	 *
2173763c3f2SGreg Roach	 * @param Individual $person
2183763c3f2SGreg Roach	 * @param Family     $family
2193763c3f2SGreg Roach	 * @param string     $option
2203763c3f2SGreg Roach	 * @param string     $relation
2213763c3f2SGreg Roach	 *
2223763c3f2SGreg Roach	 * @return Fact[]
2233763c3f2SGreg Roach	 */
2243763c3f2SGreg Roach	private static function childFacts(Individual $person, Family $family, $option, $relation) {
2253763c3f2SGreg Roach		global $controller;
2263763c3f2SGreg Roach
2273763c3f2SGreg Roach		$SHOW_RELATIVES_EVENTS = $person->getTree()->getPreference('SHOW_RELATIVES_EVENTS');
2283763c3f2SGreg Roach
22913abd6f3SGreg Roach		$facts = [];
2303763c3f2SGreg Roach
2313763c3f2SGreg Roach		// Only include events between birth and death
2323763c3f2SGreg Roach		$birt_date = $controller->record->getEstimatedBirthDate();
2333763c3f2SGreg Roach		$deat_date = $controller->record->getEstimatedDeathDate();
2343763c3f2SGreg Roach
2353763c3f2SGreg Roach		// Deal with recursion.
2363763c3f2SGreg Roach		switch ($option) {
2373763c3f2SGreg Roach		case '_CHIL':
2383763c3f2SGreg Roach			// Add grandchildren
2393763c3f2SGreg Roach			foreach ($family->getChildren() as $child) {
2403763c3f2SGreg Roach				foreach ($child->getSpouseFamilies() as $cfamily) {
2413763c3f2SGreg Roach					switch ($child->getSex()) {
2423763c3f2SGreg Roach					case 'M':
2433763c3f2SGreg Roach						foreach (self::childFacts($person, $cfamily, '_GCHI', 'son') as $fact) {
2443763c3f2SGreg Roach							$facts[] = $fact;
2453763c3f2SGreg Roach						}
2463763c3f2SGreg Roach						break;
2473763c3f2SGreg Roach					case 'F':
2483763c3f2SGreg Roach						foreach (self::childFacts($person, $cfamily, '_GCHI', 'dau') as $fact) {
2493763c3f2SGreg Roach							$facts[] = $fact;
2503763c3f2SGreg Roach						}
2513763c3f2SGreg Roach						break;
2523763c3f2SGreg Roach					default:
2533763c3f2SGreg Roach						foreach (self::childFacts($person, $cfamily, '_GCHI', 'chi') as $fact) {
2543763c3f2SGreg Roach							$facts[] = $fact;
2553763c3f2SGreg Roach						}
2563763c3f2SGreg Roach						break;
2573763c3f2SGreg Roach					}
2583763c3f2SGreg Roach				}
2593763c3f2SGreg Roach			}
2603763c3f2SGreg Roach			break;
2613763c3f2SGreg Roach		}
2623763c3f2SGreg Roach
2633763c3f2SGreg Roach		// For each child in the family
2643763c3f2SGreg Roach		foreach ($family->getChildren() as $child) {
2653763c3f2SGreg Roach			if ($child->getXref() == $person->getXref()) {
2663763c3f2SGreg Roach				// We are not our own sibling!
2673763c3f2SGreg Roach				continue;
2683763c3f2SGreg Roach			}
2693763c3f2SGreg Roach			// add child’s birth
2703763c3f2SGreg Roach			if (strpos($SHOW_RELATIVES_EVENTS, '_BIRT' . str_replace('_HSIB', '_SIBL', $option)) !== false) {
2713763c3f2SGreg Roach				foreach ($child->getFacts(WT_EVENTS_BIRT) as $fact) {
2723763c3f2SGreg Roach					$sgdate = $fact->getDate();
2733763c3f2SGreg Roach					// Always show _BIRT_CHIL, even if the dates are not known
2743763c3f2SGreg Roach					if ($option == '_CHIL' || $sgdate->isOK() && Date::compare($birt_date, $sgdate) <= 0 && Date::compare($sgdate, $deat_date) <= 0) {
2753763c3f2SGreg Roach						if ($option == '_GCHI' && $relation == 'dau') {
2763763c3f2SGreg Roach							// Convert the event to a close relatives event.
2773763c3f2SGreg Roach							$rela_fact = clone($fact);
2783763c3f2SGreg Roach							$rela_fact->setTag('_' . $fact->getTag() . '_GCH1');
2793763c3f2SGreg Roach							$facts[] = $rela_fact;
2803763c3f2SGreg Roach						} elseif ($option == '_GCHI' && $relation == 'son') {
2813763c3f2SGreg Roach							// Convert the event to a close relatives event.
2823763c3f2SGreg Roach							$rela_fact = clone($fact);
2833763c3f2SGreg Roach							$rela_fact->setTag('_' . $fact->getTag() . '_GCH2');
2843763c3f2SGreg Roach							$facts[] = $rela_fact;
2853763c3f2SGreg Roach						} else {
2863763c3f2SGreg Roach							// Convert the event to a close relatives event.
2873763c3f2SGreg Roach							$rela_fact = clone($fact);
2883763c3f2SGreg Roach							$rela_fact->setTag('_' . $fact->getTag() . $option);
2893763c3f2SGreg Roach							$facts[] = $rela_fact;
2903763c3f2SGreg Roach						}
2913763c3f2SGreg Roach					}
2923763c3f2SGreg Roach				}
2933763c3f2SGreg Roach			}
2943763c3f2SGreg Roach			// add child’s death
2953763c3f2SGreg Roach			if (strpos($SHOW_RELATIVES_EVENTS, '_DEAT' . str_replace('_HSIB', '_SIBL', $option)) !== false) {
2963763c3f2SGreg Roach				foreach ($child->getFacts(WT_EVENTS_DEAT) as $fact) {
2973763c3f2SGreg Roach					$sgdate = $fact->getDate();
2983763c3f2SGreg Roach					if ($sgdate->isOK() && Date::compare($birt_date, $sgdate) <= 0 && Date::compare($sgdate, $deat_date) <= 0) {
2993763c3f2SGreg Roach						if ($option == '_GCHI' && $relation == 'dau') {
3003763c3f2SGreg Roach							// Convert the event to a close relatives event.
3013763c3f2SGreg Roach							$rela_fact = clone($fact);
3023763c3f2SGreg Roach							$rela_fact->setTag('_' . $fact->getTag() . '_GCH1');
3033763c3f2SGreg Roach							$facts[] = $rela_fact;
3043763c3f2SGreg Roach						} elseif ($option == '_GCHI' && $relation == 'son') {
3053763c3f2SGreg Roach							// Convert the event to a close relatives event.
3063763c3f2SGreg Roach							$rela_fact = clone($fact);
3073763c3f2SGreg Roach							$rela_fact->setTag('_' . $fact->getTag() . '_GCH2');
3083763c3f2SGreg Roach							$facts[] = $rela_fact;
3093763c3f2SGreg Roach						} else {
3103763c3f2SGreg Roach							// Convert the event to a close relatives event.
3113763c3f2SGreg Roach							$rela_fact = clone($fact);
3123763c3f2SGreg Roach							$rela_fact->setTag('_' . $fact->getTag() . $option);
3133763c3f2SGreg Roach							$facts[] = $rela_fact;
3143763c3f2SGreg Roach						}
3153763c3f2SGreg Roach					}
3163763c3f2SGreg Roach				}
3173763c3f2SGreg Roach			}
3183763c3f2SGreg Roach			// add child’s marriage
3193763c3f2SGreg Roach			if (strstr($SHOW_RELATIVES_EVENTS, '_MARR' . str_replace('_HSIB', '_SIBL', $option))) {
3203763c3f2SGreg Roach				foreach ($child->getSpouseFamilies() as $sfamily) {
3213763c3f2SGreg Roach					foreach ($sfamily->getFacts(WT_EVENTS_MARR) as $fact) {
3223763c3f2SGreg Roach						$sgdate = $fact->getDate();
3233763c3f2SGreg Roach						if ($sgdate->isOK() && Date::compare($birt_date, $sgdate) <= 0 && Date::compare($sgdate, $deat_date) <= 0) {
3243763c3f2SGreg Roach							if ($option == '_GCHI' && $relation == 'dau') {
3253763c3f2SGreg Roach								// Convert the event to a close relatives event.
3263763c3f2SGreg Roach								$rela_fact = clone($fact);
3273763c3f2SGreg Roach								$rela_fact->setTag('_' . $fact->getTag() . '_GCH1');
3283763c3f2SGreg Roach								$facts[] = $rela_fact;
3293763c3f2SGreg Roach							} elseif ($option == '_GCHI' && $relation == 'son') {
3303763c3f2SGreg Roach								// Convert the event to a close relatives event.
3313763c3f2SGreg Roach								$rela_fact = clone($fact);
3323763c3f2SGreg Roach								$rela_fact->setTag('_' . $fact->getTag() . '_GCH2');
3333763c3f2SGreg Roach								$facts[] = $rela_fact;
3343763c3f2SGreg Roach							} else {
3353763c3f2SGreg Roach								// Convert the event to a close relatives event.
3363763c3f2SGreg Roach								$rela_fact = clone($fact);
3373763c3f2SGreg Roach								$rela_fact->setTag('_' . $fact->getTag() . $option);
3383763c3f2SGreg Roach								$facts[] = $rela_fact;
3393763c3f2SGreg Roach							}
3403763c3f2SGreg Roach						}
3413763c3f2SGreg Roach					}
3423763c3f2SGreg Roach				}
3433763c3f2SGreg Roach			}
3443763c3f2SGreg Roach		}
3453763c3f2SGreg Roach
3463763c3f2SGreg Roach		return $facts;
3473763c3f2SGreg Roach	}
3483763c3f2SGreg Roach
3493763c3f2SGreg Roach	/**
3503763c3f2SGreg Roach	 * Get the events of parents and grandparents.
3513763c3f2SGreg Roach	 *
3523763c3f2SGreg Roach	 * @param Individual $person
353cbc1590aSGreg Roach	 * @param int        $sosa
3543763c3f2SGreg Roach	 *
3553763c3f2SGreg Roach	 * @return Fact[]
3563763c3f2SGreg Roach	 */
3573763c3f2SGreg Roach	private static function parentFacts(Individual $person, $sosa) {
3583763c3f2SGreg Roach		global $controller;
3593763c3f2SGreg Roach
3603763c3f2SGreg Roach		$SHOW_RELATIVES_EVENTS = $person->getTree()->getPreference('SHOW_RELATIVES_EVENTS');
3613763c3f2SGreg Roach
36213abd6f3SGreg Roach		$facts = [];
3633763c3f2SGreg Roach
3643763c3f2SGreg Roach		// Only include events between birth and death
3653763c3f2SGreg Roach		$birt_date = $controller->record->getEstimatedBirthDate();
3663763c3f2SGreg Roach		$deat_date = $controller->record->getEstimatedDeathDate();
3673763c3f2SGreg Roach
3683763c3f2SGreg Roach		if ($sosa == 1) {
3693763c3f2SGreg Roach			foreach ($person->getChildFamilies() as $family) {
3703763c3f2SGreg Roach				// Add siblings
3713763c3f2SGreg Roach				foreach (self::childFacts($person, $family, '_SIBL', '') as $fact) {
3723763c3f2SGreg Roach					$facts[] = $fact;
3733763c3f2SGreg Roach				}
3743763c3f2SGreg Roach				foreach ($family->getSpouses() as $spouse) {
3753763c3f2SGreg Roach					foreach ($spouse->getSpouseFamilies() as $sfamily) {
3763763c3f2SGreg Roach						if ($family !== $sfamily) {
3773763c3f2SGreg Roach							// Add half-siblings
3783763c3f2SGreg Roach							foreach (self::childFacts($person, $sfamily, '_HSIB', '') as $fact) {
3793763c3f2SGreg Roach								$facts[] = $fact;
3803763c3f2SGreg Roach							}
3813763c3f2SGreg Roach						}
3823763c3f2SGreg Roach					}
3833763c3f2SGreg Roach					// Add grandparents
3843763c3f2SGreg Roach					foreach (self::parentFacts($spouse, $spouse->getSex() == 'F' ? 3 : 2) as $fact) {
3853763c3f2SGreg Roach						$facts[] = $fact;
3863763c3f2SGreg Roach					}
3873763c3f2SGreg Roach				}
3883763c3f2SGreg Roach			}
3893763c3f2SGreg Roach
3903763c3f2SGreg Roach			if (strstr($SHOW_RELATIVES_EVENTS, '_MARR_PARE')) {
3913763c3f2SGreg Roach				// add father/mother marriages
3923763c3f2SGreg Roach				foreach ($person->getChildFamilies() as $sfamily) {
3933763c3f2SGreg Roach					foreach ($sfamily->getFacts(WT_EVENTS_MARR) as $fact) {
3943763c3f2SGreg Roach						if ($fact->getDate()->isOK() && Date::compare($birt_date, $fact->getDate()) <= 0 && Date::compare($fact->getDate(), $deat_date) <= 0) {
3953763c3f2SGreg Roach							// marriage of parents (to each other)
3963763c3f2SGreg Roach							$rela_fact = clone($fact);
3973763c3f2SGreg Roach							$rela_fact->setTag('_' . $fact->getTag() . '_FAMC');
3983763c3f2SGreg Roach							$facts[] = $rela_fact;
3993763c3f2SGreg Roach						}
4003763c3f2SGreg Roach					}
4013763c3f2SGreg Roach				}
4023763c3f2SGreg Roach				foreach ($person->getChildStepFamilies() as $sfamily) {
4033763c3f2SGreg Roach					foreach ($sfamily->getFacts(WT_EVENTS_MARR) as $fact) {
4043763c3f2SGreg Roach						if ($fact->getDate()->isOK() && Date::compare($birt_date, $fact->getDate()) <= 0 && Date::compare($fact->getDate(), $deat_date) <= 0) {
4053763c3f2SGreg Roach							// marriage of a parent (to another spouse)
4063763c3f2SGreg Roach							// Convert the event to a close relatives event
4073763c3f2SGreg Roach							$rela_fact = clone($fact);
4083763c3f2SGreg Roach							$rela_fact->setTag('_' . $fact->getTag() . '_PARE');
4093763c3f2SGreg Roach							$facts[] = $rela_fact;
4103763c3f2SGreg Roach						}
4113763c3f2SGreg Roach					}
4123763c3f2SGreg Roach				}
4133763c3f2SGreg Roach			}
4143763c3f2SGreg Roach		}
4153763c3f2SGreg Roach
4163763c3f2SGreg Roach		foreach ($person->getChildFamilies() as $family) {
4173763c3f2SGreg Roach			foreach ($family->getSpouses() as $parent) {
4183763c3f2SGreg Roach				if (strstr($SHOW_RELATIVES_EVENTS, '_DEAT' . ($sosa == 1 ? '_PARE' : '_GPAR'))) {
4193763c3f2SGreg Roach					foreach ($parent->getFacts(WT_EVENTS_DEAT) as $fact) {
4203763c3f2SGreg Roach						if ($fact->getDate()->isOK() && Date::compare($birt_date, $fact->getDate()) <= 0 && Date::compare($fact->getDate(), $deat_date) <= 0) {
4213763c3f2SGreg Roach							switch ($sosa) {
4223763c3f2SGreg Roach							case 1:
4233763c3f2SGreg Roach								// Convert the event to a close relatives event.
4243763c3f2SGreg Roach								$rela_fact = clone($fact);
4253763c3f2SGreg Roach								$rela_fact->setTag('_' . $fact->getTag() . '_PARE');
4263763c3f2SGreg Roach								$facts[] = $rela_fact;
4273763c3f2SGreg Roach								break;
4283763c3f2SGreg Roach							case 2:
4293763c3f2SGreg Roach								// Convert the event to a close relatives event
4303763c3f2SGreg Roach								$rela_fact = clone($fact);
4313763c3f2SGreg Roach								$rela_fact->setTag('_' . $fact->getTag() . '_GPA1');
4323763c3f2SGreg Roach								$facts[] = $rela_fact;
4333763c3f2SGreg Roach								break;
4343763c3f2SGreg Roach							case 3:
4353763c3f2SGreg Roach								// Convert the event to a close relatives event
4363763c3f2SGreg Roach								$rela_fact = clone($fact);
4373763c3f2SGreg Roach								$rela_fact->setTag('_' . $fact->getTag() . '_GPA2');
4383763c3f2SGreg Roach								$facts[] = $rela_fact;
4393763c3f2SGreg Roach								break;
4403763c3f2SGreg Roach							}
4413763c3f2SGreg Roach						}
4423763c3f2SGreg Roach					}
4433763c3f2SGreg Roach				}
4443763c3f2SGreg Roach			}
4453763c3f2SGreg Roach		}
4463763c3f2SGreg Roach
4473763c3f2SGreg Roach		return $facts;
4483763c3f2SGreg Roach	}
4493763c3f2SGreg Roach
4503763c3f2SGreg Roach	/**
4513763c3f2SGreg Roach	 * Get any historical events.
4523763c3f2SGreg Roach	 *
4533763c3f2SGreg Roach	 * @param Individual $person
4543763c3f2SGreg Roach	 *
4553763c3f2SGreg Roach	 * @return Fact[]
4563763c3f2SGreg Roach	 */
4573763c3f2SGreg Roach	private static function historicalFacts(Individual $person) {
4583763c3f2SGreg Roach		$SHOW_RELATIVES_EVENTS = $person->getTree()->getPreference('SHOW_RELATIVES_EVENTS');
4593763c3f2SGreg Roach
46013abd6f3SGreg Roach		$facts = [];
4613763c3f2SGreg Roach
4623763c3f2SGreg Roach		if ($SHOW_RELATIVES_EVENTS) {
4633763c3f2SGreg Roach			// Only include events between birth and death
4643763c3f2SGreg Roach			$birt_date = $person->getEstimatedBirthDate();
4653763c3f2SGreg Roach			$deat_date = $person->getEstimatedDeathDate();
4663763c3f2SGreg Roach
4673763c3f2SGreg Roach			if (file_exists(Site::getPreference('INDEX_DIRECTORY') . 'histo.' . WT_LOCALE . '.php')) {
46813abd6f3SGreg Roach				$histo = [];
4693763c3f2SGreg Roach				require Site::getPreference('INDEX_DIRECTORY') . 'histo.' . WT_LOCALE . '.php';
4703763c3f2SGreg Roach				foreach ($histo as $hist) {
4713763c3f2SGreg Roach					$fact  = new Fact($hist, $person, 'histo');
4723763c3f2SGreg Roach					$sdate = $fact->getDate();
4733763c3f2SGreg Roach					if ($sdate->isOK() && Date::compare($birt_date, $sdate) <= 0 && Date::compare($sdate, $deat_date) <= 0) {
4743763c3f2SGreg Roach						$facts[] = $fact;
4753763c3f2SGreg Roach					}
4763763c3f2SGreg Roach				}
4773763c3f2SGreg Roach			}
4783763c3f2SGreg Roach		}
4793763c3f2SGreg Roach
4803763c3f2SGreg Roach		return $facts;
4813763c3f2SGreg Roach	}
4823763c3f2SGreg Roach
4833763c3f2SGreg Roach	/**
4843763c3f2SGreg Roach	 * Get the events of associates.
4853763c3f2SGreg Roach	 *
4863763c3f2SGreg Roach	 * @param Individual $person
4873763c3f2SGreg Roach	 *
4883763c3f2SGreg Roach	 * @return Fact[]
4893763c3f2SGreg Roach	 */
4903763c3f2SGreg Roach	private static function associateFacts(Individual $person) {
49113abd6f3SGreg Roach		$facts = [];
4923763c3f2SGreg Roach
4933763c3f2SGreg Roach		$associates = array_merge(
4943763c3f2SGreg Roach			$person->linkedIndividuals('ASSO'),
4953763c3f2SGreg Roach			$person->linkedIndividuals('_ASSO'),
4963763c3f2SGreg Roach			$person->linkedFamilies('ASSO'),
4973763c3f2SGreg Roach			$person->linkedFamilies('_ASSO')
4983763c3f2SGreg Roach		);
4993763c3f2SGreg Roach		foreach ($associates as $associate) {
5003763c3f2SGreg Roach			foreach ($associate->getFacts() as $fact) {
5013763c3f2SGreg Roach				$arec = $fact->getAttribute('_ASSO');
5023763c3f2SGreg Roach				if (!$arec) {
5033763c3f2SGreg Roach					$arec = $fact->getAttribute('ASSO');
5043763c3f2SGreg Roach				}
5053763c3f2SGreg Roach				if ($arec && trim($arec, '@') === $person->getXref()) {
5063763c3f2SGreg Roach					// Extract the important details from the fact
5073763c3f2SGreg Roach					$factrec = '1 ' . $fact->getTag();
5083763c3f2SGreg Roach					if (preg_match('/\n2 DATE .*/', $fact->getGedcom(), $match)) {
5093763c3f2SGreg Roach						$factrec .= $match[0];
5103763c3f2SGreg Roach					}
5113763c3f2SGreg Roach					if (preg_match('/\n2 PLAC .*/', $fact->getGedcom(), $match)) {
5123763c3f2SGreg Roach						$factrec .= $match[0];
5133763c3f2SGreg Roach					}
5143763c3f2SGreg Roach					if ($associate instanceof Family) {
5153763c3f2SGreg Roach						foreach ($associate->getSpouses() as $spouse) {
5163763c3f2SGreg Roach							$factrec .= "\n2 _ASSO @" . $spouse->getXref() . '@';
5173763c3f2SGreg Roach						}
5183763c3f2SGreg Roach					} else {
5193763c3f2SGreg Roach						$factrec .= "\n2 _ASSO @" . $associate->getXref() . '@';
5203763c3f2SGreg Roach					}
5213763c3f2SGreg Roach					$facts[] = new Fact($factrec, $associate, 'asso');
5223763c3f2SGreg Roach				}
5233763c3f2SGreg Roach			}
5243763c3f2SGreg Roach		}
5253763c3f2SGreg Roach
5263763c3f2SGreg Roach		return $facts;
5273763c3f2SGreg Roach	}
5283763c3f2SGreg Roach}
529