1<?php 2/** 3 * webtrees: online genealogy 4 * Copyright (C) 2019 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 */ 16declare(strict_types=1); 17 18namespace Fisharebest\Webtrees\Module; 19 20use Fisharebest\Webtrees\Auth; 21use Fisharebest\Webtrees\FlashMessages; 22use Fisharebest\Webtrees\I18N; 23use Fisharebest\Webtrees\Individual; 24use Fisharebest\Webtrees\Menu; 25use Fisharebest\Webtrees\Tree; 26use Symfony\Component\HttpFoundation\RedirectResponse; 27use Symfony\Component\HttpFoundation\Request; 28use Symfony\Component\HttpFoundation\Response; 29 30/** 31 * Class RelationshipsChartModule 32 */ 33class RelationshipsChartModule extends AbstractModule implements ModuleInterface, ModuleChartInterface, ModuleConfigInterface 34{ 35 use ModuleChartTrait; 36 use ModuleConfigTrait; 37 38 /** It would be more correct to use PHP_INT_MAX, but this isn't friendly in URLs */ 39 public const UNLIMITED_RECURSION = 99; 40 41 /** By default new trees allow unlimited recursion */ 42 public const DEFAULT_RECURSION = '99'; 43 44 /** By default new trees search for all relationships (not via ancestors) */ 45 public const DEFAULT_ANCESTORS = '0'; 46 47 /** 48 * How should this module be labelled on tabs, menus, etc.? 49 * 50 * @return string 51 */ 52 public function title(): string 53 { 54 /* I18N: Name of a module/chart */ 55 return I18N::translate('Relationships'); 56 } 57 58 /** 59 * A sentence describing what this module does. 60 * 61 * @return string 62 */ 63 public function description(): string 64 { 65 /* I18N: Description of the “RelationshipsChart” module */ 66 return I18N::translate('A chart displaying relationships between two individuals.'); 67 } 68 69 /** 70 * A main menu item for this chart. 71 * 72 * @param Individual $individual 73 * 74 * @return Menu 75 */ 76 public function chartMenu(Individual $individual): Menu 77 { 78 $gedcomid = $individual->tree()->getUserPreference(Auth::user(), 'gedcomid'); 79 80 if ($gedcomid !== '') { 81 return new Menu( 82 I18N::translate('Relationship to me'), 83 $this->chartUrl($individual, ['xref2' => $gedcomid]), 84 $this->chartMenuClass(), 85 $this->chartUrlAttributes() 86 ); 87 } 88 89 return new Menu( 90 $this->title(), 91 $this->chartUrl($individual), 92 $this->chartMenuClass(), 93 $this->chartUrlAttributes() 94 ); 95 } 96 97 /** 98 * CSS class for the URL. 99 * 100 * @return string 101 */ 102 public function chartMenuClass(): string 103 { 104 return 'menu-chart-relationship'; 105 } 106 107 /** 108 * Return a menu item for this chart - for use in individual boxes. 109 * 110 * @param Individual $individual 111 * 112 * @return Menu|null 113 */ 114 public function chartBoxMenu(Individual $individual): ?Menu 115 { 116 return $this->chartMenu($individual); 117 } 118 119 /** 120 * The URL for this chart. 121 * 122 * @param Individual $individual 123 * @param string[] $parameters 124 * 125 * @return string 126 */ 127 public function chartUrl(Individual $individual, array $parameters = []): string 128 { 129 return route('relationships', [ 130 'xref1' => $individual->xref(), 131 'ged' => $individual->tree()->name(), 132 ] + $parameters); 133 } 134 135 /** 136 * @return Response 137 */ 138 public function getAdminAction(): Response 139 { 140 $this->layout = 'layouts/administration'; 141 142 return $this->viewResponse('modules/relationships_chart/config', [ 143 'all_trees' => Tree::getAll(), 144 'ancestors_options' => $this->ancestorsOptions(), 145 'default_ancestors' => self::DEFAULT_ANCESTORS, 146 'default_recursion' => self::DEFAULT_RECURSION, 147 'recursion_options' => $this->recursionOptions(), 148 'title' => I18N::translate('Chart preferences') . ' — ' . $this->title(), 149 ]); 150 } 151 152 /** 153 * @param Request $request 154 * 155 * @return RedirectResponse 156 */ 157 public function postAdminAction(Request $request): RedirectResponse 158 { 159 foreach (Tree::getAll() as $tree) { 160 $recursion = $request->get('relationship-recursion-' . $tree->id(), ''); 161 $ancestors = $request->get('relationship-ancestors-' . $tree->id(), ''); 162 163 $tree->setPreference('RELATIONSHIP_RECURSION', $recursion); 164 $tree->setPreference('RELATIONSHIP_ANCESTORS', $ancestors); 165 } 166 167 FlashMessages::addMessage(I18N::translate('The preferences for the module “%s” have been updated.', $this->title()), 'success'); 168 169 return new RedirectResponse($this->getConfigLink()); 170 } 171 172 /** 173 * Possible options for the ancestors option 174 * 175 * @return string[] 176 */ 177 private function ancestorsOptions(): array 178 { 179 return [ 180 0 => I18N::translate('Find any relationship'), 181 1 => I18N::translate('Find relationships via ancestors'), 182 ]; 183 } 184 185 /** 186 * Possible options for the recursion option 187 * 188 * @return string[] 189 */ 190 private function recursionOptions(): array 191 { 192 return [ 193 0 => I18N::translate('none'), 194 1 => I18N::number(1), 195 2 => I18N::number(2), 196 3 => I18N::number(3), 197 self::UNLIMITED_RECURSION => I18N::translate('unlimited'), 198 ]; 199 } 200} 201