149a243cbSGreg Roach<?php 23976b470SGreg Roach 349a243cbSGreg Roach/** 449a243cbSGreg Roach * webtrees: online genealogy 51fe542e9SGreg Roach * Copyright (C) 2021 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 1589f7189bSGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>. 1649a243cbSGreg Roach */ 17fcfa147eSGreg Roach 1849a243cbSGreg Roachdeclare(strict_types=1); 1949a243cbSGreg Roach 2049a243cbSGreg Roachnamespace Fisharebest\Webtrees\Module; 2149a243cbSGreg Roach 22de2aa325SGreg Roachuse Aura\Router\Route; 23ade503dfSGreg Roachuse Fisharebest\Webtrees\Auth; 241fe542e9SGreg Roachuse Fisharebest\Webtrees\Contracts\UserInterface; 25ade503dfSGreg Roachuse Fisharebest\Webtrees\Fact; 266b9cb339SGreg Roachuse Fisharebest\Webtrees\Registry; 27ade503dfSGreg Roachuse Fisharebest\Webtrees\Gedcom; 28a49d0e3fSGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\AccountEdit; 290c0910bfSGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\ControlPanel; 30ea101122SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\HomePage; 3156f9a9c1SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\LoginPage; 3256f9a9c1SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\Logout; 336fd01894SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\ManageTrees; 3422e73debSGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\PendingChanges; 357adfb8e5SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\SelectLanguage; 367adfb8e5SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\SelectTheme; 378e0e1b25SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\TreePage; 388e0e1b25SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\TreePageEdit; 398e0e1b25SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\UserPage; 408e0e1b25SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\UserPageEdit; 41ade503dfSGreg Roachuse Fisharebest\Webtrees\I18N; 42ade503dfSGreg Roachuse Fisharebest\Webtrees\Individual; 43ade503dfSGreg Roachuse Fisharebest\Webtrees\Menu; 444ca7e03cSGreg Roachuse Fisharebest\Webtrees\Services\ModuleService; 45ade503dfSGreg Roachuse Fisharebest\Webtrees\Tree; 466ccdf4f0SGreg Roachuse Psr\Http\Message\ServerRequestInterface; 473976b470SGreg Roach 486ccdf4f0SGreg Roachuse function app; 49de2aa325SGreg Roachuse function assert; 507adfb8e5SGreg Roachuse function route; 51f78837dcSGreg Roachuse function view; 52ade503dfSGreg Roach 5349a243cbSGreg Roach/** 5449a243cbSGreg Roach * Trait ModuleThemeTrait - default implementation of ModuleThemeInterface 5549a243cbSGreg Roach */ 5649a243cbSGreg Roachtrait ModuleThemeTrait 5749a243cbSGreg Roach{ 58ade503dfSGreg Roach /** 593d8b2a8eSGreg Roach * A sentence describing what this module does. 603d8b2a8eSGreg Roach * 613d8b2a8eSGreg Roach * @return string 623d8b2a8eSGreg Roach */ 633d8b2a8eSGreg Roach public function description(): string 643d8b2a8eSGreg Roach { 653d8b2a8eSGreg Roach return I18N::translate('Theme') . ' — ' . $this->title(); 663d8b2a8eSGreg Roach } 673d8b2a8eSGreg Roach 683d8b2a8eSGreg Roach /** 69ade503dfSGreg Roach * Generate the facts, for display in charts. 70ade503dfSGreg Roach * 71ade503dfSGreg Roach * @param Individual $individual 72ade503dfSGreg Roach * 73ade503dfSGreg Roach * @return string 74ade503dfSGreg Roach */ 75ade503dfSGreg Roach public function individualBoxFacts(Individual $individual): string 76ade503dfSGreg Roach { 77ade503dfSGreg Roach $html = ''; 78ade503dfSGreg Roach 79ade503dfSGreg Roach $opt_tags = preg_split('/\W/', $individual->tree()->getPreference('CHART_BOX_TAGS'), 0, PREG_SPLIT_NO_EMPTY); 80ade503dfSGreg Roach // Show BIRT or equivalent event 81ade503dfSGreg Roach foreach (Gedcom::BIRTH_EVENTS as $birttag) { 8222d65e5aSGreg Roach if (!in_array($birttag, $opt_tags, true)) { 83820b62dfSGreg Roach $event = $individual->facts([$birttag])->first(); 84820b62dfSGreg Roach if ($event instanceof Fact) { 85ade503dfSGreg Roach $html .= $event->summary(); 86ade503dfSGreg Roach break; 87ade503dfSGreg Roach } 88ade503dfSGreg Roach } 89ade503dfSGreg Roach } 90ade503dfSGreg Roach // Show optional events (before death) 91ade503dfSGreg Roach foreach ($opt_tags as $key => $tag) { 9222d65e5aSGreg Roach if (!in_array($tag, Gedcom::DEATH_EVENTS, true)) { 93820b62dfSGreg Roach $event = $individual->facts([$tag])->first(); 94820b62dfSGreg Roach if ($event instanceof Fact) { 95ade503dfSGreg Roach $html .= $event->summary(); 96ade503dfSGreg Roach unset($opt_tags[$key]); 97ade503dfSGreg Roach } 98ade503dfSGreg Roach } 99ade503dfSGreg Roach } 100ade503dfSGreg Roach // Show DEAT or equivalent event 101ade503dfSGreg Roach foreach (Gedcom::DEATH_EVENTS as $deattag) { 102820b62dfSGreg Roach $event = $individual->facts([$deattag])->first(); 103820b62dfSGreg Roach if ($event instanceof Fact) { 104ade503dfSGreg Roach $html .= $event->summary(); 10522d65e5aSGreg Roach if (in_array($deattag, $opt_tags, true)) { 10622d65e5aSGreg Roach unset($opt_tags[array_search($deattag, $opt_tags, true)]); 107ade503dfSGreg Roach } 108ade503dfSGreg Roach break; 109ade503dfSGreg Roach } 110ade503dfSGreg Roach } 111ade503dfSGreg Roach // Show remaining optional events (after death) 112ade503dfSGreg Roach foreach ($opt_tags as $tag) { 113820b62dfSGreg Roach $event = $individual->facts([$tag])->first(); 114820b62dfSGreg Roach if ($event instanceof Fact) { 115ade503dfSGreg Roach $html .= $event->summary(); 116ade503dfSGreg Roach } 117ade503dfSGreg Roach } 118ade503dfSGreg Roach 119ade503dfSGreg Roach return $html; 120ade503dfSGreg Roach } 121ade503dfSGreg Roach 122ade503dfSGreg Roach /** 123ade503dfSGreg Roach * Links, to show in chart boxes; 124ade503dfSGreg Roach * 125ade503dfSGreg Roach * @param Individual $individual 126ade503dfSGreg Roach * 127ade503dfSGreg Roach * @return Menu[] 128ade503dfSGreg Roach */ 129ade503dfSGreg Roach public function individualBoxMenu(Individual $individual): array 130ade503dfSGreg Roach { 131aa6311c7SGreg Roach return array_merge( 132ade503dfSGreg Roach $this->individualBoxMenuCharts($individual), 133ade503dfSGreg Roach $this->individualBoxMenuFamilyLinks($individual) 134ade503dfSGreg Roach ); 135ade503dfSGreg Roach } 136ade503dfSGreg Roach 137ade503dfSGreg Roach /** 138ade503dfSGreg Roach * Chart links, to show in chart boxes; 139ade503dfSGreg Roach * 140ade503dfSGreg Roach * @param Individual $individual 141ade503dfSGreg Roach * 142ade503dfSGreg Roach * @return Menu[] 143ade503dfSGreg Roach */ 144ade503dfSGreg Roach public function individualBoxMenuCharts(Individual $individual): array 145ade503dfSGreg Roach { 146ade503dfSGreg Roach $menus = []; 147f39638cfSGreg Roach foreach (app(ModuleService::class)->findByComponent(ModuleChartInterface::class, $individual->tree(), Auth::user()) as $chart) { 148ade503dfSGreg Roach $menu = $chart->chartBoxMenu($individual); 149ade503dfSGreg Roach if ($menu) { 150ade503dfSGreg Roach $menus[] = $menu; 151ade503dfSGreg Roach } 152ade503dfSGreg Roach } 153ade503dfSGreg Roach 1540b93976aSGreg Roach usort($menus, static function (Menu $x, Menu $y): int { 155*37646143SGreg Roach return I18N::comparator()($x->getLabel(), $y->getLabel()); 156ade503dfSGreg Roach }); 157ade503dfSGreg Roach 158ade503dfSGreg Roach return $menus; 159ade503dfSGreg Roach } 160ade503dfSGreg Roach 161ade503dfSGreg Roach /** 162ade503dfSGreg Roach * Family links, to show in chart boxes. 163ade503dfSGreg Roach * 164ade503dfSGreg Roach * @param Individual $individual 165ade503dfSGreg Roach * 166ade503dfSGreg Roach * @return Menu[] 167ade503dfSGreg Roach */ 168ade503dfSGreg Roach public function individualBoxMenuFamilyLinks(Individual $individual): array 169ade503dfSGreg Roach { 170ade503dfSGreg Roach $menus = []; 171ade503dfSGreg Roach 17239ca88baSGreg Roach foreach ($individual->spouseFamilies() as $family) { 173ade503dfSGreg Roach $menus[] = new Menu('<strong>' . I18N::translate('Family with spouse') . '</strong>', $family->url()); 17439ca88baSGreg Roach $spouse = $family->spouse($individual); 175ade503dfSGreg Roach if ($spouse && $spouse->canShowName()) { 17639ca88baSGreg Roach $menus[] = new Menu($spouse->fullName(), $spouse->url()); 177ade503dfSGreg Roach } 17839ca88baSGreg Roach foreach ($family->children() as $child) { 179ade503dfSGreg Roach if ($child->canShowName()) { 18039ca88baSGreg Roach $menus[] = new Menu($child->fullName(), $child->url()); 181ade503dfSGreg Roach } 182ade503dfSGreg Roach } 183ade503dfSGreg Roach } 184ade503dfSGreg Roach 185ade503dfSGreg Roach return $menus; 186ade503dfSGreg Roach } 187ade503dfSGreg Roach 188ade503dfSGreg Roach /** 189f567c3d8SGreg Roach * Generate a menu item to change the blocks on the current tree/user page. 190ade503dfSGreg Roach * 1910c8c69d4SGreg Roach * @param Tree $tree 1920c8c69d4SGreg Roach * 193ade503dfSGreg Roach * @return Menu|null 194ade503dfSGreg Roach */ 195e364afe4SGreg Roach public function menuChangeBlocks(Tree $tree): ?Menu 196ade503dfSGreg Roach { 197eb235819SGreg Roach /** @var ServerRequestInterface $request */ 1986ccdf4f0SGreg Roach $request = app(ServerRequestInterface::class); 199e6bcfa02SGreg Roach 2000d7461faSGreg Roach $route = $request->getAttribute('route'); 201de2aa325SGreg Roach assert($route instanceof Route); 202eb235819SGreg Roach 203de2aa325SGreg Roach if (Auth::check() && $route->name === UserPage::class) { 2048e0e1b25SGreg Roach return new Menu(I18N::translate('Customize this page'), route(UserPageEdit::class, ['tree' => $tree->name()]), 'menu-change-blocks'); 205ade503dfSGreg Roach } 206ade503dfSGreg Roach 207de2aa325SGreg Roach if (Auth::isManager($tree) && $route->name === TreePage::class) { 2088e0e1b25SGreg Roach return new Menu(I18N::translate('Customize this page'), route(TreePageEdit::class, ['tree' => $tree->name()]), 'menu-change-blocks'); 209ade503dfSGreg Roach } 210ade503dfSGreg Roach 211ade503dfSGreg Roach return null; 212ade503dfSGreg Roach } 213ade503dfSGreg Roach 214ade503dfSGreg Roach /** 215ade503dfSGreg Roach * Generate a menu item for the control panel. 216ade503dfSGreg Roach * 2170c8c69d4SGreg Roach * @param Tree $tree 2180c8c69d4SGreg Roach * 219ade503dfSGreg Roach * @return Menu|null 220ade503dfSGreg Roach */ 221e364afe4SGreg Roach public function menuControlPanel(Tree $tree): ?Menu 222ade503dfSGreg Roach { 223ade503dfSGreg Roach if (Auth::isAdmin()) { 2240c0910bfSGreg Roach return new Menu(I18N::translate('Control panel'), route(ControlPanel::class), 'menu-admin'); 225ade503dfSGreg Roach } 226ade503dfSGreg Roach 2270c8c69d4SGreg Roach if (Auth::isManager($tree)) { 2286fd01894SGreg Roach return new Menu(I18N::translate('Control panel'), route(ManageTrees::class, ['tree' => $tree->name()]), 'menu-admin'); 229ade503dfSGreg Roach } 230ade503dfSGreg Roach 231ade503dfSGreg Roach return null; 232ade503dfSGreg Roach } 233ade503dfSGreg Roach 234ade503dfSGreg Roach /** 235ade503dfSGreg Roach * A menu to show a list of available languages. 236ade503dfSGreg Roach * 237ade503dfSGreg Roach * @return Menu|null 238ade503dfSGreg Roach */ 239e364afe4SGreg Roach public function menuLanguages(): ?Menu 240ade503dfSGreg Roach { 241ade503dfSGreg Roach $menu = new Menu(I18N::translate('Language'), '#', 'menu-language'); 242ade503dfSGreg Roach 24390a2f718SGreg Roach foreach (I18N::activeLocales() as $active_locale) { 24490a2f718SGreg Roach $language_tag = $active_locale->languageTag(); 24565cf5706SGreg Roach $class = 'menu-language-' . $language_tag . (I18N::languageTag() === $language_tag ? ' active' : ''); 24690a2f718SGreg Roach $menu->addSubmenu(new Menu($active_locale->endonym(), '#', $class, [ 2477adfb8e5SGreg Roach 'data-post-url' => route(SelectLanguage::class, ['language' => $language_tag]), 248ade503dfSGreg Roach ])); 249ade503dfSGreg Roach } 250ade503dfSGreg Roach 251ade503dfSGreg Roach if (count($menu->getSubmenus()) > 1) { 252ade503dfSGreg Roach return $menu; 253ade503dfSGreg Roach } 254ade503dfSGreg Roach 255ade503dfSGreg Roach return null; 256ade503dfSGreg Roach } 257ade503dfSGreg Roach 258ade503dfSGreg Roach /** 259ade503dfSGreg Roach * A login menu option (or null if we are already logged in). 260ade503dfSGreg Roach * 261ade503dfSGreg Roach * @return Menu|null 262ade503dfSGreg Roach */ 263e364afe4SGreg Roach public function menuLogin(): ?Menu 264ade503dfSGreg Roach { 265ade503dfSGreg Roach if (Auth::check()) { 266ade503dfSGreg Roach return null; 267ade503dfSGreg Roach } 268ade503dfSGreg Roach 26986661454SGreg Roach $request = app(ServerRequestInterface::class); 27086661454SGreg Roach 271ade503dfSGreg Roach // Return to this page after login... 272b6c0b825SGreg Roach $redirect = $request->getQueryParams()['url'] ?? (string) $request->getUri(); 273ade503dfSGreg Roach 274b45ccc4fSGreg Roach $tree = $request->getAttribute('tree'); 275de2aa325SGreg Roach $route = $request->getAttribute('route'); 276de2aa325SGreg Roach assert($route instanceof Route); 277b45ccc4fSGreg Roach 278ade503dfSGreg Roach // ...but switch from the tree-page to the user-page 279de2aa325SGreg Roach if ($route->name === TreePage::class) { 2808e0e1b25SGreg Roach $redirect = route(UserPage::class, ['tree' => $tree instanceof Tree ? $tree->name() : null]); 28191c514e5SGreg Roach } 282ade503dfSGreg Roach 28386661454SGreg Roach // Stay on the same tree page 28491c514e5SGreg Roach $url = route(LoginPage::class, ['tree' => $tree instanceof Tree ? $tree->name() : null, 'url' => $redirect]); 28586661454SGreg Roach 28686661454SGreg Roach return new Menu(I18N::translate('Sign in'), $url, 'menu-login', ['rel' => 'nofollow']); 287ade503dfSGreg Roach } 288ade503dfSGreg Roach 289ade503dfSGreg Roach /** 290ade503dfSGreg Roach * A logout menu option (or null if we are already logged out). 291ade503dfSGreg Roach * 292ade503dfSGreg Roach * @return Menu|null 293ade503dfSGreg Roach */ 294e364afe4SGreg Roach public function menuLogout(): ?Menu 295ade503dfSGreg Roach { 296ade503dfSGreg Roach if (Auth::check()) { 2979b541e4aSGreg Roach $parameters = [ 2989b541e4aSGreg Roach 'data-post-url' => route(Logout::class), 299ea101122SGreg Roach 'data-reload-url' => route(HomePage::class) 3009b541e4aSGreg Roach ]; 3019b541e4aSGreg Roach 3029b541e4aSGreg Roach return new Menu(I18N::translate('Sign out'), '#', 'menu-logout', $parameters); 303ade503dfSGreg Roach } 304ade503dfSGreg Roach 305ade503dfSGreg Roach return null; 306ade503dfSGreg Roach } 307ade503dfSGreg Roach 308ade503dfSGreg Roach /** 309ade503dfSGreg Roach * A link to allow users to edit their account settings. 310ade503dfSGreg Roach * 31165aec466SGreg Roach * @param Tree|null $tree 312a49d0e3fSGreg Roach * 313a49d0e3fSGreg Roach * @return Menu 314ade503dfSGreg Roach */ 315a49d0e3fSGreg Roach public function menuMyAccount(?Tree $tree): Menu 316ade503dfSGreg Roach { 317a49d0e3fSGreg Roach $url = route(AccountEdit::class, ['tree' => $tree instanceof Tree ? $tree->name() : null]); 318ade503dfSGreg Roach 319df314983SGreg Roach return new Menu(I18N::translate('My account'), $url, 'menu-myaccount'); 320ade503dfSGreg Roach } 321ade503dfSGreg Roach 322ade503dfSGreg Roach /** 323ade503dfSGreg Roach * A link to the user's individual record (individual.php). 324ade503dfSGreg Roach * 3250c8c69d4SGreg Roach * @param Tree $tree 3260c8c69d4SGreg Roach * 327ade503dfSGreg Roach * @return Menu|null 328ade503dfSGreg Roach */ 329e364afe4SGreg Roach public function menuMyIndividualRecord(Tree $tree): ?Menu 330ade503dfSGreg Roach { 3311fe542e9SGreg Roach $record = Registry::individualFactory()->make($tree->getUserPreference(Auth::user(), UserInterface::PREF_TREE_ACCOUNT_XREF), $tree); 332ade503dfSGreg Roach 333ade503dfSGreg Roach if ($record) { 334ade503dfSGreg Roach return new Menu(I18N::translate('My individual record'), $record->url(), 'menu-myrecord'); 335ade503dfSGreg Roach } 336ade503dfSGreg Roach 337ade503dfSGreg Roach return null; 338ade503dfSGreg Roach } 339ade503dfSGreg Roach 340ade503dfSGreg Roach /** 341ade503dfSGreg Roach * A link to the user's personal home page. 342ade503dfSGreg Roach * 3430c8c69d4SGreg Roach * @param Tree $tree 3440c8c69d4SGreg Roach * 345ade503dfSGreg Roach * @return Menu 346ade503dfSGreg Roach */ 3470c8c69d4SGreg Roach public function menuMyPage(Tree $tree): Menu 348ade503dfSGreg Roach { 3498e0e1b25SGreg Roach return new Menu(I18N::translate('My page'), route(UserPage::class, ['tree' => $tree->name()]), 'menu-mypage'); 350ade503dfSGreg Roach } 351ade503dfSGreg Roach 352ade503dfSGreg Roach /** 353ade503dfSGreg Roach * A menu for the user's personal pages. 354ade503dfSGreg Roach * 3550c8c69d4SGreg Roach * @param Tree|null $tree 3560c8c69d4SGreg Roach * 357ade503dfSGreg Roach * @return Menu|null 358ade503dfSGreg Roach */ 359e364afe4SGreg Roach public function menuMyPages(?Tree $tree): ?Menu 360ade503dfSGreg Roach { 361047fd705SGreg Roach if (Auth::check()) { 362a49d0e3fSGreg Roach if ($tree instanceof Tree) { 363ade503dfSGreg Roach return new Menu(I18N::translate('My pages'), '#', 'menu-mymenu', [], array_filter([ 3640c8c69d4SGreg Roach $this->menuMyPage($tree), 3650c8c69d4SGreg Roach $this->menuMyIndividualRecord($tree), 3660c8c69d4SGreg Roach $this->menuMyPedigree($tree), 367a49d0e3fSGreg Roach $this->menuMyAccount($tree), 3680c8c69d4SGreg Roach $this->menuControlPanel($tree), 3690c8c69d4SGreg Roach $this->menuChangeBlocks($tree), 370ade503dfSGreg Roach ])); 371ade503dfSGreg Roach } 372ade503dfSGreg Roach 373a49d0e3fSGreg Roach return $this->menuMyAccount($tree); 374a49d0e3fSGreg Roach } 375a49d0e3fSGreg Roach 376ade503dfSGreg Roach return null; 377ade503dfSGreg Roach } 378ade503dfSGreg Roach 379ade503dfSGreg Roach /** 380ade503dfSGreg Roach * A link to the user's individual record. 381ade503dfSGreg Roach * 3820c8c69d4SGreg Roach * @param Tree $tree 3830c8c69d4SGreg Roach * 384ade503dfSGreg Roach * @return Menu|null 385ade503dfSGreg Roach */ 386e364afe4SGreg Roach public function menuMyPedigree(Tree $tree): ?Menu 387ade503dfSGreg Roach { 3881fe542e9SGreg Roach $gedcomid = $tree->getUserPreference(Auth::user(), UserInterface::PREF_TREE_ACCOUNT_XREF); 389ade503dfSGreg Roach 3900c8c69d4SGreg Roach $pedigree_chart = app(ModuleService::class)->findByComponent(ModuleChartInterface::class, $tree, Auth::user()) 3910b5fd0a6SGreg Roach ->filter(static function (ModuleInterface $module): bool { 392ade503dfSGreg Roach return $module instanceof PedigreeChartModule; 393ade503dfSGreg Roach }); 394ade503dfSGreg Roach 395ade503dfSGreg Roach if ($gedcomid !== '' && $pedigree_chart instanceof PedigreeChartModule) { 396ade503dfSGreg Roach return new Menu( 397ade503dfSGreg Roach I18N::translate('My pedigree'), 398ade503dfSGreg Roach route('pedigree', [ 399ade503dfSGreg Roach 'xref' => $gedcomid, 4009022ab66SGreg Roach 'tree' => $tree->name(), 401ade503dfSGreg Roach ]), 402ade503dfSGreg Roach 'menu-mypedigree' 403ade503dfSGreg Roach ); 404ade503dfSGreg Roach } 405ade503dfSGreg Roach 406ade503dfSGreg Roach return null; 407ade503dfSGreg Roach } 408ade503dfSGreg Roach 409ade503dfSGreg Roach /** 410ade503dfSGreg Roach * Create a pending changes menu. 411ade503dfSGreg Roach * 4120c8c69d4SGreg Roach * @param Tree|null $tree 4130c8c69d4SGreg Roach * 414ade503dfSGreg Roach * @return Menu|null 415ade503dfSGreg Roach */ 416e364afe4SGreg Roach public function menuPendingChanges(?Tree $tree): ?Menu 417ade503dfSGreg Roach { 4180c8c69d4SGreg Roach if ($tree instanceof Tree && $tree->hasPendingEdit() && Auth::isModerator($tree)) { 41922e73debSGreg Roach $url = route(PendingChanges::class, [ 4209022ab66SGreg Roach 'tree' => $tree->name(), 421cf8c0692SGreg Roach 'url' => (string) app(ServerRequestInterface::class)->getUri(), 422ade503dfSGreg Roach ]); 423ade503dfSGreg Roach 424ade503dfSGreg Roach return new Menu(I18N::translate('Pending changes'), $url, 'menu-pending'); 425ade503dfSGreg Roach } 426ade503dfSGreg Roach 427ade503dfSGreg Roach return null; 428ade503dfSGreg Roach } 429ade503dfSGreg Roach 430ade503dfSGreg Roach /** 431ade503dfSGreg Roach * Themes menu. 432ade503dfSGreg Roach * 433ade503dfSGreg Roach * @return Menu|null 434ade503dfSGreg Roach */ 435e364afe4SGreg Roach public function menuThemes(): ?Menu 436ade503dfSGreg Roach { 437b668782fSGreg Roach $themes = app(ModuleService::class)->findByInterface(ModuleThemeInterface::class, false, true); 438df8baf00SGreg Roach 439cab242e7SGreg Roach $current_theme = app(ModuleThemeInterface::class); 4408136679eSGreg Roach 4418136679eSGreg Roach if ($themes->count() > 1) { 4420b5fd0a6SGreg Roach $submenus = $themes->map(static function (ModuleThemeInterface $theme) use ($current_theme): Menu { 4438136679eSGreg Roach $active = $theme->name() === $current_theme->name(); 4448136679eSGreg Roach $class = 'menu-theme-' . $theme->name() . ($active ? ' active' : ''); 4458136679eSGreg Roach 4468136679eSGreg Roach return new Menu($theme->title(), '#', $class, [ 4477adfb8e5SGreg Roach 'data-post-url' => route(SelectTheme::class, ['theme' => $theme->name()]), 448ade503dfSGreg Roach ]); 449ade503dfSGreg Roach }); 450ade503dfSGreg Roach 4518136679eSGreg Roach return new Menu(I18N::translate('Theme'), '#', 'menu-theme', [], $submenus->all()); 452ade503dfSGreg Roach } 453ade503dfSGreg Roach 454ade503dfSGreg Roach return null; 455ade503dfSGreg Roach } 456ade503dfSGreg Roach 457ade503dfSGreg Roach /** 458fceda430SGreg Roach * Miscellaneous dimensions, fonts, styles, etc. 459ade503dfSGreg Roach * 460ade503dfSGreg Roach * @param string $parameter_name 461ade503dfSGreg Roach * 462ade503dfSGreg Roach * @return string|int|float 463ade503dfSGreg Roach */ 464ade503dfSGreg Roach public function parameter($parameter_name) 465ade503dfSGreg Roach { 466ade503dfSGreg Roach return ''; 467ade503dfSGreg Roach } 468ade503dfSGreg Roach 469ade503dfSGreg Roach /** 470ade503dfSGreg Roach * Generate a list of items for the main menu. 471ade503dfSGreg Roach * 4720c8c69d4SGreg Roach * @param Tree|null $tree 4730c8c69d4SGreg Roach * 474ade503dfSGreg Roach * @return Menu[] 475ade503dfSGreg Roach */ 4760c8c69d4SGreg Roach public function genealogyMenu(?Tree $tree): array 477ade503dfSGreg Roach { 4780c8c69d4SGreg Roach if ($tree === null) { 4790c8c69d4SGreg Roach return []; 4800c8c69d4SGreg Roach } 4810c8c69d4SGreg Roach 4820c8c69d4SGreg Roach return app(ModuleService::class)->findByComponent(ModuleMenuInterface::class, $tree, Auth::user()) 4830b5fd0a6SGreg Roach ->map(static function (ModuleMenuInterface $menu) use ($tree): ?Menu { 4840c8c69d4SGreg Roach return $menu->getMenu($tree); 485ade503dfSGreg Roach }) 486ade503dfSGreg Roach ->filter() 487ade503dfSGreg Roach ->all(); 488ade503dfSGreg Roach } 489ade503dfSGreg Roach 490ade503dfSGreg Roach /** 4910c8c69d4SGreg Roach * Create the genealogy menu. 492ade503dfSGreg Roach * 493ade503dfSGreg Roach * @param Menu[] $menus 494ade503dfSGreg Roach * 495ade503dfSGreg Roach * @return string 496ade503dfSGreg Roach */ 4970c8c69d4SGreg Roach public function genealogyMenuContent(array $menus): string 498ade503dfSGreg Roach { 4990b5fd0a6SGreg Roach return implode('', array_map(static function (Menu $menu): string { 500f78837dcSGreg Roach return view('components/menu-item', ['menu' => $menu]); 501ade503dfSGreg Roach }, $menus)); 502ade503dfSGreg Roach } 503ade503dfSGreg Roach 504ade503dfSGreg Roach /** 505ade503dfSGreg Roach * Generate a list of items for the user menu. 506ade503dfSGreg Roach * 5070c8c69d4SGreg Roach * @param Tree|null $tree 5080c8c69d4SGreg Roach * 509ade503dfSGreg Roach * @return Menu[] 510ade503dfSGreg Roach */ 5110c8c69d4SGreg Roach public function userMenu(?Tree $tree): array 512ade503dfSGreg Roach { 513ade503dfSGreg Roach return array_filter([ 5140c8c69d4SGreg Roach $this->menuPendingChanges($tree), 5150c8c69d4SGreg Roach $this->menuMyPages($tree), 516ade503dfSGreg Roach $this->menuThemes(), 517ade503dfSGreg Roach $this->menuLanguages(), 518ade503dfSGreg Roach $this->menuLogin(), 519ade503dfSGreg Roach $this->menuLogout(), 520ade503dfSGreg Roach ]); 521ade503dfSGreg Roach } 522ade503dfSGreg Roach 523ade503dfSGreg Roach /** 524ade503dfSGreg Roach * A list of CSS files to include for this page. 525ade503dfSGreg Roach * 52624f2a3afSGreg Roach * @return array<string> 527ade503dfSGreg Roach */ 528ade503dfSGreg Roach public function stylesheets(): array 529ade503dfSGreg Roach { 530ade503dfSGreg Roach return []; 531ade503dfSGreg Roach } 53249a243cbSGreg Roach} 533