xref: /webtrees/app/Module/InteractiveTreeModule.php (revision 15d603e7c7c15d20f055d3d9c38d6b133453c5be)
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	 * @return Menu|null
77	 */
78	public function getChartMenu(Individual $individual) {
79		return new Menu(
80			$this->getTitle(),
81			'module.php?mod=tree&amp;mod_action=treeview&amp;rootid=' . $individual->getXref() . '&amp;ged=' . $individual->getTree()->getNameUrl(),
82			'menu-chart-tree',
83			['rel' => 'nofollow']
84		);
85	}
86
87	/**
88	 * Return a menu item for this chart - for use in individual boxes.
89	 *
90	 * @return Menu|null
91	 */
92	public function getBoxChartMenu(Individual $individual) {
93		return $this->getChartMenu($individual);
94	}
95
96	/** {@inheritdoc} */
97	public function getPreLoadContent() {
98		// We cannot use $("head").append(<link rel="stylesheet" ...as jQuery is not loaded at this time
99		return
100			'<script>
101			if (document.createStyleSheet) {
102				document.createStyleSheet("' . $this->css() . '"); // For Internet Explorer
103			} else {
104				var newSheet=document.createElement("link");
105				newSheet.setAttribute("rel","stylesheet");
106				newSheet.setAttribute("type","text/css");
107				newSheet.setAttribute("href","' . $this->css() . '");
108				document.getElementsByTagName("head")[0].appendChild(newSheet);
109			}
110			</script>';
111	}
112
113	/**
114	 * This is a general purpose hook, allowing modules to respond to routes
115	 * of the form module.php?mod=FOO&mod_action=BAR
116	 *
117	 * @param string $mod_action
118	 */
119	public function modAction($mod_action) {
120		global $controller, $WT_TREE;
121
122		switch ($mod_action) {
123		case 'treeview':
124			$controller = new ChartController;
125			$tv         = new TreeView('tv');
126			ob_start();
127
128			$person = $controller->getSignificantIndividual();
129
130			list($html, $js) = $tv->drawViewport($person, 4);
131
132			$controller
133				->setPageTitle(I18N::translate('Interactive tree of %s', $person->getFullName()))
134				->pageHeader()
135				->addExternalJavascript($this->js())
136				->addInlineJavascript($js)
137				->addInlineJavascript('
138					if (document.createStyleSheet) {
139						document.createStyleSheet("' . $this->css() . '"); // For Internet Explorer
140					} else {
141						$("head").append(\'<link rel="stylesheet" type="text/css" href="' . $this->css() . '">\');
142					}
143				');
144			echo $html;
145			break;
146
147		case 'getDetails':
148			header('Content-Type: text/html; charset=UTF-8');
149			$pid        = Filter::get('pid', WT_REGEX_XREF);
150			$i          = Filter::get('instance');
151			$tv         = new TreeView($i);
152			$individual = Individual::getInstance($pid, $WT_TREE);
153			if ($individual) {
154				echo $tv->getDetails($individual);
155			}
156			break;
157
158		case 'getPersons':
159			header('Content-Type: text/html; charset=UTF-8');
160			$q  = Filter::get('q');
161			$i  = Filter::get('instance');
162			$tv = new TreeView($i);
163			echo $tv->getPersons($q);
164			break;
165
166		default:
167			http_response_code(404);
168			break;
169		}
170	}
171
172	/**
173	 * URL for our style sheet.
174	 *
175	 * @return string
176	 */
177	public function css() {
178		return WT_STATIC_URL . WT_MODULES_DIR . $this->getName() . '/css/treeview.css';
179	}
180
181	/**
182	 * URL for our JavaScript.
183	 *
184	 * @return string
185	 */
186	public function js() {
187		return WT_STATIC_URL . WT_MODULES_DIR . $this->getName() . '/js/treeview.js';
188	}
189}
190