xref: /webtrees/app/Module/InteractiveTreeModule.php (revision 13abd6f3a37322f885d85df150e105d27ad81f8d)
1<?php
2/**
3 * webtrees: online genealogy
4 * Copyright (C) 2016 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\Auth;
19use Fisharebest\Webtrees\Controller\ChartController;
20use Fisharebest\Webtrees\Filter;
21use Fisharebest\Webtrees\I18N;
22use Fisharebest\Webtrees\Individual;
23use Fisharebest\Webtrees\Menu;
24use Fisharebest\Webtrees\Module\InteractiveTree\TreeView;
25
26/**
27 * Class InteractiveTreeModule
28 * 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
29 */
30class InteractiveTreeModule extends AbstractModule implements ModuleTabInterface, ModuleChartInterface {
31	/** {@inheritdoc} */
32	public function getTitle() {
33		return /* I18N: Name of a module */ I18N::translate('Interactive tree');
34	}
35
36	/** {@inheritdoc} */
37	public function getDescription() {
38		return /* I18N: Description of the “Interactive tree” module */ I18N::translate('An interactive tree, showing all the ancestors and descendants of an individual.');
39	}
40
41	/** {@inheritdoc} */
42	public function defaultTabOrder() {
43		return 68;
44	}
45
46	/** {@inheritdoc} */
47	public function getTabContent() {
48		global $controller;
49
50		$tv              = new TreeView('tvTab');
51		list($html, $js) = $tv->drawViewport($controller->record, 3);
52
53		return
54			'<script src="' . $this->js() . '"></script>' .
55			'<script src="' . WT_JQUERYUI_TOUCH_PUNCH_URL . '"></script>' .
56			'<script>' . $js . '</script>' .
57			$html;
58	}
59
60	/** {@inheritdoc} */
61	public function hasTabContent() {
62		return !Auth::isSearchEngine();
63	}
64
65	/** {@inheritdoc} */
66	public function isGrayedOut() {
67		return false;
68	}
69
70	/** {@inheritdoc} */
71	public function canLoadAjax() {
72		return true;
73	}
74
75	/**
76	 * Return a menu item for this chart.
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	 * @return Menu|null
93	 */
94	public function getBoxChartMenu(Individual $individual) {
95		return $this->getChartMenu($individual);
96	}
97
98	/** {@inheritdoc} */
99	public function getPreLoadContent() {
100		// We cannot use jQuery("head").append(<link rel="stylesheet" ...as jQuery is not loaded at this time
101		return
102			'<script>
103			if (document.createStyleSheet) {
104				document.createStyleSheet("' . $this->css() . '"); // For Internet Explorer
105			} else {
106				var newSheet=document.createElement("link");
107				newSheet.setAttribute("rel","stylesheet");
108				newSheet.setAttribute("type","text/css");
109				newSheet.setAttribute("href","' . $this->css() . '");
110				document.getElementsByTagName("head")[0].appendChild(newSheet);
111			}
112			</script>';
113	}
114
115	/**
116	 * This is a general purpose hook, allowing modules to respond to routes
117	 * of the form module.php?mod=FOO&mod_action=BAR
118	 *
119	 * @param string $mod_action
120	 */
121	public function modAction($mod_action) {
122		global $controller, $WT_TREE;
123
124		switch ($mod_action) {
125		case 'treeview':
126			$controller = new ChartController;
127			$tv         = new TreeView('tv');
128			ob_start();
129
130			$person = $controller->getSignificantIndividual();
131
132			list($html, $js) = $tv->drawViewport($person, 4);
133
134			$controller
135				->setPageTitle(I18N::translate('Interactive tree of %s', $person->getFullName()))
136				->pageHeader()
137				->addExternalJavascript($this->js())
138				->addExternalJavascript(WT_JQUERYUI_TOUCH_PUNCH_URL)
139				->addInlineJavascript($js)
140				->addInlineJavascript('
141					if (document.createStyleSheet) {
142						document.createStyleSheet("' . $this->css() . '"); // For Internet Explorer
143					} else {
144						jQuery("head").append(\'<link rel="stylesheet" type="text/css" href="' . $this->css() . '">\');
145					}
146				');
147			echo $html;
148			break;
149
150		case 'getDetails':
151			header('Content-Type: text/html; charset=UTF-8');
152			$pid        = Filter::get('pid', WT_REGEX_XREF);
153			$i          = Filter::get('instance');
154			$tv         = new TreeView($i);
155			$individual = Individual::getInstance($pid, $WT_TREE);
156			if ($individual) {
157				echo $tv->getDetails($individual);
158			}
159			break;
160
161		case 'getPersons':
162			header('Content-Type: text/html; charset=UTF-8');
163			$q  = Filter::get('q');
164			$i  = Filter::get('instance');
165			$tv = new TreeView($i);
166			echo $tv->getPersons($q);
167			break;
168
169		default:
170			http_response_code(404);
171			break;
172		}
173	}
174
175	/**
176	 * URL for our style sheet.
177	 *
178	 * @return string
179	 */
180	public function css() {
181		return WT_STATIC_URL . WT_MODULES_DIR . $this->getName() . '/css/treeview.css';
182	}
183
184	/**
185	 * URL for our JavaScript.
186	 *
187	 * @return string
188	 */
189	public function js() {
190		return WT_STATIC_URL . WT_MODULES_DIR . $this->getName() . '/js/treeview.js';
191	}
192}
193