18c2e8227SGreg Roach<?php 23976b470SGreg Roach 38c2e8227SGreg Roach/** 48c2e8227SGreg Roach * webtrees: online genealogy 51fe542e9SGreg Roach * Copyright (C) 2021 webtrees development team 68c2e8227SGreg Roach * This program is free software: you can redistribute it and/or modify 78c2e8227SGreg Roach * it under the terms of the GNU General Public License as published by 88c2e8227SGreg Roach * the Free Software Foundation, either version 3 of the License, or 98c2e8227SGreg Roach * (at your option) any later version. 108c2e8227SGreg Roach * This program is distributed in the hope that it will be useful, 118c2e8227SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 128c2e8227SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 138c2e8227SGreg Roach * GNU General Public License for more details. 148c2e8227SGreg Roach * You should have received a copy of the GNU General Public License 1589f7189bSGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>. 168c2e8227SGreg Roach */ 17fcfa147eSGreg Roach 18e7f56f2aSGreg Roachdeclare(strict_types=1); 19e7f56f2aSGreg Roach 2076692c8bSGreg Roachnamespace Fisharebest\Webtrees\Module; 2176692c8bSGreg Roach 220e62c4b8SGreg Roachuse Fisharebest\Webtrees\Auth; 231fe542e9SGreg Roachuse Fisharebest\Webtrees\Contracts\UserInterface; 240e62c4b8SGreg Roachuse Fisharebest\Webtrees\I18N; 250e62c4b8SGreg Roachuse Fisharebest\Webtrees\Individual; 260e62c4b8SGreg Roachuse Fisharebest\Webtrees\Module\InteractiveTree\TreeView; 27406008aaSGreg Roachuse Fisharebest\Webtrees\Registry; 284ca7e03cSGreg Roachuse Fisharebest\Webtrees\Services\ModuleService; 29e490cd80SGreg Roachuse Fisharebest\Webtrees\Tree; 301e7a7a28SGreg Roachuse Illuminate\Support\Str; 316ccdf4f0SGreg Roachuse Psr\Http\Message\ServerRequestInterface; 328c2e8227SGreg Roach 33406008aaSGreg Roachuse function extract; 34406008aaSGreg Roachuse function uasort; 35406008aaSGreg Roachuse function view; 36406008aaSGreg Roach 37406008aaSGreg Roachuse const EXTR_OVERWRITE; 38406008aaSGreg Roach 398c2e8227SGreg Roach/** 408c2e8227SGreg Roach * Class ChartsBlockModule 418c2e8227SGreg Roach */ 4237eb8894SGreg Roachclass ChartsBlockModule extends AbstractModule implements ModuleBlockInterface 43c1010edaSGreg Roach{ 4449a243cbSGreg Roach use ModuleBlockTrait; 4549a243cbSGreg Roach 4643f2f523SGreg Roach private ModuleService $module_service; 474ca7e03cSGreg Roach 484ca7e03cSGreg Roach /** 494ca7e03cSGreg Roach * ChartsBlockModule constructor. 504ca7e03cSGreg Roach * 514ca7e03cSGreg Roach * @param ModuleService $module_service 524ca7e03cSGreg Roach */ 535bdbe281SGreg Roach public function __construct(ModuleService $module_service) 545bdbe281SGreg Roach { 554ca7e03cSGreg Roach $this->module_service = $module_service; 564ca7e03cSGreg Roach } 574ca7e03cSGreg Roach 584ca7e03cSGreg Roach /** 590cfd6963SGreg Roach * How should this module be identified in the control panel, etc.? 60961ec755SGreg Roach * 61961ec755SGreg Roach * @return string 62961ec755SGreg Roach */ 6349a243cbSGreg Roach public function title(): string 64c1010edaSGreg Roach { 65bbb76c12SGreg Roach /* I18N: Name of a module/block */ 66bbb76c12SGreg Roach return I18N::translate('Charts'); 678c2e8227SGreg Roach } 688c2e8227SGreg Roach 69961ec755SGreg Roach /** 70961ec755SGreg Roach * A sentence describing what this module does. 71961ec755SGreg Roach * 72961ec755SGreg Roach * @return string 73961ec755SGreg Roach */ 7449a243cbSGreg Roach public function description(): string 75c1010edaSGreg Roach { 76bbb76c12SGreg Roach /* I18N: Description of the “Charts” module */ 77bbb76c12SGreg Roach return I18N::translate('An alternative way to display charts.'); 788c2e8227SGreg Roach } 798c2e8227SGreg Roach 8076692c8bSGreg Roach /** 8176692c8bSGreg Roach * Generate the HTML content of this block. 8276692c8bSGreg Roach * 83e490cd80SGreg Roach * @param Tree $tree 8476692c8bSGreg Roach * @param int $block_id 853caaa4d2SGreg Roach * @param string $context 86*76d39c55SGreg Roach * @param array<string,string> $config 8776692c8bSGreg Roach * 8876692c8bSGreg Roach * @return string 8976692c8bSGreg Roach */ 903caaa4d2SGreg Roach public function getBlock(Tree $tree, int $block_id, string $context, array $config = []): string 91c1010edaSGreg Roach { 92e490cd80SGreg Roach $PEDIGREE_ROOT_ID = $tree->getPreference('PEDIGREE_ROOT_ID'); 931fe542e9SGreg Roach $gedcomid = $tree->getUserPreference(Auth::user(), UserInterface::PREF_TREE_ACCOUNT_XREF); 94575707d1SGreg Roach $default_xref = $gedcomid ?: $PEDIGREE_ROOT_ID; 958c2e8227SGreg Roach 96e2a378d3SGreg Roach $type = $this->getBlockSetting($block_id, 'type', 'pedigree'); 97575707d1SGreg Roach $xref = $this->getBlockSetting($block_id, 'pid', $default_xref); 988c2e8227SGreg Roach 993caaa4d2SGreg Roach extract($config, EXTR_OVERWRITE); 1008c2e8227SGreg Roach 1016b9cb339SGreg Roach $individual = Registry::individualFactory()->make($xref, $tree); 1028c2e8227SGreg Roach 10349a243cbSGreg Roach $title = $this->title(); 1048c2e8227SGreg Roach 105575707d1SGreg Roach if ($individual instanceof Individual) { 1068c2e8227SGreg Roach switch ($type) { 107677aaceaSGreg Roach default: 1088c2e8227SGreg Roach case 'pedigree': 109ed9ba438SGreg Roach $module = $this->module_service->findByInterface(PedigreeChartModule::class)->first(); 110406008aaSGreg Roach if ($module instanceof PedigreeChartModule) { 111575707d1SGreg Roach $title = $module->chartTitle($individual); 112575707d1SGreg Roach $chart_url = $module->chartUrl($individual, [ 1139b5537c3SGreg Roach 'ajax' => true, 11402fe1c37SGreg Roach 'generations' => 3, 11571378461SGreg Roach 'layout' => PedigreeChartModule::STYLE_RIGHT, 11602fe1c37SGreg Roach ]); 117147e99aaSGreg Roach $content = view('modules/charts/chart', [ 11802fe1c37SGreg Roach 'block_id' => $block_id, 11902fe1c37SGreg Roach 'chart_url' => $chart_url, 12002fe1c37SGreg Roach ]); 121406008aaSGreg Roach } else { 122406008aaSGreg Roach $title = I18N::translate('Pedigree'); 123406008aaSGreg Roach $content = I18N::translate('The module “%s” has been disabled.', $title); 124406008aaSGreg Roach } 1258c2e8227SGreg Roach break; 126677aaceaSGreg Roach 1278c2e8227SGreg Roach case 'descendants': 128ed9ba438SGreg Roach $module = $this->module_service->findByInterface(DescendancyChartModule::class)->first(); 129406008aaSGreg Roach 130406008aaSGreg Roach if ($module instanceof DescendancyChartModule) { 131575707d1SGreg Roach $title = $module->chartTitle($individual); 132575707d1SGreg Roach $chart_url = $module->chartUrl($individual, [ 1339b5537c3SGreg Roach 'ajax' => true, 13402fe1c37SGreg Roach 'generations' => 2, 1350f1e0f10SGreg Roach 'chart_style' => DescendancyChartModule::CHART_STYLE_TREE, 13602fe1c37SGreg Roach ]); 137147e99aaSGreg Roach $content = view('modules/charts/chart', [ 13802fe1c37SGreg Roach 'block_id' => $block_id, 13902fe1c37SGreg Roach 'chart_url' => $chart_url, 14002fe1c37SGreg Roach ]); 141406008aaSGreg Roach } else { 142406008aaSGreg Roach $title = I18N::translate('Descendants'); 143406008aaSGreg Roach $content = I18N::translate('The module “%s” has been disabled.', $title); 144406008aaSGreg Roach } 145406008aaSGreg Roach 1468c2e8227SGreg Roach break; 147677aaceaSGreg Roach 1488c2e8227SGreg Roach case 'hourglass': 149ed9ba438SGreg Roach $module = $this->module_service->findByInterface(HourglassChartModule::class)->first(); 150406008aaSGreg Roach 151406008aaSGreg Roach if ($module instanceof HourglassChartModule) { 152575707d1SGreg Roach $title = $module->chartTitle($individual); 153575707d1SGreg Roach $chart_url = $module->chartUrl($individual, [ 1549b5537c3SGreg Roach 'ajax' => true, 15502fe1c37SGreg Roach 'generations' => 2, 15602fe1c37SGreg Roach ]); 157147e99aaSGreg Roach $content = view('modules/charts/chart', [ 15802fe1c37SGreg Roach 'block_id' => $block_id, 15902fe1c37SGreg Roach 'chart_url' => $chart_url, 16002fe1c37SGreg Roach ]); 161406008aaSGreg Roach } else { 162406008aaSGreg Roach $title = I18N::translate('Hourglass chart'); 163406008aaSGreg Roach $content = I18N::translate('The module “%s” has been disabled.', $title); 164406008aaSGreg Roach } 1658c2e8227SGreg Roach break; 166677aaceaSGreg Roach 1678c2e8227SGreg Roach case 'treenav': 16841f309deSGreg Roach $module = $this->module_service->findByInterface(InteractiveTreeModule::class)->first(); 169406008aaSGreg Roach 170406008aaSGreg Roach if ($module instanceof InteractiveTreeModule) { 171575707d1SGreg Roach $title = I18N::translate('Interactive tree of %s', $individual->fullName()); 17259f2f229SGreg Roach $tv = new TreeView(); 173575707d1SGreg Roach [$html, $js] = $tv->drawViewport($individual, 2); 174575707d1SGreg Roach $content = $html . '<script>' . $js . '</script>'; 175406008aaSGreg Roach } else { 176406008aaSGreg Roach $title = I18N::translate('Interactive tree'); 177406008aaSGreg Roach $content = I18N::translate('The module “%s” has been disabled.', $title); 178406008aaSGreg Roach } 179406008aaSGreg Roach 1808c2e8227SGreg Roach break; 1818c2e8227SGreg Roach } 1828c2e8227SGreg Roach } else { 1836e7bf391SGreg Roach $content = I18N::translate('You must select an individual and a chart type in the block preferences'); 1848c2e8227SGreg Roach } 1858c2e8227SGreg Roach 1863caaa4d2SGreg Roach if ($context !== self::CONTEXT_EMBED) { 187147e99aaSGreg Roach return view('modules/block-template', [ 1881e7a7a28SGreg Roach 'block' => Str::kebab($this->name()), 1899c6524dcSGreg Roach 'id' => $block_id, 1903caaa4d2SGreg Roach 'config_url' => $this->configUrl($tree, $context, $block_id), 1913f385873SGreg Roach 'title' => $title, 1929c6524dcSGreg Roach 'content' => $content, 1939c6524dcSGreg Roach ]); 1948c2e8227SGreg Roach } 195b2ce94c6SRico Sonntag 196b2ce94c6SRico Sonntag return $content; 1978c2e8227SGreg Roach } 1988c2e8227SGreg Roach 1993caaa4d2SGreg Roach /** 2003caaa4d2SGreg Roach * Should this block load asynchronously using AJAX? 2013caaa4d2SGreg Roach * 2023caaa4d2SGreg Roach * Simple blocks are faster in-line, more complex ones can be loaded later. 2033caaa4d2SGreg Roach * 2043caaa4d2SGreg Roach * @return bool 2053caaa4d2SGreg Roach */ 206c1010edaSGreg Roach public function loadAjax(): bool 207c1010edaSGreg Roach { 2088c2e8227SGreg Roach return true; 2098c2e8227SGreg Roach } 2108c2e8227SGreg Roach 2113caaa4d2SGreg Roach /** 2123caaa4d2SGreg Roach * Can this block be shown on the tree’s home page? 2133caaa4d2SGreg Roach * 2143caaa4d2SGreg Roach * @return bool 2153caaa4d2SGreg Roach */ 21663276d8fSGreg Roach public function isTreeBlock(): bool 217c1010edaSGreg Roach { 2188c2e8227SGreg Roach return true; 2198c2e8227SGreg Roach } 2208c2e8227SGreg Roach 22176692c8bSGreg Roach /** 222a45f9889SGreg Roach * Update the configuration for a block. 223a45f9889SGreg Roach * 2246ccdf4f0SGreg Roach * @param ServerRequestInterface $request 225a45f9889SGreg Roach * @param int $block_id 226a45f9889SGreg Roach * 227a45f9889SGreg Roach * @return void 228a45f9889SGreg Roach */ 2296ccdf4f0SGreg Roach public function saveBlockConfiguration(ServerRequestInterface $request, int $block_id): void 230a45f9889SGreg Roach { 231b46c87bdSGreg Roach $params = (array) $request->getParsedBody(); 232b46c87bdSGreg Roach 233b46c87bdSGreg Roach $this->setBlockSetting($block_id, 'type', $params['type'] ?? 'pedigree'); 234b46c87bdSGreg Roach $this->setBlockSetting($block_id, 'pid', $params['xref'] ?? ''); 235a45f9889SGreg Roach } 236a45f9889SGreg Roach 237a45f9889SGreg Roach /** 23876692c8bSGreg Roach * An HTML form to edit block settings 23976692c8bSGreg Roach * 240e490cd80SGreg Roach * @param Tree $tree 24176692c8bSGreg Roach * @param int $block_id 242a9430be8SGreg Roach * 2433caaa4d2SGreg Roach * @return string 24476692c8bSGreg Roach */ 2453caaa4d2SGreg Roach public function editBlockConfiguration(Tree $tree, int $block_id): string 246c1010edaSGreg Roach { 247e490cd80SGreg Roach $PEDIGREE_ROOT_ID = $tree->getPreference('PEDIGREE_ROOT_ID'); 2481fe542e9SGreg Roach $gedcomid = $tree->getUserPreference(Auth::user(), UserInterface::PREF_TREE_ACCOUNT_XREF); 249575707d1SGreg Roach $default_xref = $gedcomid ?: $PEDIGREE_ROOT_ID; 2508c2e8227SGreg Roach 251e2a378d3SGreg Roach $type = $this->getBlockSetting($block_id, 'type', 'pedigree'); 252575707d1SGreg Roach $xref = $this->getBlockSetting($block_id, 'pid', $default_xref); 2538c2e8227SGreg Roach 25413abd6f3SGreg Roach $charts = [ 255fddfbb14SGreg Roach 'pedigree' => I18N::translate('Pedigree'), 256fddfbb14SGreg Roach 'descendants' => I18N::translate('Descendants'), 257fddfbb14SGreg Roach 'hourglass' => I18N::translate('Hourglass chart'), 258fddfbb14SGreg Roach 'treenav' => I18N::translate('Interactive tree'), 25913abd6f3SGreg Roach ]; 26037646143SGreg Roach uasort($charts, I18N::comparator()); 261fddfbb14SGreg Roach 2626b9cb339SGreg Roach $individual = Registry::individualFactory()->make($xref, $tree); 263c385536dSGreg Roach 2643caaa4d2SGreg Roach return view('modules/charts/config', [ 265c385536dSGreg Roach 'charts' => $charts, 266c385536dSGreg Roach 'individual' => $individual, 267e490cd80SGreg Roach 'tree' => $tree, 268c385536dSGreg Roach 'type' => $type, 269c385536dSGreg Roach ]); 2708c2e8227SGreg Roach } 2718c2e8227SGreg Roach} 272