xref: /webtrees/app/Module/FamilyNavigatorModule.php (revision ffd703ea1e658c7dcb5e5f1f9ef137a420f2d167)
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 AbstractModule 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;
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		foreach ($family->getSpouses() as $spouse) {
116			$menu = new Menu(get_close_relationship_name($controller->record, $spouse));
117			$menu->addClass('', 'submenu flyout');
118			$menu->addSubmenu(new Menu($this->getParents($spouse)));
119			?>
120			<tr>
121				<td class="facts_label">
122					<?php echo $menu->getMenu(); ?>
123				</td>
124				<td class="center <?php echo $controller->getPersonStyle($spouse); ?> nam">
125					<a class="famnav_link" href="<?php echo $spouse->getHtmlUrl(); ?>">
126						<?php echo $spouse->getFullName(); ?>
127					</a>
128					<div class="font9">
129						<?php echo $spouse->getLifeSpan(); ?>
130					</div>
131				</td>
132			</tr>
133		<?php
134		}
135
136		foreach ($family->getChildren() as $child) {
137			$menu = new Menu(get_close_relationship_name($controller->record, $child));
138			$menu->addClass('', 'submenu flyout');
139			$menu->addSubmenu(new Menu($this->getFamily($child)));
140			?>
141			<tr>
142				<td class="facts_label">
143					<?php echo $menu->getMenu(); ?>
144				</td>
145				<td class="center <?php echo $controller->getPersonStyle($child); ?> nam">
146					<a class="famnav_link" href="<?php echo $child->getHtmlUrl(); ?>">
147						<?php echo $child->getFullName(); ?>
148					</a>
149					<div class="font9">
150						<?php echo $child->getLifeSpan(); ?>
151					</div>
152				</td>
153			</tr>
154		<?php
155		}
156	}
157
158	/**
159	 * @param         $person
160	 * @param boolean $showUnknown
161	 *
162	 * @return string
163	 */
164	private function getHTML($person, $showUnknown = false) {
165		if ($person instanceof Individual) {
166			return sprintf(self::LNK, $person->getHtmlUrl(), $person->getFullName());
167		} elseif ($showUnknown) {
168			return sprintf(self::MSG, I18N::translate('unknown'));
169		} else {
170			return '';
171		}
172	}
173
174	/**
175	 * @param Individual $person
176	 *
177	 * @return string
178	 */
179	private function getParents(Individual $person) {
180		$father = null;
181		$mother = null;
182		$html = sprintf(self::TTL, I18N::translate('Parents'));
183		$family = $person->getPrimaryChildFamily();
184		if (!Auth::isSearchEngine() && $person->canShowName() && $family !== null) {
185			$father = $family->getHusband();
186			$mother = $family->getWife();
187			$html .= $this->getHTML($father) .
188					 $this->getHTML($mother);
189
190			// Can only have a step parent if one & only one parent found at this point
191			if ($father instanceof Individual xor $mother instanceof Individual) {
192				$stepParents = '';
193				foreach ($person->getChildStepFamilies() as $family) {
194					if (!$father instanceof Individual) {
195						$stepParents .= $this->getHTML($family->getHusband());
196					} else {
197						$stepParents .= $this->getHTML($family->getWife());
198					}
199				}
200				if ($stepParents) {
201					$relationship = $father instanceof Individual ?
202						I18N::translateContext("father’s wife", "step-mother") : I18N::translateContext("mother’s husband", "step-father");
203					$html .= sprintf(self::TTL, $relationship) . $stepParents;
204				}
205			}
206		}
207		if (!($father instanceof Individual || $mother instanceof Individual)) {
208			$html .= sprintf(self::MSG, I18N::translateContext('unknown family', 'unknown'));
209		}
210		return $html;
211	}
212
213	/**
214	 * @param Individual $person
215	 *
216	 * @return string
217	 */
218	private function getFamily(Individual $person) {
219		$html = '';
220		if ($person->canShowName() && !Auth::isSearchEngine()) {
221			foreach ($person->getSpouseFamilies() as $family) {
222				$spouse = $family->getSpouse($person);
223				$html .= $this->getHTML($spouse, true);
224				$children = $family->getChildren();
225				if (count($children) > 0) {
226					$html .= "<ul class='clist'>";
227					foreach ($children as $child) {
228						$html .= '<li>' . $this->getHTML($child) . '</li>';
229					}
230					$html .= '</ul>';
231				}
232			}
233		}
234		if (!$html) {
235			$html = sprintf(self::MSG, I18N::translate('none'));
236		}
237		return sprintf(self::TTL, I18N::translate('Family')) . $html;
238	}
239
240}
241