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 22de2aa325SGreg Roachuse Aura\Router\Route; 23ade503dfSGreg Roachuse Fisharebest\Webtrees\Auth; 24ade503dfSGreg Roachuse Fisharebest\Webtrees\Fact; 25ade503dfSGreg Roachuse Fisharebest\Webtrees\Gedcom; 26a49d0e3fSGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\AccountEdit; 270c0910bfSGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\ControlPanel; 2856f9a9c1SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\LoginPage; 2956f9a9c1SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\Logout; 3022e73debSGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\PendingChanges; 317adfb8e5SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\SelectLanguage; 327adfb8e5SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\SelectTheme; 338e0e1b25SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\TreePage; 348e0e1b25SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\TreePageEdit; 358e0e1b25SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\UserPage; 368e0e1b25SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\UserPageEdit; 37ade503dfSGreg Roachuse Fisharebest\Webtrees\I18N; 38ade503dfSGreg Roachuse Fisharebest\Webtrees\Individual; 39ade503dfSGreg Roachuse Fisharebest\Webtrees\Menu; 404ca7e03cSGreg Roachuse Fisharebest\Webtrees\Services\ModuleService; 41ade503dfSGreg Roachuse Fisharebest\Webtrees\Tree; 427c4add84SGreg Roachuse Fisharebest\Webtrees\User; 436ccdf4f0SGreg Roachuse Psr\Http\Message\ServerRequestInterface; 443976b470SGreg Roach 456ccdf4f0SGreg Roachuse function app; 46de2aa325SGreg Roachuse function assert; 477adfb8e5SGreg Roachuse function route; 48f78837dcSGreg Roachuse function view; 49ade503dfSGreg Roach 5049a243cbSGreg Roach/** 5149a243cbSGreg Roach * Trait ModuleThemeTrait - default implementation of ModuleThemeInterface 5249a243cbSGreg Roach */ 5349a243cbSGreg Roachtrait ModuleThemeTrait 5449a243cbSGreg Roach{ 55ade503dfSGreg Roach /** 56962ead51SGreg Roach * @return string 57962ead51SGreg Roach */ 58962ead51SGreg Roach abstract public function name(): string; 59962ead51SGreg Roach 60962ead51SGreg Roach /** 61962ead51SGreg Roach * @return string 62962ead51SGreg Roach */ 63962ead51SGreg Roach abstract public function title(): string; 64962ead51SGreg Roach 65962ead51SGreg Roach /** 663d8b2a8eSGreg Roach * A sentence describing what this module does. 673d8b2a8eSGreg Roach * 683d8b2a8eSGreg Roach * @return string 693d8b2a8eSGreg Roach */ 703d8b2a8eSGreg Roach public function description(): string 713d8b2a8eSGreg Roach { 723d8b2a8eSGreg Roach return I18N::translate('Theme') . ' — ' . $this->title(); 733d8b2a8eSGreg Roach } 743d8b2a8eSGreg Roach 753d8b2a8eSGreg Roach /** 76ade503dfSGreg Roach * Generate the facts, for display in charts. 77ade503dfSGreg Roach * 78ade503dfSGreg Roach * @param Individual $individual 79ade503dfSGreg Roach * 80ade503dfSGreg Roach * @return string 81ade503dfSGreg Roach */ 82ade503dfSGreg Roach public function individualBoxFacts(Individual $individual): string 83ade503dfSGreg Roach { 84ade503dfSGreg Roach $html = ''; 85ade503dfSGreg Roach 86ade503dfSGreg Roach $opt_tags = preg_split('/\W/', $individual->tree()->getPreference('CHART_BOX_TAGS'), 0, PREG_SPLIT_NO_EMPTY); 87ade503dfSGreg Roach // Show BIRT or equivalent event 88ade503dfSGreg Roach foreach (Gedcom::BIRTH_EVENTS as $birttag) { 8922d65e5aSGreg Roach if (!in_array($birttag, $opt_tags, true)) { 90820b62dfSGreg Roach $event = $individual->facts([$birttag])->first(); 91820b62dfSGreg Roach if ($event instanceof Fact) { 92ade503dfSGreg Roach $html .= $event->summary(); 93ade503dfSGreg Roach break; 94ade503dfSGreg Roach } 95ade503dfSGreg Roach } 96ade503dfSGreg Roach } 97ade503dfSGreg Roach // Show optional events (before death) 98ade503dfSGreg Roach foreach ($opt_tags as $key => $tag) { 9922d65e5aSGreg Roach if (!in_array($tag, Gedcom::DEATH_EVENTS, true)) { 100820b62dfSGreg Roach $event = $individual->facts([$tag])->first(); 101820b62dfSGreg Roach if ($event instanceof Fact) { 102ade503dfSGreg Roach $html .= $event->summary(); 103ade503dfSGreg Roach unset($opt_tags[$key]); 104ade503dfSGreg Roach } 105ade503dfSGreg Roach } 106ade503dfSGreg Roach } 107ade503dfSGreg Roach // Show DEAT or equivalent event 108ade503dfSGreg Roach foreach (Gedcom::DEATH_EVENTS as $deattag) { 109820b62dfSGreg Roach $event = $individual->facts([$deattag])->first(); 110820b62dfSGreg Roach if ($event instanceof Fact) { 111ade503dfSGreg Roach $html .= $event->summary(); 11222d65e5aSGreg Roach if (in_array($deattag, $opt_tags, true)) { 11322d65e5aSGreg Roach unset($opt_tags[array_search($deattag, $opt_tags, true)]); 114ade503dfSGreg Roach } 115ade503dfSGreg Roach break; 116ade503dfSGreg Roach } 117ade503dfSGreg Roach } 118ade503dfSGreg Roach // Show remaining optional events (after death) 119ade503dfSGreg Roach foreach ($opt_tags as $tag) { 120820b62dfSGreg Roach $event = $individual->facts([$tag])->first(); 121820b62dfSGreg Roach if ($event instanceof Fact) { 122ade503dfSGreg Roach $html .= $event->summary(); 123ade503dfSGreg Roach } 124ade503dfSGreg Roach } 125ade503dfSGreg Roach 126ade503dfSGreg Roach return $html; 127ade503dfSGreg Roach } 128ade503dfSGreg Roach 129ade503dfSGreg Roach /** 130ade503dfSGreg Roach * Links, to show in chart boxes; 131ade503dfSGreg Roach * 132ade503dfSGreg Roach * @param Individual $individual 133ade503dfSGreg Roach * 134ade503dfSGreg Roach * @return Menu[] 135ade503dfSGreg Roach */ 136ade503dfSGreg Roach public function individualBoxMenu(Individual $individual): array 137ade503dfSGreg Roach { 138aa6311c7SGreg Roach return array_merge( 139ade503dfSGreg Roach $this->individualBoxMenuCharts($individual), 140ade503dfSGreg Roach $this->individualBoxMenuFamilyLinks($individual) 141ade503dfSGreg Roach ); 142ade503dfSGreg Roach } 143ade503dfSGreg Roach 144ade503dfSGreg Roach /** 145ade503dfSGreg Roach * Chart links, to show in chart boxes; 146ade503dfSGreg Roach * 147ade503dfSGreg Roach * @param Individual $individual 148ade503dfSGreg Roach * 149ade503dfSGreg Roach * @return Menu[] 150ade503dfSGreg Roach */ 151ade503dfSGreg Roach public function individualBoxMenuCharts(Individual $individual): array 152ade503dfSGreg Roach { 153ade503dfSGreg Roach $menus = []; 154f39638cfSGreg Roach foreach (app(ModuleService::class)->findByComponent(ModuleChartInterface::class, $individual->tree(), Auth::user()) as $chart) { 155ade503dfSGreg Roach $menu = $chart->chartBoxMenu($individual); 156ade503dfSGreg Roach if ($menu) { 157ade503dfSGreg Roach $menus[] = $menu; 158ade503dfSGreg Roach } 159ade503dfSGreg Roach } 160ade503dfSGreg Roach 1610b93976aSGreg Roach usort($menus, static function (Menu $x, Menu $y): int { 162ade503dfSGreg Roach return I18N::strcasecmp($x->getLabel(), $y->getLabel()); 163ade503dfSGreg Roach }); 164ade503dfSGreg Roach 165ade503dfSGreg Roach return $menus; 166ade503dfSGreg Roach } 167ade503dfSGreg Roach 168ade503dfSGreg Roach /** 169ade503dfSGreg Roach * Family 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 individualBoxMenuFamilyLinks(Individual $individual): array 176ade503dfSGreg Roach { 177ade503dfSGreg Roach $menus = []; 178ade503dfSGreg Roach 17939ca88baSGreg Roach foreach ($individual->spouseFamilies() as $family) { 180ade503dfSGreg Roach $menus[] = new Menu('<strong>' . I18N::translate('Family with spouse') . '</strong>', $family->url()); 18139ca88baSGreg Roach $spouse = $family->spouse($individual); 182ade503dfSGreg Roach if ($spouse && $spouse->canShowName()) { 18339ca88baSGreg Roach $menus[] = new Menu($spouse->fullName(), $spouse->url()); 184ade503dfSGreg Roach } 18539ca88baSGreg Roach foreach ($family->children() as $child) { 186ade503dfSGreg Roach if ($child->canShowName()) { 18739ca88baSGreg Roach $menus[] = new Menu($child->fullName(), $child->url()); 188ade503dfSGreg Roach } 189ade503dfSGreg Roach } 190ade503dfSGreg Roach } 191ade503dfSGreg Roach 192ade503dfSGreg Roach return $menus; 193ade503dfSGreg Roach } 194ade503dfSGreg Roach 195ade503dfSGreg Roach /** 196f567c3d8SGreg Roach * Generate a menu item to change the blocks on the current tree/user page. 197ade503dfSGreg Roach * 1980c8c69d4SGreg Roach * @param Tree $tree 1990c8c69d4SGreg Roach * 200ade503dfSGreg Roach * @return Menu|null 201ade503dfSGreg Roach */ 202e364afe4SGreg Roach public function menuChangeBlocks(Tree $tree): ?Menu 203ade503dfSGreg Roach { 204eb235819SGreg Roach /** @var ServerRequestInterface $request */ 2056ccdf4f0SGreg Roach $request = app(ServerRequestInterface::class); 206e6bcfa02SGreg Roach 2070d7461faSGreg Roach $route = $request->getAttribute('route'); 208de2aa325SGreg Roach assert($route instanceof Route); 209eb235819SGreg Roach 210de2aa325SGreg Roach if (Auth::check() && $route->name === UserPage::class) { 2118e0e1b25SGreg Roach return new Menu(I18N::translate('Customize this page'), route(UserPageEdit::class, ['tree' => $tree->name()]), 'menu-change-blocks'); 212ade503dfSGreg Roach } 213ade503dfSGreg Roach 214de2aa325SGreg Roach if (Auth::isManager($tree) && $route->name === TreePage::class) { 2158e0e1b25SGreg Roach return new Menu(I18N::translate('Customize this page'), route(TreePageEdit::class, ['tree' => $tree->name()]), 'menu-change-blocks'); 216ade503dfSGreg Roach } 217ade503dfSGreg Roach 218ade503dfSGreg Roach return null; 219ade503dfSGreg Roach } 220ade503dfSGreg Roach 221ade503dfSGreg Roach /** 222ade503dfSGreg Roach * Generate a menu item for the control panel. 223ade503dfSGreg Roach * 2240c8c69d4SGreg Roach * @param Tree $tree 2250c8c69d4SGreg Roach * 226ade503dfSGreg Roach * @return Menu|null 227ade503dfSGreg Roach */ 228e364afe4SGreg Roach public function menuControlPanel(Tree $tree): ?Menu 229ade503dfSGreg Roach { 230ade503dfSGreg Roach if (Auth::isAdmin()) { 2310c0910bfSGreg Roach return new Menu(I18N::translate('Control panel'), route(ControlPanel::class), 'menu-admin'); 232ade503dfSGreg Roach } 233ade503dfSGreg Roach 2340c8c69d4SGreg Roach if (Auth::isManager($tree)) { 2356f414251SGreg Roach return new Menu(I18N::translate('Control panel'), route('manage-trees', ['tree' => $tree->name()]), 'menu-admin'); 236ade503dfSGreg Roach } 237ade503dfSGreg Roach 238ade503dfSGreg Roach return null; 239ade503dfSGreg Roach } 240ade503dfSGreg Roach 241ade503dfSGreg Roach /** 242ade503dfSGreg Roach * A menu to show a list of available languages. 243ade503dfSGreg Roach * 244ade503dfSGreg Roach * @return Menu|null 245ade503dfSGreg Roach */ 246e364afe4SGreg Roach public function menuLanguages(): ?Menu 247ade503dfSGreg Roach { 248ade503dfSGreg Roach $menu = new Menu(I18N::translate('Language'), '#', 'menu-language'); 249ade503dfSGreg Roach 25090a2f718SGreg Roach foreach (I18N::activeLocales() as $active_locale) { 25190a2f718SGreg Roach $language_tag = $active_locale->languageTag(); 25265cf5706SGreg Roach $class = 'menu-language-' . $language_tag . (I18N::languageTag() === $language_tag ? ' active' : ''); 25390a2f718SGreg Roach $menu->addSubmenu(new Menu($active_locale->endonym(), '#', $class, [ 2547adfb8e5SGreg Roach 'data-post-url' => route(SelectLanguage::class, ['language' => $language_tag]), 255ade503dfSGreg Roach ])); 256ade503dfSGreg Roach } 257ade503dfSGreg Roach 258ade503dfSGreg Roach if (count($menu->getSubmenus()) > 1) { 259ade503dfSGreg Roach return $menu; 260ade503dfSGreg Roach } 261ade503dfSGreg Roach 262ade503dfSGreg Roach return null; 263ade503dfSGreg Roach } 264ade503dfSGreg Roach 265ade503dfSGreg Roach /** 266ade503dfSGreg Roach * A login menu option (or null if we are already logged in). 267ade503dfSGreg Roach * 268ade503dfSGreg Roach * @return Menu|null 269ade503dfSGreg Roach */ 270e364afe4SGreg Roach public function menuLogin(): ?Menu 271ade503dfSGreg Roach { 272ade503dfSGreg Roach if (Auth::check()) { 273ade503dfSGreg Roach return null; 274ade503dfSGreg Roach } 275ade503dfSGreg Roach 27686661454SGreg Roach $request = app(ServerRequestInterface::class); 27786661454SGreg Roach 278ade503dfSGreg Roach // Return to this page after login... 279b6c0b825SGreg Roach $redirect = $request->getQueryParams()['url'] ?? (string) $request->getUri(); 280ade503dfSGreg Roach 281b45ccc4fSGreg Roach $tree = $request->getAttribute('tree'); 282de2aa325SGreg Roach $route = $request->getAttribute('route'); 283de2aa325SGreg Roach assert($route instanceof Route); 284b45ccc4fSGreg Roach 285ade503dfSGreg Roach // ...but switch from the tree-page to the user-page 286de2aa325SGreg Roach if ($route->name === TreePage::class) { 2878e0e1b25SGreg Roach $redirect = route(UserPage::class, ['tree' => $tree instanceof Tree ? $tree->name() : null]); 28891c514e5SGreg Roach } 289ade503dfSGreg Roach 29086661454SGreg Roach // Stay on the same tree page 29191c514e5SGreg Roach $url = route(LoginPage::class, ['tree' => $tree instanceof Tree ? $tree->name() : null, 'url' => $redirect]); 29286661454SGreg Roach 29386661454SGreg Roach return new Menu(I18N::translate('Sign in'), $url, 'menu-login', ['rel' => 'nofollow']); 294ade503dfSGreg Roach } 295ade503dfSGreg Roach 296ade503dfSGreg Roach /** 297ade503dfSGreg Roach * A logout menu option (or null if we are already logged out). 298ade503dfSGreg Roach * 299ade503dfSGreg Roach * @return Menu|null 300ade503dfSGreg Roach */ 301e364afe4SGreg Roach public function menuLogout(): ?Menu 302ade503dfSGreg Roach { 303ade503dfSGreg Roach if (Auth::check()) { 3049b541e4aSGreg Roach $parameters = [ 3059b541e4aSGreg Roach 'data-post-url' => route(Logout::class), 3069b541e4aSGreg Roach ]; 3079b541e4aSGreg Roach 3089b541e4aSGreg Roach return new Menu(I18N::translate('Sign out'), '#', 'menu-logout', $parameters); 309ade503dfSGreg Roach } 310ade503dfSGreg Roach 311ade503dfSGreg Roach return null; 312ade503dfSGreg Roach } 313ade503dfSGreg Roach 314ade503dfSGreg Roach /** 315ade503dfSGreg Roach * A link to allow users to edit their account settings. 316ade503dfSGreg Roach * 31765aec466SGreg Roach * @param Tree|null $tree 318a49d0e3fSGreg Roach * 319a49d0e3fSGreg Roach * @return Menu 320ade503dfSGreg Roach */ 321a49d0e3fSGreg Roach public function menuMyAccount(?Tree $tree): Menu 322ade503dfSGreg Roach { 323a49d0e3fSGreg Roach $url = route(AccountEdit::class, ['tree' => $tree instanceof Tree ? $tree->name() : null]); 324ade503dfSGreg Roach 325*df314983SGreg Roach return new Menu(I18N::translate('My account'), $url, 'menu-myaccount'); 326ade503dfSGreg Roach } 327ade503dfSGreg Roach 328ade503dfSGreg Roach /** 329ade503dfSGreg Roach * A link to the user's individual record (individual.php). 330ade503dfSGreg Roach * 3310c8c69d4SGreg Roach * @param Tree $tree 3320c8c69d4SGreg Roach * 333ade503dfSGreg Roach * @return Menu|null 334ade503dfSGreg Roach */ 335e364afe4SGreg Roach public function menuMyIndividualRecord(Tree $tree): ?Menu 336ade503dfSGreg Roach { 3377c4add84SGreg Roach $record = Individual::getInstance($tree->getUserPreference(Auth::user(), User::PREF_TREE_ACCOUNT_XREF), $tree); 338ade503dfSGreg Roach 339ade503dfSGreg Roach if ($record) { 340ade503dfSGreg Roach return new Menu(I18N::translate('My individual record'), $record->url(), 'menu-myrecord'); 341ade503dfSGreg Roach } 342ade503dfSGreg Roach 343ade503dfSGreg Roach return null; 344ade503dfSGreg Roach } 345ade503dfSGreg Roach 346ade503dfSGreg Roach /** 347ade503dfSGreg Roach * A link to the user's personal home page. 348ade503dfSGreg Roach * 3490c8c69d4SGreg Roach * @param Tree $tree 3500c8c69d4SGreg Roach * 351ade503dfSGreg Roach * @return Menu 352ade503dfSGreg Roach */ 3530c8c69d4SGreg Roach public function menuMyPage(Tree $tree): Menu 354ade503dfSGreg Roach { 3558e0e1b25SGreg Roach return new Menu(I18N::translate('My page'), route(UserPage::class, ['tree' => $tree->name()]), 'menu-mypage'); 356ade503dfSGreg Roach } 357ade503dfSGreg Roach 358ade503dfSGreg Roach /** 359ade503dfSGreg Roach * A menu for the user's personal pages. 360ade503dfSGreg Roach * 3610c8c69d4SGreg Roach * @param Tree|null $tree 3620c8c69d4SGreg Roach * 363ade503dfSGreg Roach * @return Menu|null 364ade503dfSGreg Roach */ 365e364afe4SGreg Roach public function menuMyPages(?Tree $tree): ?Menu 366ade503dfSGreg Roach { 367a49d0e3fSGreg Roach if (Auth::id()) { 368a49d0e3fSGreg Roach if ($tree instanceof Tree) { 369ade503dfSGreg Roach return new Menu(I18N::translate('My pages'), '#', 'menu-mymenu', [], array_filter([ 3700c8c69d4SGreg Roach $this->menuMyPage($tree), 3710c8c69d4SGreg Roach $this->menuMyIndividualRecord($tree), 3720c8c69d4SGreg Roach $this->menuMyPedigree($tree), 373a49d0e3fSGreg Roach $this->menuMyAccount($tree), 3740c8c69d4SGreg Roach $this->menuControlPanel($tree), 3750c8c69d4SGreg Roach $this->menuChangeBlocks($tree), 376ade503dfSGreg Roach ])); 377ade503dfSGreg Roach } 378ade503dfSGreg Roach 379a49d0e3fSGreg Roach return $this->menuMyAccount($tree); 380a49d0e3fSGreg Roach } 381a49d0e3fSGreg Roach 382ade503dfSGreg Roach return null; 383ade503dfSGreg Roach } 384ade503dfSGreg Roach 385ade503dfSGreg Roach /** 386ade503dfSGreg Roach * A link to the user's individual record. 387ade503dfSGreg Roach * 3880c8c69d4SGreg Roach * @param Tree $tree 3890c8c69d4SGreg Roach * 390ade503dfSGreg Roach * @return Menu|null 391ade503dfSGreg Roach */ 392e364afe4SGreg Roach public function menuMyPedigree(Tree $tree): ?Menu 393ade503dfSGreg Roach { 3947c4add84SGreg Roach $gedcomid = $tree->getUserPreference(Auth::user(), User::PREF_TREE_ACCOUNT_XREF); 395ade503dfSGreg Roach 3960c8c69d4SGreg Roach $pedigree_chart = app(ModuleService::class)->findByComponent(ModuleChartInterface::class, $tree, Auth::user()) 3970b5fd0a6SGreg Roach ->filter(static function (ModuleInterface $module): bool { 398ade503dfSGreg Roach return $module instanceof PedigreeChartModule; 399ade503dfSGreg Roach }); 400ade503dfSGreg Roach 401ade503dfSGreg Roach if ($gedcomid !== '' && $pedigree_chart instanceof PedigreeChartModule) { 402ade503dfSGreg Roach return new Menu( 403ade503dfSGreg Roach I18N::translate('My pedigree'), 404ade503dfSGreg Roach route('pedigree', [ 405ade503dfSGreg Roach 'xref' => $gedcomid, 4069022ab66SGreg Roach 'tree' => $tree->name(), 407ade503dfSGreg Roach ]), 408ade503dfSGreg Roach 'menu-mypedigree' 409ade503dfSGreg Roach ); 410ade503dfSGreg Roach } 411ade503dfSGreg Roach 412ade503dfSGreg Roach return null; 413ade503dfSGreg Roach } 414ade503dfSGreg Roach 415ade503dfSGreg Roach /** 416ade503dfSGreg Roach * Create a pending changes menu. 417ade503dfSGreg Roach * 4180c8c69d4SGreg Roach * @param Tree|null $tree 4190c8c69d4SGreg Roach * 420ade503dfSGreg Roach * @return Menu|null 421ade503dfSGreg Roach */ 422e364afe4SGreg Roach public function menuPendingChanges(?Tree $tree): ?Menu 423ade503dfSGreg Roach { 4240c8c69d4SGreg Roach if ($tree instanceof Tree && $tree->hasPendingEdit() && Auth::isModerator($tree)) { 42522e73debSGreg Roach $url = route(PendingChanges::class, [ 4269022ab66SGreg Roach 'tree' => $tree->name(), 427cf8c0692SGreg Roach 'url' => (string) app(ServerRequestInterface::class)->getUri(), 428ade503dfSGreg Roach ]); 429ade503dfSGreg Roach 430ade503dfSGreg Roach return new Menu(I18N::translate('Pending changes'), $url, 'menu-pending'); 431ade503dfSGreg Roach } 432ade503dfSGreg Roach 433ade503dfSGreg Roach return null; 434ade503dfSGreg Roach } 435ade503dfSGreg Roach 436ade503dfSGreg Roach /** 437ade503dfSGreg Roach * Themes menu. 438ade503dfSGreg Roach * 439ade503dfSGreg Roach * @return Menu|null 440ade503dfSGreg Roach */ 441e364afe4SGreg Roach public function menuThemes(): ?Menu 442ade503dfSGreg Roach { 443b668782fSGreg Roach $themes = app(ModuleService::class)->findByInterface(ModuleThemeInterface::class, false, true); 444df8baf00SGreg Roach 445cab242e7SGreg Roach $current_theme = app(ModuleThemeInterface::class); 4468136679eSGreg Roach 4478136679eSGreg Roach if ($themes->count() > 1) { 4480b5fd0a6SGreg Roach $submenus = $themes->map(static function (ModuleThemeInterface $theme) use ($current_theme): Menu { 4498136679eSGreg Roach $active = $theme->name() === $current_theme->name(); 4508136679eSGreg Roach $class = 'menu-theme-' . $theme->name() . ($active ? ' active' : ''); 4518136679eSGreg Roach 4528136679eSGreg Roach return new Menu($theme->title(), '#', $class, [ 4537adfb8e5SGreg Roach 'data-post-url' => route(SelectTheme::class, ['theme' => $theme->name()]), 454ade503dfSGreg Roach ]); 455ade503dfSGreg Roach }); 456ade503dfSGreg Roach 4578136679eSGreg Roach return new Menu(I18N::translate('Theme'), '#', 'menu-theme', [], $submenus->all()); 458ade503dfSGreg Roach } 459ade503dfSGreg Roach 460ade503dfSGreg Roach return null; 461ade503dfSGreg Roach } 462ade503dfSGreg Roach 463ade503dfSGreg Roach /** 464ade503dfSGreg Roach * Misecellaneous dimensions, fonts, styles, etc. 465ade503dfSGreg Roach * 466ade503dfSGreg Roach * @param string $parameter_name 467ade503dfSGreg Roach * 468ade503dfSGreg Roach * @return string|int|float 469ade503dfSGreg Roach */ 470ade503dfSGreg Roach public function parameter($parameter_name) 471ade503dfSGreg Roach { 472ade503dfSGreg Roach return ''; 473ade503dfSGreg Roach } 474ade503dfSGreg Roach 475ade503dfSGreg Roach /** 476ade503dfSGreg Roach * Generate a list of items for the main menu. 477ade503dfSGreg Roach * 4780c8c69d4SGreg Roach * @param Tree|null $tree 4790c8c69d4SGreg Roach * 480ade503dfSGreg Roach * @return Menu[] 481ade503dfSGreg Roach */ 4820c8c69d4SGreg Roach public function genealogyMenu(?Tree $tree): array 483ade503dfSGreg Roach { 4840c8c69d4SGreg Roach if ($tree === null) { 4850c8c69d4SGreg Roach return []; 4860c8c69d4SGreg Roach } 4870c8c69d4SGreg Roach 4880c8c69d4SGreg Roach return app(ModuleService::class)->findByComponent(ModuleMenuInterface::class, $tree, Auth::user()) 4890b5fd0a6SGreg Roach ->map(static function (ModuleMenuInterface $menu) use ($tree): ?Menu { 4900c8c69d4SGreg Roach return $menu->getMenu($tree); 491ade503dfSGreg Roach }) 492ade503dfSGreg Roach ->filter() 493ade503dfSGreg Roach ->all(); 494ade503dfSGreg Roach } 495ade503dfSGreg Roach 496ade503dfSGreg Roach /** 4970c8c69d4SGreg Roach * Create the genealogy menu. 498ade503dfSGreg Roach * 499ade503dfSGreg Roach * @param Menu[] $menus 500ade503dfSGreg Roach * 501ade503dfSGreg Roach * @return string 502ade503dfSGreg Roach */ 5030c8c69d4SGreg Roach public function genealogyMenuContent(array $menus): string 504ade503dfSGreg Roach { 5050b5fd0a6SGreg Roach return implode('', array_map(static function (Menu $menu): string { 506f78837dcSGreg Roach return view('components/menu-item', ['menu' => $menu]); 507ade503dfSGreg Roach }, $menus)); 508ade503dfSGreg Roach } 509ade503dfSGreg Roach 510ade503dfSGreg Roach /** 511ade503dfSGreg Roach * Generate a list of items for the user menu. 512ade503dfSGreg Roach * 5130c8c69d4SGreg Roach * @param Tree|null $tree 5140c8c69d4SGreg Roach * 515ade503dfSGreg Roach * @return Menu[] 516ade503dfSGreg Roach */ 5170c8c69d4SGreg Roach public function userMenu(?Tree $tree): array 518ade503dfSGreg Roach { 519ade503dfSGreg Roach return array_filter([ 5200c8c69d4SGreg Roach $this->menuPendingChanges($tree), 5210c8c69d4SGreg Roach $this->menuMyPages($tree), 522ade503dfSGreg Roach $this->menuThemes(), 523ade503dfSGreg Roach $this->menuLanguages(), 524ade503dfSGreg Roach $this->menuLogin(), 525ade503dfSGreg Roach $this->menuLogout(), 526ade503dfSGreg Roach ]); 527ade503dfSGreg Roach } 528ade503dfSGreg Roach 529ade503dfSGreg Roach /** 530ade503dfSGreg Roach * A list of CSS files to include for this page. 531ade503dfSGreg Roach * 532ade503dfSGreg Roach * @return string[] 533ade503dfSGreg Roach */ 534ade503dfSGreg Roach public function stylesheets(): array 535ade503dfSGreg Roach { 536ade503dfSGreg Roach return []; 537ade503dfSGreg Roach } 53849a243cbSGreg Roach} 539