xref: /webtrees/app/Module/InteractiveTreeModule.php (revision ed53a9c0a479c5871db36fde10b575b33b9a209b)
1<?php
2/**
3 * webtrees: online genealogy
4 * Copyright (C) 2017 webtrees development team
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16namespace Fisharebest\Webtrees\Module;
17
18use Fisharebest\Webtrees\Controller\ChartController;
19use Fisharebest\Webtrees\Filter;
20use Fisharebest\Webtrees\I18N;
21use Fisharebest\Webtrees\Individual;
22use Fisharebest\Webtrees\Menu;
23use Fisharebest\Webtrees\Module\InteractiveTree\TreeView;
24
25/**
26 * Class InteractiveTreeModule
27 * Tip : you could change the number of generations loaded before ajax calls both in individual page and in treeview page to optimize speed and server load
28 */
29class InteractiveTreeModule extends AbstractModule implements ModuleTabInterface, ModuleChartInterface {
30	/** {@inheritdoc} */
31	public function getTitle() {
32		return /* I18N: Name of a module */ I18N::translate('Interactive tree');
33	}
34
35	/** {@inheritdoc} */
36	public function getDescription() {
37		return /* I18N: Description of the “Interactive tree” module */ I18N::translate('An interactive tree, showing all the ancestors and descendants of an individual.');
38	}
39
40	/** {@inheritdoc} */
41	public function defaultTabOrder() {
42		return 68;
43	}
44
45	/** {@inheritdoc} */
46	public function getTabContent() {
47		global $controller;
48
49		$tv              = new TreeView('tvTab');
50		list($html, $js) = $tv->drawViewport($controller->record, 3);
51
52		return
53			'<script src="' . $this->js() . '"></script>' .
54			'<script>' . $js . '</script>' .
55			$html;
56	}
57
58	/** {@inheritdoc} */
59	public function hasTabContent() {
60		return true;
61	}
62
63	/** {@inheritdoc} */
64	public function isGrayedOut() {
65		return false;
66	}
67
68	/** {@inheritdoc} */
69	public function canLoadAjax() {
70		return true;
71	}
72
73	/**
74	 * Return a menu item for this chart.
75	 *
76	 * @param Individual $individual
77	 *
78	 * @return Menu|null
79	 */
80	public function getChartMenu(Individual $individual) {
81		return new Menu(
82			$this->getTitle(),
83			'module.php?mod=tree&amp;mod_action=treeview&amp;rootid=' . $individual->getXref() . '&amp;ged=' . $individual->getTree()->getNameUrl(),
84			'menu-chart-tree',
85			['rel' => 'nofollow']
86		);
87	}
88
89	/**
90	 * Return a menu item for this chart - for use in individual boxes.
91	 *
92	 * @param Individual $individual
93	 *
94	 * @return Menu|null
95	 */
96	public function getBoxChartMenu(Individual $individual) {
97		return $this->getChartMenu($individual);
98	}
99
100	/** {@inheritdoc} */
101	public function getPreLoadContent() {
102		// We cannot use $("head").append(<link rel="stylesheet" ...as jQuery is not loaded at this time
103		return
104			'<script>
105			if (document.createStyleSheet) {
106				document.createStyleSheet("' . $this->css() . '"); // For Internet Explorer
107			} else {
108				var newSheet=document.createElement("link");
109				newSheet.setAttribute("rel","stylesheet");
110				newSheet.setAttribute("type","text/css");
111				newSheet.setAttribute("href","' . $this->css() . '");
112				document.getElementsByTagName("head")[0].appendChild(newSheet);
113			}
114			</script>';
115	}
116
117	/**
118	 * This is a general purpose hook, allowing modules to respond to routes
119	 * of the form module.php?mod=FOO&mod_action=BAR
120	 *
121	 * @param string $mod_action
122	 */
123	public function modAction($mod_action) {
124		global $controller, $WT_TREE;
125
126		switch ($mod_action) {
127		case 'treeview':
128			$controller = new ChartController;
129			$tv         = new TreeView('tv');
130			ob_start();
131
132			$person = $controller->getSignificantIndividual();
133
134			list($html, $js) = $tv->drawViewport($person, 4);
135
136			$controller
137				->setPageTitle(I18N::translate('Interactive tree of %s', $person->getFullName()))
138				->pageHeader()
139				->addExternalJavascript($this->js())
140				->addInlineJavascript($js)
141				->addInlineJavascript('
142					if (document.createStyleSheet) {
143						document.createStyleSheet("' . $this->css() . '"); // For Internet Explorer
144					} else {
145						$("head").append(\'<link rel="stylesheet" type="text/css" href="' . $this->css() . '">\');
146					}
147				');
148			echo $html;
149			break;
150
151		case 'getDetails':
152			header('Content-Type: text/html; charset=UTF-8');
153			$pid        = Filter::get('pid', WT_REGEX_XREF);
154			$i          = Filter::get('instance');
155			$tv         = new TreeView($i);
156			$individual = Individual::getInstance($pid, $WT_TREE);
157			if ($individual) {
158				echo $tv->getDetails($individual);
159			}
160			break;
161
162		case 'getPersons':
163			header('Content-Type: text/html; charset=UTF-8');
164			$q  = Filter::get('q');
165			$i  = Filter::get('instance');
166			$tv = new TreeView($i);
167			echo $tv->getPersons($q);
168			break;
169
170		default:
171			http_response_code(404);
172			break;
173		}
174	}
175
176	/**
177	 * URL for our style sheet.
178	 *
179	 * @return string
180	 */
181	public function css() {
182		return WT_MODULES_DIR . $this->getName() . '/css/treeview.css';
183	}
184
185	/**
186	 * URL for our JavaScript.
187	 *
188	 * @return string
189	 */
190	public function js() {
191		return WT_MODULES_DIR . $this->getName() . '/js/treeview.js';
192	}
193}
194