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\I18N; 22use Fisharebest\Webtrees\Individual; 23use Fisharebest\Webtrees\Module; 24use Fisharebest\Webtrees\Module\InteractiveTree\TreeView; 25use Fisharebest\Webtrees\Tree; 26use Symfony\Component\HttpFoundation\Request; 27 28/** 29 * Class ChartsBlockModule 30 */ 31class ChartsBlockModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface 32{ 33 use ModuleBlockTrait; 34 35 /** 36 * How should this module be labelled on tabs, menus, etc.? 37 * 38 * @return string 39 */ 40 public function title(): string 41 { 42 /* I18N: Name of a module/block */ 43 return I18N::translate('Charts'); 44 } 45 46 /** 47 * A sentence describing what this module does. 48 * 49 * @return string 50 */ 51 public function description(): string 52 { 53 /* I18N: Description of the “Charts” module */ 54 return I18N::translate('An alternative way to display charts.'); 55 } 56 57 /** 58 * Generate the HTML content of this block. 59 * 60 * @param Tree $tree 61 * @param int $block_id 62 * @param string $ctype 63 * @param string[] $cfg 64 * 65 * @return string 66 */ 67 public function getBlock(Tree $tree, int $block_id, string $ctype = '', array $cfg = []): string 68 { 69 $PEDIGREE_ROOT_ID = $tree->getPreference('PEDIGREE_ROOT_ID'); 70 $gedcomid = $tree->getUserPreference(Auth::user(), 'gedcomid'); 71 72 $type = $this->getBlockSetting($block_id, 'type', 'pedigree'); 73 $pid = $this->getBlockSetting($block_id, 'pid', Auth::check() ? ($gedcomid ?: $PEDIGREE_ROOT_ID) : $PEDIGREE_ROOT_ID); 74 75 extract($cfg, EXTR_OVERWRITE); 76 77 $person = Individual::getInstance($pid, $tree); 78 if (!$person) { 79 $pid = $PEDIGREE_ROOT_ID; 80 $this->setBlockSetting($block_id, 'pid', $pid); 81 $person = Individual::getInstance($pid, $tree); 82 } 83 84 $title = $this->title(); 85 86 if ($person) { 87 switch ($type) { 88 default: 89 case 'pedigree': 90 /** @var PedigreeChartModule $module */ 91 $module = Module::getModuleByClassName(PedigreeChartModule::class); 92 $title = $module->chartTitle($person); 93 $chart_url = $module->chartUrl($person, [ 94 'ajax' => true, 95 'generations' => 3, 96 'layout' => PedigreeChartModule::PORTRAIT, 97 ]); 98 $content = view('modules/charts/chart', [ 99 'block_id' => $block_id, 100 'chart_url' => $chart_url, 101 ]); 102 break; 103 104 case 'descendants': 105 /** @var DescendancyChartModule $module */ 106 $module = Module::getModuleByClassName(DescendancyChartModule::class); 107 $title = $module->chartTitle($person); 108 $chart_url = $module->chartUrl($person, [ 109 'ajax' => true, 110 'generations' => 2, 111 'chart_style' => DescendancyChartModule::CHART_STYLE_LIST, 112 ]); 113 $content = view('modules/charts/chart', [ 114 'block_id' => $block_id, 115 'chart_url' => $chart_url, 116 ]); 117 break; 118 119 case 'hourglass': 120 /** @var HourglassChartModule $module */ 121 $module = Module::getModuleByClassName(HourglassChartModule::class); 122 $title = $module->chartTitle($person); 123 $chart_url = $module->chartUrl($person, [ 124 'ajax' => true, 125 'generations' => 2, 126 ]); 127 $content = view('modules/charts/chart', [ 128 'block_id' => $block_id, 129 'chart_url' => $chart_url, 130 ]); 131 break; 132 133 case 'treenav': 134 /** @var InteractiveTreeModule $module */ 135 $module = Module::getModuleByClassName(InteractiveTreeModule::class); 136 $title = I18N::translate('Interactive tree of %s', $person->getFullName()); 137 $tv = new TreeView(); 138 $content = '<script>$("head").append(\'<link rel="stylesheet" href="' . $module->css() . '" type="text/css" />\');</script>'; 139 $content .= '<script src="' . $module->js() . '"></script>'; 140 [$html, $js] = $tv->drawViewport($person, 2); 141 $content .= $html . '<script>' . $js . '</script>'; 142 break; 143 } 144 } else { 145 $content = I18N::translate('You must select an individual and a chart type in the block preferences'); 146 } 147 148 if ($ctype !== '') { 149 if ($ctype === 'gedcom' && Auth::isManager($tree)) { 150 $config_url = route('tree-page-block-edit', [ 151 'block_id' => $block_id, 152 'ged' => $tree->name(), 153 ]); 154 } elseif ($ctype === 'user' && Auth::check()) { 155 $config_url = route('user-page-block-edit', [ 156 'block_id' => $block_id, 157 'ged' => $tree->name(), 158 ]); 159 } else { 160 $config_url = ''; 161 } 162 163 return view('modules/block-template', [ 164 'block' => str_replace('_', '-', $this->name()), 165 'id' => $block_id, 166 'config_url' => $config_url, 167 'title' => strip_tags($title), 168 'content' => $content, 169 ]); 170 } 171 172 return $content; 173 } 174 175 /** {@inheritdoc} */ 176 public function loadAjax(): bool 177 { 178 return true; 179 } 180 181 /** {@inheritdoc} */ 182 public function isUserBlock(): bool 183 { 184 return true; 185 } 186 187 /** {@inheritdoc} */ 188 public function isGedcomBlock(): bool 189 { 190 return true; 191 } 192 193 /** 194 * Update the configuration for a block. 195 * 196 * @param Request $request 197 * @param int $block_id 198 * 199 * @return void 200 */ 201 public function saveBlockConfiguration(Request $request, int $block_id) 202 { 203 $this->setBlockSetting($block_id, 'type', $request->get('type', 'pedigree')); 204 $this->setBlockSetting($block_id, 'pid', $request->get('pid', '')); 205 } 206 207 /** 208 * An HTML form to edit block settings 209 * 210 * @param Tree $tree 211 * @param int $block_id 212 * 213 * @return void 214 */ 215 public function editBlockConfiguration(Tree $tree, int $block_id) 216 { 217 $PEDIGREE_ROOT_ID = $tree->getPreference('PEDIGREE_ROOT_ID'); 218 $gedcomid = $tree->getUserPreference(Auth::user(), 'gedcomid'); 219 220 $type = $this->getBlockSetting($block_id, 'type', 'pedigree'); 221 $pid = $this->getBlockSetting($block_id, 'pid', Auth::check() ? ($gedcomid ?: $PEDIGREE_ROOT_ID) : $PEDIGREE_ROOT_ID); 222 223 $charts = [ 224 'pedigree' => I18N::translate('Pedigree'), 225 'descendants' => I18N::translate('Descendants'), 226 'hourglass' => I18N::translate('Hourglass chart'), 227 'treenav' => I18N::translate('Interactive tree'), 228 ]; 229 uasort($charts, 'Fisharebest\Webtrees\I18N::strcasecmp'); 230 231 $individual = Individual::getInstance($pid, $tree); 232 233 echo view('modules/charts/config', [ 234 'charts' => $charts, 235 'individual' => $individual, 236 'tree' => $tree, 237 'type' => $type, 238 ]); 239 } 240} 241