xref: /webtrees/app/Module/FamilyNavigatorModule.php (revision 28db1f7cfd196ce6d9f5ea1513dcb93a2fdd8036)
1<?php
2namespace Fisharebest\Webtrees;
3
4/**
5 * webtrees: online genealogy
6 * Copyright (C) 2015 webtrees development team
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * Class FamilyNavigatorModule
21 */
22class FamilyNavigatorModule extends Module implements ModuleSidebarInterface {
23
24	const TTL = "<div class='flyout2'>%s</div>";
25	const LNK = "<div class='flyout3' data-href='%s'>%s</div>";
26	const MSG = "<div class='flyout4'>(%s)</div>"; // class flyout4 not used in standard themes
27
28	/** {@inheritdoc} */
29	public function getTitle() {
30		return /* I18N: Name of a module/sidebar */ I18N::translate('Family navigator');
31	}
32
33	/** {@inheritdoc} */
34	public function getDescription() {
35		return /* I18N: Description of the “Family navigator” module */ I18N::translate('A sidebar showing an individual’s close families and relatives.');
36	}
37
38	/** {@inheritdoc} */
39	public function defaultSidebarOrder() {
40		return 20;
41	}
42
43	/** {@inheritdoc} */
44	public function hasSidebarContent() {
45		return !Auth::isSearchEngine();
46	}
47
48	/** {@inheritdoc} */
49	public function getSidebarAjaxContent() {
50		return '';
51	}
52
53	/** {@inheritdoc} */
54	public function getSidebarContent() {
55		global $controller;
56
57		$controller->addInlineJavascript('
58			jQuery("#sb_family_nav_content")
59				.on("click", ".flyout a", function() {
60					return false;
61				})
62				.on("click", ".flyout3", function() {
63					window.location.href = jQuery(this).data("href");
64					return false;
65				});
66		');
67
68		ob_start();
69
70		?>
71		<div id="sb_family_nav_content">
72			<table class="nav_content">
73
74		<?php
75		//-- parent families -------------------------------------------------------------
76		foreach ($controller->record->getChildFamilies() as $family) {
77			$this->drawFamily($family, $controller->record->getChildFamilyLabel($family));
78		}
79		//-- step parents ----------------------------------------------------------------
80		foreach ($controller->record->getChildStepFamilies() as $family) {
81			$this->drawFamily($family, $controller->record->getStepFamilyLabel($family));
82		}
83		//-- spouse and children --------------------------------------------------
84		foreach ($controller->record->getSpouseFamilies() as $family) {
85			$this->drawFamily($family, $controller->record->getSpouseFamilyLabel($family));
86		}
87		//-- step children ----------------------------------------------------------------
88		foreach ($controller->record->getSpouseStepFamilies() as $family) {
89			$this->drawFamily($family, $family->getFullName());
90		}
91		?>
92			</table>
93		</div>
94		<?php
95
96		return ob_get_clean();
97	}
98
99	/**
100	 * @param Family $family
101	 * @param string $title
102	 */
103	private function drawFamily(Family $family, $title) {
104		global $controller, $SHOW_PRIVATE_RELATIONSHIPS;
105
106		?>
107		<tr>
108			<td class="center" colspan="2">
109				<a class="famnav_title" href="<?php echo $family->getHtmlUrl(); ?>">
110					<?php echo $title; ?>
111				</a>
112			</td>
113		</tr>
114		<?php
115		$access_level = $SHOW_PRIVATE_RELATIONSHIPS ? Auth::PRIV_HIDE : Auth::accessLevel($family->getTree());
116		$facts = array_merge($family->getFacts('HUSB', false, $access_level), $family->getFacts('WIFE', false, $access_level));
117		foreach ($facts as $fact) {
118			$spouse = $fact->getTarget();
119			if ($spouse instanceof Individual) {
120				$menu = new Menu(get_close_relationship_name($controller->record, $spouse));
121				$menu->addClass('', 'submenu flyout');
122				$menu->addSubmenu(new Menu($this->getParents($spouse)));
123				?>
124				<tr>
125					<td class="facts_label">
126						<?php echo $menu->getMenu(); ?>
127					</td>
128					<td class="center <?php echo $controller->getPersonStyle($spouse); ?> nam">
129						<a class="famnav_link" href="<?php echo $spouse->getHtmlUrl(); ?>">
130							<?php echo $spouse->getFullName(); ?>
131						</a>
132						<div class="font9">
133							<?php echo $spouse->getLifeSpan(); ?>
134						</div>
135					</td>
136				</tr>
137				<?php
138			}
139		}
140
141		foreach ($family->getFacts('CHIL', false, $access_level) as $fact) {
142			$child = $fact->getTarget();
143			if ($child instanceof Individual) {
144				$menu = new Menu(get_close_relationship_name($controller->record, $child));
145				$menu->addClass('', 'submenu flyout');
146				$menu->addSubmenu(new Menu($this->getFamily($child)));
147				?>
148				<tr>
149					<td class="facts_label">
150						<?php echo $menu->getMenu(); ?>
151					</td>
152					<td class="center <?php echo $controller->getPersonStyle($child); ?> nam">
153						<a class="famnav_link" href="<?php echo $child->getHtmlUrl(); ?>">
154							<?php echo $child->getFullName(); ?>
155						</a>
156						<div class="font9">
157							<?php echo $child->getLifeSpan(); ?>
158						</div>
159					</td>
160				</tr>
161				<?php
162			}
163		}
164	}
165
166	/**
167	 * @param         $person
168	 * @param boolean $showUnknown
169	 *
170	 * @return string
171	 */
172	private function getHTML($person, $showUnknown = false) {
173		if ($person instanceof Individual) {
174			return sprintf(self::LNK, $person->getHtmlUrl(), $person->getFullName());
175		} elseif ($showUnknown) {
176			return sprintf(self::MSG, I18N::translate('unknown'));
177		} else {
178			return '';
179		}
180	}
181
182	/**
183	 * @param Individual $person
184	 *
185	 * @return string
186	 */
187	private function getParents(Individual $person) {
188		$father = null;
189		$mother = null;
190		$html = sprintf(self::TTL, I18N::translate('Parents'));
191		$family = $person->getPrimaryChildFamily();
192		if (!Auth::isSearchEngine() && $person->canShowName() && $family !== null) {
193			$father = $family->getHusband();
194			$mother = $family->getWife();
195			$html .= $this->getHTML($father) .
196					 $this->getHTML($mother);
197
198			// Can only have a step parent if one & only one parent found at this point
199			if ($father instanceof Individual xor $mother instanceof Individual) {
200				$stepParents = '';
201				foreach ($person->getChildStepFamilies() as $family) {
202					if (!$father instanceof Individual) {
203						$stepParents .= $this->getHTML($family->getHusband());
204					} else {
205						$stepParents .= $this->getHTML($family->getWife());
206					}
207				}
208				if ($stepParents) {
209					$relationship = $father instanceof Individual ?
210						I18N::translateContext("father’s wife", "step-mother") : I18N::translateContext("mother’s husband", "step-father");
211					$html .= sprintf(self::TTL, $relationship) . $stepParents;
212				}
213			}
214		}
215		if (!($father instanceof Individual || $mother instanceof Individual)) {
216			$html .= sprintf(self::MSG, I18N::translateContext('unknown family', 'unknown'));
217		}
218		return $html;
219	}
220
221	/**
222	 * @param Individual $person
223	 *
224	 * @return string
225	 */
226	private function getFamily(Individual $person) {
227		$html = '';
228		if ($person->canShowName() && !Auth::isSearchEngine()) {
229			foreach ($person->getSpouseFamilies() as $family) {
230				$spouse = $family->getSpouse($person);
231				$html .= $this->getHTML($spouse, true);
232				$children = $family->getChildren();
233				if (count($children) > 0) {
234					$html .= "<ul class='clist'>";
235					foreach ($children as $child) {
236						$html .= '<li>' . $this->getHTML($child) . '</li>';
237					}
238					$html .= '</ul>';
239				}
240			}
241		}
242		if (!$html) {
243			$html = sprintf(self::MSG, I18N::translate('none'));
244		}
245		return sprintf(self::TTL, I18N::translate('Family')) . $html;
246	}
247
248}
249