xref: /webtrees/app/Module/RelationshipsChartModule.php (revision 2c689cc89a5a7ad832f2f1ac50a2e8cc7e9814fd)
1168ff6f3Sric2016<?php
2168ff6f3Sric2016/**
3168ff6f3Sric2016 * webtrees: online genealogy
41062a142SGreg Roach * Copyright (C) 2018 webtrees development team
5168ff6f3Sric2016 * This program is free software: you can redistribute it and/or modify
6168ff6f3Sric2016 * it under the terms of the GNU General Public License as published by
7168ff6f3Sric2016 * the Free Software Foundation, either version 3 of the License, or
8168ff6f3Sric2016 * (at your option) any later version.
9168ff6f3Sric2016 * This program is distributed in the hope that it will be useful,
10168ff6f3Sric2016 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11168ff6f3Sric2016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12168ff6f3Sric2016 * GNU General Public License for more details.
13168ff6f3Sric2016 * You should have received a copy of the GNU General Public License
14168ff6f3Sric2016 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15168ff6f3Sric2016 */
16168ff6f3Sric2016namespace Fisharebest\Webtrees\Module;
17168ff6f3Sric2016
18168ff6f3Sric2016use Fisharebest\Webtrees\Auth;
1915d603e7SGreg Roachuse Fisharebest\Webtrees\Bootstrap4;
2045ac604bSGreg Roachuse Fisharebest\Webtrees\Controller\PageController;
2145ac604bSGreg Roachuse Fisharebest\Webtrees\Filter;
2245ac604bSGreg Roachuse Fisharebest\Webtrees\FlashMessages;
23b1b85189SGreg Roachuse Fisharebest\Webtrees\Html;
24168ff6f3Sric2016use Fisharebest\Webtrees\I18N;
25168ff6f3Sric2016use Fisharebest\Webtrees\Individual;
261e3273c9SGreg Roachuse Fisharebest\Webtrees\Menu;
2745ac604bSGreg Roachuse Fisharebest\Webtrees\Tree;
28168ff6f3Sric2016
29168ff6f3Sric2016/**
30168ff6f3Sric2016 * Class RelationshipsChartModule
31168ff6f3Sric2016 */
3245ac604bSGreg Roachclass RelationshipsChartModule extends AbstractModule implements ModuleConfigInterface, ModuleChartInterface {
331e3273c9SGreg Roach	/** It would be more correct to use PHP_INT_MAX, but this isn't friendly in URLs */
341e3273c9SGreg Roach	const UNLIMITED_RECURSION = 99;
351e3273c9SGreg Roach
361e3273c9SGreg Roach	/** By default new trees allow unlimited recursion */
371e3273c9SGreg Roach	const DEFAULT_RECURSION = self::UNLIMITED_RECURSION;
3845ac604bSGreg Roach
39e0bd7dc9SGreg Roach	/** By default new trees search for all relationships (not via ancestors) */
40e0bd7dc9SGreg Roach	const DEFAULT_ANCESTORS = 0;
41e0bd7dc9SGreg Roach
42168ff6f3Sric2016	/**
43168ff6f3Sric2016	 * How should this module be labelled on tabs, menus, etc.?
44168ff6f3Sric2016	 *
45168ff6f3Sric2016	 * @return string
46168ff6f3Sric2016	 */
47168ff6f3Sric2016	public function getTitle() {
48168ff6f3Sric2016		return /* I18N: Name of a module/chart */ I18N::translate('Relationships');
49168ff6f3Sric2016	}
50168ff6f3Sric2016
51168ff6f3Sric2016	/**
52168ff6f3Sric2016	 * A sentence describing what this module does.
53168ff6f3Sric2016	 *
54168ff6f3Sric2016	 * @return string
55168ff6f3Sric2016	 */
56168ff6f3Sric2016	public function getDescription() {
57168ff6f3Sric2016		return /* I18N: Description of the “RelationshipsChart” module */ I18N::translate('A chart displaying relationships between two individuals.');
58168ff6f3Sric2016	}
59168ff6f3Sric2016
60168ff6f3Sric2016	/**
61168ff6f3Sric2016	 * What is the default access level for this module?
62168ff6f3Sric2016	 *
63168ff6f3Sric2016	 * Some modules are aimed at admins or managers, and are not generally shown to users.
64168ff6f3Sric2016	 *
65168ff6f3Sric2016	 * @return int
66168ff6f3Sric2016	 */
67168ff6f3Sric2016	public function defaultAccessLevel() {
68168ff6f3Sric2016		return Auth::PRIV_PRIVATE;
69168ff6f3Sric2016	}
70168ff6f3Sric2016
71168ff6f3Sric2016	/**
72168ff6f3Sric2016	 * Return a menu item for this chart.
73168ff6f3Sric2016	 *
748e69695bSGreg Roach	 * @param Individual $individual
758e69695bSGreg Roach	 *
764eb71cfaSGreg Roach	 * @return Menu|null
77168ff6f3Sric2016	 */
78168ff6f3Sric2016	public function getChartMenu(Individual $individual) {
794eb71cfaSGreg Roach		$tree     = $individual->getTree();
80*2c689cc8SGreg Roach		$gedcomid = $tree->getUserPreference(Auth::user(), 'gedcomid', '');
81168ff6f3Sric2016
82*2c689cc8SGreg Roach		if ($gedcomid !== '') {
83168ff6f3Sric2016			return new Menu(
84168ff6f3Sric2016				I18N::translate('Relationship to me'),
85*2c689cc8SGreg Roach				e(route('relationships', ['xref1' => $gedcomid, 'xref2' => $individual->getXref(), 'ged' => $individual->getTree()->getName()])),
86168ff6f3Sric2016				'menu-chart-relationship',
8713abd6f3SGreg Roach				['rel' => 'nofollow']
88168ff6f3Sric2016			);
89168ff6f3Sric2016		} else {
90168ff6f3Sric2016			return new Menu(
91168ff6f3Sric2016				I18N::translate('Relationships'),
9207895620SGreg Roach				e(route('relationships', ['xref1' => $individual->getXref(), 'ged' => $individual->getTree()->getName()])),
93168ff6f3Sric2016				'menu-chart-relationship',
9413abd6f3SGreg Roach				['rel' => 'nofollow']
95168ff6f3Sric2016			);
96168ff6f3Sric2016		}
97168ff6f3Sric2016	}
98168ff6f3Sric2016
994eb71cfaSGreg Roach	/**
1004eb71cfaSGreg Roach	 * Return a menu item for this chart - for use in individual boxes.
1014eb71cfaSGreg Roach	 *
1028e69695bSGreg Roach	 * @param Individual $individual
1038e69695bSGreg Roach	 *
1044eb71cfaSGreg Roach	 * @return Menu|null
1054eb71cfaSGreg Roach	 */
106168ff6f3Sric2016	public function getBoxChartMenu(Individual $individual) {
107168ff6f3Sric2016		return $this->getChartMenu($individual);
108168ff6f3Sric2016	}
10945ac604bSGreg Roach
11045ac604bSGreg Roach	/**
11145ac604bSGreg Roach	 * This is a general purpose hook, allowing modules to respond to routes
11245ac604bSGreg Roach	 * of the form module.php?mod=FOO&mod_action=BAR
11345ac604bSGreg Roach	 *
11445ac604bSGreg Roach	 * @param string $mod_action
11545ac604bSGreg Roach	 */
11645ac604bSGreg Roach	public function modAction($mod_action) {
11745ac604bSGreg Roach		switch ($mod_action) {
11845ac604bSGreg Roach			case 'admin':
11945ac604bSGreg Roach				if ($_SERVER['REQUEST_METHOD'] === 'POST') {
12045ac604bSGreg Roach					$this->saveConfig();
12145ac604bSGreg Roach				} else {
12245ac604bSGreg Roach					$this->editConfig();
12345ac604bSGreg Roach				}
12445ac604bSGreg Roach				break;
12545ac604bSGreg Roach			default:
12645ac604bSGreg Roach				http_response_code(404);
12745ac604bSGreg Roach		}
12845ac604bSGreg Roach	}
12945ac604bSGreg Roach
13045ac604bSGreg Roach	/**
131e0bd7dc9SGreg Roach	 * Possible options for the ancestors option
132e0bd7dc9SGreg Roach	 */
133e0bd7dc9SGreg Roach	private function ancestorsOptions() {
13413abd6f3SGreg Roach		return [
135e0bd7dc9SGreg Roach			0 => I18N::translate('Find any relationship'),
136e0bd7dc9SGreg Roach			1 => I18N::translate('Find relationships via ancestors'),
13713abd6f3SGreg Roach		];
138e0bd7dc9SGreg Roach	}
139e0bd7dc9SGreg Roach
140e0bd7dc9SGreg Roach	/**
1411e3273c9SGreg Roach	 * Possible options for the recursion option
1421e3273c9SGreg Roach	 */
1431e3273c9SGreg Roach	private function recursionOptions() {
14413abd6f3SGreg Roach		return [
1451e3273c9SGreg Roach			0                         => I18N::translate('none'),
1461e3273c9SGreg Roach			1                         => I18N::number(1),
1471e3273c9SGreg Roach			2                         => I18N::number(2),
1481e3273c9SGreg Roach			3                         => I18N::number(3),
149e0bd7dc9SGreg Roach			self::UNLIMITED_RECURSION => I18N::translate('unlimited'),
15013abd6f3SGreg Roach		];
1511e3273c9SGreg Roach	}
1521e3273c9SGreg Roach
1531e3273c9SGreg Roach	/**
15445ac604bSGreg Roach	 * Display a form to edit configuration settings.
15545ac604bSGreg Roach	 */
15645ac604bSGreg Roach	private function editConfig() {
15745ac604bSGreg Roach		$controller = new PageController;
15845ac604bSGreg Roach		$controller
15945ac604bSGreg Roach			->restrictAccess(Auth::isAdmin())
16045ac604bSGreg Roach			->setPageTitle(I18N::translate('Chart preferences') . ' — ' . $this->getTitle())
16145ac604bSGreg Roach			->pageHeader();
16245ac604bSGreg Roach
16315d603e7SGreg Roach		echo Bootstrap4::breadcrumbs([
1641f3fb95cSGreg Roach			route('admin-control-panel') => I18N::translate('Control panel'),
1651f3fb95cSGreg Roach			route('admin-modules')       => I18N::translate('Module administration'),
16615d603e7SGreg Roach		], $controller->getPageTitle());
16745ac604bSGreg Roach		?>
16815d603e7SGreg Roach
16915d603e7SGreg Roach		<h1><?= $controller->getPageTitle() ?></h1>
17045ac604bSGreg Roach
171e0bd7dc9SGreg Roach		<p>
17215d603e7SGreg Roach			<?= I18N::translate('Searching for all possible relationships can take a lot of time in complex trees.') ?>
173e0bd7dc9SGreg Roach		</p>
174e0bd7dc9SGreg Roach
17545ac604bSGreg Roach		<form method="post">
17645ac604bSGreg Roach			<?php foreach (Tree::getAll() as $tree): ?>
17715d603e7SGreg Roach				<h2><?= $tree->getTitleHtml() ?></h2>
17815d603e7SGreg Roach				<div class="row form-group">
17915d603e7SGreg Roach					<label class="col-sm-3 col-form-label" for="relationship-ancestors-<?= $tree->getTreeId() ?>">
18015d603e7SGreg Roach						<?= /* I18N: Configuration option */I18N::translate('Relationships') ?>
181e0bd7dc9SGreg Roach					</label>
182e0bd7dc9SGreg Roach					<div class="col-sm-9">
18315d603e7SGreg Roach						<?= Bootstrap4::select($this->ancestorsOptions(), $tree->getPreference('RELATIONSHIP_ANCESTORS', self::DEFAULT_ANCESTORS), ['id' => 'relationship-ancestors-' . $tree->getTreeId(), 'name' => 'relationship-ancestors-' . $tree->getTreeId()]) ?>
184e0bd7dc9SGreg Roach					</div>
185e0bd7dc9SGreg Roach				</div>
186e0bd7dc9SGreg Roach
18745ac604bSGreg Roach				<fieldset class="form-group">
18815d603e7SGreg Roach					<div class="row">
189fff20713SGreg Roach						<legend class="col-form-label col-sm-3">
19015d603e7SGreg Roach							<?= /* I18N: Configuration option */I18N::translate('How much recursion to use when searching for relationships') ?>
19145ac604bSGreg Roach						</legend>
19245ac604bSGreg Roach						<div class="col-sm-9">
19315d603e7SGreg Roach							<?= Bootstrap4::radioButtons('relationship-recursion-' . $tree->getTreeId(), $this->recursionOptions(), $tree->getPreference('RELATIONSHIP_RECURSION', self::DEFAULT_RECURSION), true) ?>
19415d603e7SGreg Roach						</div>
19545ac604bSGreg Roach					</div>
19645ac604bSGreg Roach				</fieldset>
19715d603e7SGreg Roach			<?php endforeach ?>
19845ac604bSGreg Roach
19915d603e7SGreg Roach			<div class="row form-group">
20015d603e7SGreg Roach				<div class="offset-sm-3 col-sm-9">
20145ac604bSGreg Roach					<button type="submit" class="btn btn-primary">
2028108dc50SGreg Roach						<i class="fas fa-check"></i>
20315d603e7SGreg Roach						<?= I18N::translate('save') ?>
20445ac604bSGreg Roach					</button>
20545ac604bSGreg Roach				</div>
20645ac604bSGreg Roach			</div>
20745ac604bSGreg Roach		</form>
20845ac604bSGreg Roach		<?php
20945ac604bSGreg Roach	}
21045ac604bSGreg Roach
21145ac604bSGreg Roach	/**
21245ac604bSGreg Roach	 * Save updated configuration settings.
21345ac604bSGreg Roach	 */
21445ac604bSGreg Roach	private function saveConfig() {
21545ac604bSGreg Roach		if (Auth::isAdmin()) {
21645ac604bSGreg Roach			foreach (Tree::getAll() as $tree) {
2171e3273c9SGreg Roach				$tree->setPreference('RELATIONSHIP_RECURSION', Filter::post('relationship-recursion-' . $tree->getTreeId()));
218e0bd7dc9SGreg Roach				$tree->setPreference('RELATIONSHIP_ANCESTORS', Filter::post('relationship-ancestors-' . $tree->getTreeId()));
21945ac604bSGreg Roach			}
22045ac604bSGreg Roach
22145ac604bSGreg Roach			FlashMessages::addMessage(I18N::translate('The preferences for the chart “%s” have been updated.', $this->getTitle()), 'success');
22245ac604bSGreg Roach		}
22345ac604bSGreg Roach
224bff8dc60SGreg Roach		header('Location: module.php?mod=' . $this->getName() . '&mod_action=admin');
22545ac604bSGreg Roach	}
22645ac604bSGreg Roach
22745ac604bSGreg Roach	/**
22845ac604bSGreg Roach	 * The URL to a page where the user can modify the configuration of this module.
22945ac604bSGreg Roach	 *
23045ac604bSGreg Roach	 * @return string
23145ac604bSGreg Roach	 */
23245ac604bSGreg Roach	public function getConfigLink() {
233b1b85189SGreg Roach		return Html::url('module.php', [
234b1b85189SGreg Roach			'mod'        => $this->getName(),
235b1b85189SGreg Roach			'mod_action' => 'admin',
236b1b85189SGreg Roach		]);
23745ac604bSGreg Roach	}
238168ff6f3Sric2016}
239