149a243cbSGreg Roach<?php 23976b470SGreg Roach 349a243cbSGreg Roach/** 449a243cbSGreg Roach * webtrees: online genealogy 549a243cbSGreg Roach * Copyright (C) 2019 webtrees development team 649a243cbSGreg Roach * This program is free software: you can redistribute it and/or modify 749a243cbSGreg Roach * it under the terms of the GNU General Public License as published by 849a243cbSGreg Roach * the Free Software Foundation, either version 3 of the License, or 949a243cbSGreg Roach * (at your option) any later version. 1049a243cbSGreg Roach * This program is distributed in the hope that it will be useful, 1149a243cbSGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 1249a243cbSGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1349a243cbSGreg Roach * GNU General Public License for more details. 1449a243cbSGreg Roach * You should have received a copy of the GNU General Public License 1549a243cbSGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>. 1649a243cbSGreg Roach */ 17fcfa147eSGreg Roach 1849a243cbSGreg Roachdeclare(strict_types=1); 1949a243cbSGreg Roach 2049a243cbSGreg Roachnamespace Fisharebest\Webtrees\Module; 2149a243cbSGreg Roach 2290a2f718SGreg Roachuse Fisharebest\Localization\Locale\LocaleInterface; 23ade503dfSGreg Roachuse Fisharebest\Webtrees\Auth; 24ade503dfSGreg Roachuse Fisharebest\Webtrees\Fact; 25ade503dfSGreg Roachuse Fisharebest\Webtrees\Gedcom; 26ade503dfSGreg Roachuse Fisharebest\Webtrees\GedcomTag; 27a49d0e3fSGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\AccountEdit; 280c0910bfSGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\ControlPanel; 299b541e4aSGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\HomePage; 3056f9a9c1SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\LoginPage; 3156f9a9c1SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\Logout; 3222e73debSGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\PendingChanges; 337adfb8e5SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\SelectLanguage; 347adfb8e5SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\SelectTheme; 35ade503dfSGreg Roachuse Fisharebest\Webtrees\I18N; 36ade503dfSGreg Roachuse Fisharebest\Webtrees\Individual; 37ade503dfSGreg Roachuse Fisharebest\Webtrees\Menu; 384ca7e03cSGreg Roachuse Fisharebest\Webtrees\Services\ModuleService; 39ade503dfSGreg Roachuse Fisharebest\Webtrees\Tree; 40f397d0fdSGreg Roachuse Fisharebest\Webtrees\Webtrees; 416ccdf4f0SGreg Roachuse Psr\Http\Message\ServerRequestInterface; 423976b470SGreg Roach 436ccdf4f0SGreg Roachuse function app; 4490a2f718SGreg Roachuse function assert; 457adfb8e5SGreg Roachuse function route; 46ade503dfSGreg Roach 4749a243cbSGreg Roach/** 4849a243cbSGreg Roach * Trait ModuleThemeTrait - default implementation of ModuleThemeInterface 4949a243cbSGreg Roach */ 5049a243cbSGreg Roachtrait ModuleThemeTrait 5149a243cbSGreg Roach{ 52ade503dfSGreg Roach /** 53962ead51SGreg Roach * @return string 54962ead51SGreg Roach */ 55962ead51SGreg Roach abstract public function name(): string; 56962ead51SGreg Roach 57962ead51SGreg Roach /** 58962ead51SGreg Roach * @return string 59962ead51SGreg Roach */ 60962ead51SGreg Roach abstract public function title(): string; 61962ead51SGreg Roach 62962ead51SGreg Roach /** 633d8b2a8eSGreg Roach * A sentence describing what this module does. 643d8b2a8eSGreg Roach * 653d8b2a8eSGreg Roach * @return string 663d8b2a8eSGreg Roach */ 673d8b2a8eSGreg Roach public function description(): string 683d8b2a8eSGreg Roach { 693d8b2a8eSGreg Roach return I18N::translate('Theme') . ' — ' . $this->title(); 703d8b2a8eSGreg Roach } 713d8b2a8eSGreg Roach 723d8b2a8eSGreg Roach /** 73ade503dfSGreg Roach * Display an icon for this fact. 74ade503dfSGreg Roach * 75e837ff07SGreg Roach * @TODO use CSS for this 76e837ff07SGreg Roach * 77ade503dfSGreg Roach * @param Fact $fact 78ade503dfSGreg Roach * 79ade503dfSGreg Roach * @return string 80ade503dfSGreg Roach */ 81ade503dfSGreg Roach public function icon(Fact $fact): string 82ade503dfSGreg Roach { 83e837ff07SGreg Roach $asset = 'public/css/' . $this->name() . '/images/facts/' . $fact->getTag() . '.png'; 84f397d0fdSGreg Roach if (file_exists(Webtrees::ROOT_DIR . 'public' . $asset)) { 85e837ff07SGreg Roach return '<img src="' . e(asset($asset)) . '" title="' . GedcomTag::getLabel($fact->getTag()) . '">'; 86ade503dfSGreg Roach } 87ade503dfSGreg Roach 88ade503dfSGreg Roach // Spacer image - for alignment - until we move to a sprite. 89e837ff07SGreg Roach $asset = 'public/css/' . $this->name() . '/images/facts/NULL.png'; 90f397d0fdSGreg Roach if (file_exists(Webtrees::ROOT_DIR . 'public' . $asset)) { 91e837ff07SGreg Roach return '<img src="' . e(asset($asset)) . '">'; 92ade503dfSGreg Roach } 93ade503dfSGreg Roach 94ade503dfSGreg Roach return ''; 95ade503dfSGreg Roach } 96ade503dfSGreg Roach 97ade503dfSGreg Roach /** 98ade503dfSGreg Roach * Generate the facts, for display in charts. 99ade503dfSGreg Roach * 100ade503dfSGreg Roach * @param Individual $individual 101ade503dfSGreg Roach * 102ade503dfSGreg Roach * @return string 103ade503dfSGreg Roach */ 104ade503dfSGreg Roach public function individualBoxFacts(Individual $individual): string 105ade503dfSGreg Roach { 106ade503dfSGreg Roach $html = ''; 107ade503dfSGreg Roach 108ade503dfSGreg Roach $opt_tags = preg_split('/\W/', $individual->tree()->getPreference('CHART_BOX_TAGS'), 0, PREG_SPLIT_NO_EMPTY); 109ade503dfSGreg Roach // Show BIRT or equivalent event 110ade503dfSGreg Roach foreach (Gedcom::BIRTH_EVENTS as $birttag) { 11122d65e5aSGreg Roach if (!in_array($birttag, $opt_tags, true)) { 112820b62dfSGreg Roach $event = $individual->facts([$birttag])->first(); 113820b62dfSGreg Roach if ($event instanceof Fact) { 114ade503dfSGreg Roach $html .= $event->summary(); 115ade503dfSGreg Roach break; 116ade503dfSGreg Roach } 117ade503dfSGreg Roach } 118ade503dfSGreg Roach } 119ade503dfSGreg Roach // Show optional events (before death) 120ade503dfSGreg Roach foreach ($opt_tags as $key => $tag) { 12122d65e5aSGreg Roach if (!in_array($tag, Gedcom::DEATH_EVENTS, true)) { 122820b62dfSGreg Roach $event = $individual->facts([$tag])->first(); 123820b62dfSGreg Roach if ($event instanceof Fact) { 124ade503dfSGreg Roach $html .= $event->summary(); 125ade503dfSGreg Roach unset($opt_tags[$key]); 126ade503dfSGreg Roach } 127ade503dfSGreg Roach } 128ade503dfSGreg Roach } 129ade503dfSGreg Roach // Show DEAT or equivalent event 130ade503dfSGreg Roach foreach (Gedcom::DEATH_EVENTS as $deattag) { 131820b62dfSGreg Roach $event = $individual->facts([$deattag])->first(); 132820b62dfSGreg Roach if ($event instanceof Fact) { 133ade503dfSGreg Roach $html .= $event->summary(); 13422d65e5aSGreg Roach if (in_array($deattag, $opt_tags, true)) { 13522d65e5aSGreg Roach unset($opt_tags[array_search($deattag, $opt_tags, true)]); 136ade503dfSGreg Roach } 137ade503dfSGreg Roach break; 138ade503dfSGreg Roach } 139ade503dfSGreg Roach } 140ade503dfSGreg Roach // Show remaining optional events (after death) 141ade503dfSGreg Roach foreach ($opt_tags as $tag) { 142820b62dfSGreg Roach $event = $individual->facts([$tag])->first(); 143820b62dfSGreg Roach if ($event instanceof Fact) { 144ade503dfSGreg Roach $html .= $event->summary(); 145ade503dfSGreg Roach } 146ade503dfSGreg Roach } 147ade503dfSGreg Roach 148ade503dfSGreg Roach return $html; 149ade503dfSGreg Roach } 150ade503dfSGreg Roach 151ade503dfSGreg Roach /** 152ade503dfSGreg Roach * Links, to show in chart boxes; 153ade503dfSGreg Roach * 154ade503dfSGreg Roach * @param Individual $individual 155ade503dfSGreg Roach * 156ade503dfSGreg Roach * @return Menu[] 157ade503dfSGreg Roach */ 158ade503dfSGreg Roach public function individualBoxMenu(Individual $individual): array 159ade503dfSGreg Roach { 160ade503dfSGreg Roach $menus = array_merge( 161ade503dfSGreg Roach $this->individualBoxMenuCharts($individual), 162ade503dfSGreg Roach $this->individualBoxMenuFamilyLinks($individual) 163ade503dfSGreg Roach ); 164ade503dfSGreg Roach 165ade503dfSGreg Roach return $menus; 166ade503dfSGreg Roach } 167ade503dfSGreg Roach 168ade503dfSGreg Roach /** 169ade503dfSGreg Roach * Chart links, to show in chart boxes; 170ade503dfSGreg Roach * 171ade503dfSGreg Roach * @param Individual $individual 172ade503dfSGreg Roach * 173ade503dfSGreg Roach * @return Menu[] 174ade503dfSGreg Roach */ 175ade503dfSGreg Roach public function individualBoxMenuCharts(Individual $individual): array 176ade503dfSGreg Roach { 177ade503dfSGreg Roach $menus = []; 178f39638cfSGreg Roach foreach (app(ModuleService::class)->findByComponent(ModuleChartInterface::class, $individual->tree(), Auth::user()) as $chart) { 179ade503dfSGreg Roach $menu = $chart->chartBoxMenu($individual); 180ade503dfSGreg Roach if ($menu) { 181ade503dfSGreg Roach $menus[] = $menu; 182ade503dfSGreg Roach } 183ade503dfSGreg Roach } 184ade503dfSGreg Roach 1850b93976aSGreg Roach usort($menus, static function (Menu $x, Menu $y): int { 186ade503dfSGreg Roach return I18N::strcasecmp($x->getLabel(), $y->getLabel()); 187ade503dfSGreg Roach }); 188ade503dfSGreg Roach 189ade503dfSGreg Roach return $menus; 190ade503dfSGreg Roach } 191ade503dfSGreg Roach 192ade503dfSGreg Roach /** 193ade503dfSGreg Roach * Family links, to show in chart boxes. 194ade503dfSGreg Roach * 195ade503dfSGreg Roach * @param Individual $individual 196ade503dfSGreg Roach * 197ade503dfSGreg Roach * @return Menu[] 198ade503dfSGreg Roach */ 199ade503dfSGreg Roach public function individualBoxMenuFamilyLinks(Individual $individual): array 200ade503dfSGreg Roach { 201ade503dfSGreg Roach $menus = []; 202ade503dfSGreg Roach 20339ca88baSGreg Roach foreach ($individual->spouseFamilies() as $family) { 204ade503dfSGreg Roach $menus[] = new Menu('<strong>' . I18N::translate('Family with spouse') . '</strong>', $family->url()); 20539ca88baSGreg Roach $spouse = $family->spouse($individual); 206ade503dfSGreg Roach if ($spouse && $spouse->canShowName()) { 20739ca88baSGreg Roach $menus[] = new Menu($spouse->fullName(), $spouse->url()); 208ade503dfSGreg Roach } 20939ca88baSGreg Roach foreach ($family->children() as $child) { 210ade503dfSGreg Roach if ($child->canShowName()) { 21139ca88baSGreg Roach $menus[] = new Menu($child->fullName(), $child->url()); 212ade503dfSGreg Roach } 213ade503dfSGreg Roach } 214ade503dfSGreg Roach } 215ade503dfSGreg Roach 216ade503dfSGreg Roach return $menus; 217ade503dfSGreg Roach } 218ade503dfSGreg Roach 219ade503dfSGreg Roach /** 220f567c3d8SGreg Roach * Generate a menu item to change the blocks on the current tree/user page. 221ade503dfSGreg Roach * 2220c8c69d4SGreg Roach * @param Tree $tree 2230c8c69d4SGreg Roach * 224ade503dfSGreg Roach * @return Menu|null 225ade503dfSGreg Roach */ 226e364afe4SGreg Roach public function menuChangeBlocks(Tree $tree): ?Menu 227ade503dfSGreg Roach { 228eb235819SGreg Roach /** @var ServerRequestInterface $request */ 2296ccdf4f0SGreg Roach $request = app(ServerRequestInterface::class); 230e6bcfa02SGreg Roach 2310d7461faSGreg Roach $route = $request->getAttribute('route'); 232eb235819SGreg Roach 233eb235819SGreg Roach if (Auth::check() && $route === 'user-page') { 234d72b284aSGreg Roach return new Menu(I18N::translate('Customize this page'), route('user-page-edit', ['tree' => $tree->name()]), 'menu-change-blocks'); 235ade503dfSGreg Roach } 236ade503dfSGreg Roach 237eb235819SGreg Roach if (Auth::isManager($tree) && $route === 'tree-page') { 238d72b284aSGreg Roach return new Menu(I18N::translate('Customize this page'), route('tree-page-edit', ['tree' => $tree->name()]), 'menu-change-blocks'); 239ade503dfSGreg Roach } 240ade503dfSGreg Roach 241ade503dfSGreg Roach return null; 242ade503dfSGreg Roach } 243ade503dfSGreg Roach 244ade503dfSGreg Roach /** 245ade503dfSGreg Roach * Generate a menu item for the control panel. 246ade503dfSGreg Roach * 2470c8c69d4SGreg Roach * @param Tree $tree 2480c8c69d4SGreg Roach * 249ade503dfSGreg Roach * @return Menu|null 250ade503dfSGreg Roach */ 251e364afe4SGreg Roach public function menuControlPanel(Tree $tree): ?Menu 252ade503dfSGreg Roach { 253ade503dfSGreg Roach if (Auth::isAdmin()) { 2540c0910bfSGreg Roach return new Menu(I18N::translate('Control panel'), route(ControlPanel::class), 'menu-admin'); 255ade503dfSGreg Roach } 256ade503dfSGreg Roach 2570c8c69d4SGreg Roach if (Auth::isManager($tree)) { 2580c0910bfSGreg Roach return new Menu(I18N::translate('Control panel'), route('manage-trees'), 'menu-admin'); 259ade503dfSGreg Roach } 260ade503dfSGreg Roach 261ade503dfSGreg Roach return null; 262ade503dfSGreg Roach } 263ade503dfSGreg Roach 264ade503dfSGreg Roach /** 265ade503dfSGreg Roach * A menu to show a list of available languages. 266ade503dfSGreg Roach * 267ade503dfSGreg Roach * @return Menu|null 268ade503dfSGreg Roach */ 269e364afe4SGreg Roach public function menuLanguages(): ?Menu 270ade503dfSGreg Roach { 27190a2f718SGreg Roach $locale = app(ServerRequestInterface::class)->getAttribute('locale'); 27290a2f718SGreg Roach assert($locale instanceof LocaleInterface); 27390a2f718SGreg Roach 274ade503dfSGreg Roach $menu = new Menu(I18N::translate('Language'), '#', 'menu-language'); 275ade503dfSGreg Roach 27690a2f718SGreg Roach foreach (I18N::activeLocales() as $active_locale) { 27790a2f718SGreg Roach $language_tag = $active_locale->languageTag(); 27890a2f718SGreg Roach $class = 'menu-language-' . $language_tag . ($locale->languageTag() === $language_tag ? ' active' : ''); 27990a2f718SGreg Roach $menu->addSubmenu(new Menu($active_locale->endonym(), '#', $class, [ 2807adfb8e5SGreg Roach 'data-post-url' => route(SelectLanguage::class, ['language' => $language_tag]), 281ade503dfSGreg Roach ])); 282ade503dfSGreg Roach } 283ade503dfSGreg Roach 284ade503dfSGreg Roach if (count($menu->getSubmenus()) > 1) { 285ade503dfSGreg Roach return $menu; 286ade503dfSGreg Roach } 287ade503dfSGreg Roach 288ade503dfSGreg Roach return null; 289ade503dfSGreg Roach } 290ade503dfSGreg Roach 291ade503dfSGreg Roach /** 292ade503dfSGreg Roach * A login menu option (or null if we are already logged in). 293ade503dfSGreg Roach * 294ade503dfSGreg Roach * @return Menu|null 295ade503dfSGreg Roach */ 296e364afe4SGreg Roach public function menuLogin(): ?Menu 297ade503dfSGreg Roach { 298ade503dfSGreg Roach if (Auth::check()) { 299ade503dfSGreg Roach return null; 300ade503dfSGreg Roach } 301ade503dfSGreg Roach 30286661454SGreg Roach $request = app(ServerRequestInterface::class); 30386661454SGreg Roach 304ade503dfSGreg Roach // Return to this page after login... 305*b6c0b825SGreg Roach $redirect = $request->getQueryParams()['url'] ?? (string) $request->getUri(); 306ade503dfSGreg Roach 307ade503dfSGreg Roach // ...but switch from the tree-page to the user-page 30891c514e5SGreg Roach if ($request->getAttribute('route') === 'tree-page') { 30991c514e5SGreg Roach $tree = $request->getAttribute('tree'); 31075964c75SGreg Roach assert($tree instanceof Tree); 31191c514e5SGreg Roach $redirect = route('user-page', ['tree' => $tree->name()]); 31291c514e5SGreg Roach } 313ade503dfSGreg Roach 31486661454SGreg Roach // Stay on the same tree page 31586661454SGreg Roach $tree = $request->getAttribute('tree'); 31691c514e5SGreg Roach $url = route(LoginPage::class, ['tree' => $tree instanceof Tree ? $tree->name() : null, 'url' => $redirect]); 31786661454SGreg Roach 31886661454SGreg Roach return new Menu(I18N::translate('Sign in'), $url, 'menu-login', ['rel' => 'nofollow']); 319ade503dfSGreg Roach } 320ade503dfSGreg Roach 321ade503dfSGreg Roach /** 322ade503dfSGreg Roach * A logout menu option (or null if we are already logged out). 323ade503dfSGreg Roach * 324ade503dfSGreg Roach * @return Menu|null 325ade503dfSGreg Roach */ 326e364afe4SGreg Roach public function menuLogout(): ?Menu 327ade503dfSGreg Roach { 328ade503dfSGreg Roach if (Auth::check()) { 3299b541e4aSGreg Roach $parameters = [ 3309b541e4aSGreg Roach 'data-post-url' => route(Logout::class), 3319b541e4aSGreg Roach 'data-reload-url' => route(HomePage::class), 3329b541e4aSGreg Roach ]; 3339b541e4aSGreg Roach 3349b541e4aSGreg Roach return new Menu(I18N::translate('Sign out'), '#', 'menu-logout', $parameters); 335ade503dfSGreg Roach } 336ade503dfSGreg Roach 337ade503dfSGreg Roach return null; 338ade503dfSGreg Roach } 339ade503dfSGreg Roach 340ade503dfSGreg Roach /** 341ade503dfSGreg Roach * A link to allow users to edit their account settings. 342ade503dfSGreg Roach * 34365aec466SGreg Roach * @param Tree|null $tree 344a49d0e3fSGreg Roach * 345a49d0e3fSGreg Roach * @return Menu 346ade503dfSGreg Roach */ 347a49d0e3fSGreg Roach public function menuMyAccount(?Tree $tree): Menu 348ade503dfSGreg Roach { 349a49d0e3fSGreg Roach $url = route(AccountEdit::class, ['tree' => $tree instanceof Tree ? $tree->name() : null]); 350ade503dfSGreg Roach 351a49d0e3fSGreg Roach return new Menu(I18N::translate('My account'), $url); 352ade503dfSGreg Roach } 353ade503dfSGreg Roach 354ade503dfSGreg Roach /** 355ade503dfSGreg Roach * A link to the user's individual record (individual.php). 356ade503dfSGreg Roach * 3570c8c69d4SGreg Roach * @param Tree $tree 3580c8c69d4SGreg Roach * 359ade503dfSGreg Roach * @return Menu|null 360ade503dfSGreg Roach */ 361e364afe4SGreg Roach public function menuMyIndividualRecord(Tree $tree): ?Menu 362ade503dfSGreg Roach { 3630c8c69d4SGreg Roach $record = Individual::getInstance($tree->getUserPreference(Auth::user(), 'gedcomid'), $tree); 364ade503dfSGreg Roach 365ade503dfSGreg Roach if ($record) { 366ade503dfSGreg Roach return new Menu(I18N::translate('My individual record'), $record->url(), 'menu-myrecord'); 367ade503dfSGreg Roach } 368ade503dfSGreg Roach 369ade503dfSGreg Roach return null; 370ade503dfSGreg Roach } 371ade503dfSGreg Roach 372ade503dfSGreg Roach /** 373ade503dfSGreg Roach * A link to the user's personal home page. 374ade503dfSGreg Roach * 3750c8c69d4SGreg Roach * @param Tree $tree 3760c8c69d4SGreg Roach * 377ade503dfSGreg Roach * @return Menu 378ade503dfSGreg Roach */ 3790c8c69d4SGreg Roach public function menuMyPage(Tree $tree): Menu 380ade503dfSGreg Roach { 381d72b284aSGreg Roach return new Menu(I18N::translate('My page'), route('user-page', ['tree' => $tree->name()]), 'menu-mypage'); 382ade503dfSGreg Roach } 383ade503dfSGreg Roach 384ade503dfSGreg Roach /** 385ade503dfSGreg Roach * A menu for the user's personal pages. 386ade503dfSGreg Roach * 3870c8c69d4SGreg Roach * @param Tree|null $tree 3880c8c69d4SGreg Roach * 389ade503dfSGreg Roach * @return Menu|null 390ade503dfSGreg Roach */ 391e364afe4SGreg Roach public function menuMyPages(?Tree $tree): ?Menu 392ade503dfSGreg Roach { 393a49d0e3fSGreg Roach if (Auth::id()) { 394a49d0e3fSGreg Roach if ($tree instanceof Tree) { 395ade503dfSGreg Roach return new Menu(I18N::translate('My pages'), '#', 'menu-mymenu', [], array_filter([ 3960c8c69d4SGreg Roach $this->menuMyPage($tree), 3970c8c69d4SGreg Roach $this->menuMyIndividualRecord($tree), 3980c8c69d4SGreg Roach $this->menuMyPedigree($tree), 399a49d0e3fSGreg Roach $this->menuMyAccount($tree), 4000c8c69d4SGreg Roach $this->menuControlPanel($tree), 4010c8c69d4SGreg Roach $this->menuChangeBlocks($tree), 402ade503dfSGreg Roach ])); 403ade503dfSGreg Roach } 404ade503dfSGreg Roach 405a49d0e3fSGreg Roach return $this->menuMyAccount($tree); 406a49d0e3fSGreg Roach } 407a49d0e3fSGreg Roach 408ade503dfSGreg Roach return null; 409ade503dfSGreg Roach } 410ade503dfSGreg Roach 411ade503dfSGreg Roach /** 412ade503dfSGreg Roach * A link to the user's individual record. 413ade503dfSGreg Roach * 4140c8c69d4SGreg Roach * @param Tree $tree 4150c8c69d4SGreg Roach * 416ade503dfSGreg Roach * @return Menu|null 417ade503dfSGreg Roach */ 418e364afe4SGreg Roach public function menuMyPedigree(Tree $tree): ?Menu 419ade503dfSGreg Roach { 4200c8c69d4SGreg Roach $gedcomid = $tree->getUserPreference(Auth::user(), 'gedcomid'); 421ade503dfSGreg Roach 4220c8c69d4SGreg Roach $pedigree_chart = app(ModuleService::class)->findByComponent(ModuleChartInterface::class, $tree, Auth::user()) 4230b5fd0a6SGreg Roach ->filter(static function (ModuleInterface $module): bool { 424ade503dfSGreg Roach return $module instanceof PedigreeChartModule; 425ade503dfSGreg Roach }); 426ade503dfSGreg Roach 427ade503dfSGreg Roach if ($gedcomid !== '' && $pedigree_chart instanceof PedigreeChartModule) { 428ade503dfSGreg Roach return new Menu( 429ade503dfSGreg Roach I18N::translate('My pedigree'), 430ade503dfSGreg Roach route('pedigree', [ 431ade503dfSGreg Roach 'xref' => $gedcomid, 4329022ab66SGreg Roach 'tree' => $tree->name(), 433ade503dfSGreg Roach ]), 434ade503dfSGreg Roach 'menu-mypedigree' 435ade503dfSGreg Roach ); 436ade503dfSGreg Roach } 437ade503dfSGreg Roach 438ade503dfSGreg Roach return null; 439ade503dfSGreg Roach } 440ade503dfSGreg Roach 441ade503dfSGreg Roach /** 442ade503dfSGreg Roach * Create a pending changes menu. 443ade503dfSGreg Roach * 4440c8c69d4SGreg Roach * @param Tree|null $tree 4450c8c69d4SGreg Roach * 446ade503dfSGreg Roach * @return Menu|null 447ade503dfSGreg Roach */ 448e364afe4SGreg Roach public function menuPendingChanges(?Tree $tree): ?Menu 449ade503dfSGreg Roach { 4500c8c69d4SGreg Roach if ($tree instanceof Tree && $tree->hasPendingEdit() && Auth::isModerator($tree)) { 45122e73debSGreg Roach $url = route(PendingChanges::class, [ 4529022ab66SGreg Roach 'tree' => $tree->name(), 453cf8c0692SGreg Roach 'url' => (string) app(ServerRequestInterface::class)->getUri(), 454ade503dfSGreg Roach ]); 455ade503dfSGreg Roach 456ade503dfSGreg Roach return new Menu(I18N::translate('Pending changes'), $url, 'menu-pending'); 457ade503dfSGreg Roach } 458ade503dfSGreg Roach 459ade503dfSGreg Roach return null; 460ade503dfSGreg Roach } 461ade503dfSGreg Roach 462ade503dfSGreg Roach /** 463ade503dfSGreg Roach * Themes menu. 464ade503dfSGreg Roach * 465ade503dfSGreg Roach * @return Menu|null 466ade503dfSGreg Roach */ 467e364afe4SGreg Roach public function menuThemes(): ?Menu 468ade503dfSGreg Roach { 469b668782fSGreg Roach $themes = app(ModuleService::class)->findByInterface(ModuleThemeInterface::class, false, true); 470df8baf00SGreg Roach 471cab242e7SGreg Roach $current_theme = app(ModuleThemeInterface::class); 4728136679eSGreg Roach 4738136679eSGreg Roach if ($themes->count() > 1) { 4740b5fd0a6SGreg Roach $submenus = $themes->map(static function (ModuleThemeInterface $theme) use ($current_theme): Menu { 4758136679eSGreg Roach $active = $theme->name() === $current_theme->name(); 4768136679eSGreg Roach $class = 'menu-theme-' . $theme->name() . ($active ? ' active' : ''); 4778136679eSGreg Roach 4788136679eSGreg Roach return new Menu($theme->title(), '#', $class, [ 4797adfb8e5SGreg Roach 'data-post-url' => route(SelectTheme::class, ['theme' => $theme->name()]), 480ade503dfSGreg Roach ]); 481ade503dfSGreg Roach }); 482ade503dfSGreg Roach 4838136679eSGreg Roach return new Menu(I18N::translate('Theme'), '#', 'menu-theme', [], $submenus->all()); 484ade503dfSGreg Roach } 485ade503dfSGreg Roach 486ade503dfSGreg Roach return null; 487ade503dfSGreg Roach } 488ade503dfSGreg Roach 489ade503dfSGreg Roach /** 490ade503dfSGreg Roach * Misecellaneous dimensions, fonts, styles, etc. 491ade503dfSGreg Roach * 492ade503dfSGreg Roach * @param string $parameter_name 493ade503dfSGreg Roach * 494ade503dfSGreg Roach * @return string|int|float 495ade503dfSGreg Roach */ 496ade503dfSGreg Roach public function parameter($parameter_name) 497ade503dfSGreg Roach { 498ade503dfSGreg Roach return ''; 499ade503dfSGreg Roach } 500ade503dfSGreg Roach 501ade503dfSGreg Roach /** 502ade503dfSGreg Roach * Generate a list of items for the main menu. 503ade503dfSGreg Roach * 5040c8c69d4SGreg Roach * @param Tree|null $tree 5050c8c69d4SGreg Roach * 506ade503dfSGreg Roach * @return Menu[] 507ade503dfSGreg Roach */ 5080c8c69d4SGreg Roach public function genealogyMenu(?Tree $tree): array 509ade503dfSGreg Roach { 5100c8c69d4SGreg Roach if ($tree === null) { 5110c8c69d4SGreg Roach return []; 5120c8c69d4SGreg Roach } 5130c8c69d4SGreg Roach 5140c8c69d4SGreg Roach return app(ModuleService::class)->findByComponent(ModuleMenuInterface::class, $tree, Auth::user()) 5150b5fd0a6SGreg Roach ->map(static function (ModuleMenuInterface $menu) use ($tree): ?Menu { 5160c8c69d4SGreg Roach return $menu->getMenu($tree); 517ade503dfSGreg Roach }) 518ade503dfSGreg Roach ->filter() 519ade503dfSGreg Roach ->all(); 520ade503dfSGreg Roach } 521ade503dfSGreg Roach 522ade503dfSGreg Roach /** 5230c8c69d4SGreg Roach * Create the genealogy menu. 524ade503dfSGreg Roach * 525ade503dfSGreg Roach * @param Menu[] $menus 526ade503dfSGreg Roach * 527ade503dfSGreg Roach * @return string 528ade503dfSGreg Roach */ 5290c8c69d4SGreg Roach public function genealogyMenuContent(array $menus): string 530ade503dfSGreg Roach { 5310b5fd0a6SGreg Roach return implode('', array_map(static function (Menu $menu): string { 532ade503dfSGreg Roach return $menu->bootstrap4(); 533ade503dfSGreg Roach }, $menus)); 534ade503dfSGreg Roach } 535ade503dfSGreg Roach 536ade503dfSGreg Roach /** 537ade503dfSGreg Roach * Generate a list of items for the user menu. 538ade503dfSGreg Roach * 5390c8c69d4SGreg Roach * @param Tree|null $tree 5400c8c69d4SGreg Roach * 541ade503dfSGreg Roach * @return Menu[] 542ade503dfSGreg Roach */ 5430c8c69d4SGreg Roach public function userMenu(?Tree $tree): array 544ade503dfSGreg Roach { 545ade503dfSGreg Roach return array_filter([ 5460c8c69d4SGreg Roach $this->menuPendingChanges($tree), 5470c8c69d4SGreg Roach $this->menuMyPages($tree), 548ade503dfSGreg Roach $this->menuThemes(), 549ade503dfSGreg Roach $this->menuLanguages(), 550ade503dfSGreg Roach $this->menuLogin(), 551ade503dfSGreg Roach $this->menuLogout(), 552ade503dfSGreg Roach ]); 553ade503dfSGreg Roach } 554ade503dfSGreg Roach 555ade503dfSGreg Roach /** 556ade503dfSGreg Roach * A list of CSS files to include for this page. 557ade503dfSGreg Roach * 558ade503dfSGreg Roach * @return string[] 559ade503dfSGreg Roach */ 560ade503dfSGreg Roach public function stylesheets(): array 561ade503dfSGreg Roach { 562ade503dfSGreg Roach return []; 563ade503dfSGreg Roach } 56449a243cbSGreg Roach} 565