149a243cbSGreg Roach<?php 249a243cbSGreg Roach/** 349a243cbSGreg Roach * webtrees: online genealogy 449a243cbSGreg Roach * Copyright (C) 2019 webtrees development team 549a243cbSGreg Roach * This program is free software: you can redistribute it and/or modify 649a243cbSGreg Roach * it under the terms of the GNU General Public License as published by 749a243cbSGreg Roach * the Free Software Foundation, either version 3 of the License, or 849a243cbSGreg Roach * (at your option) any later version. 949a243cbSGreg Roach * This program is distributed in the hope that it will be useful, 1049a243cbSGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 1149a243cbSGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1249a243cbSGreg Roach * GNU General Public License for more details. 1349a243cbSGreg Roach * You should have received a copy of the GNU General Public License 1449a243cbSGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>. 1549a243cbSGreg Roach */ 1649a243cbSGreg Roachdeclare(strict_types=1); 1749a243cbSGreg Roach 1849a243cbSGreg Roachnamespace Fisharebest\Webtrees\Module; 1949a243cbSGreg Roach 20ade503dfSGreg Roachuse Fisharebest\Webtrees\Auth; 21ade503dfSGreg Roachuse Fisharebest\Webtrees\Fact; 22ade503dfSGreg Roachuse Fisharebest\Webtrees\Gedcom; 23ade503dfSGreg Roachuse Fisharebest\Webtrees\GedcomTag; 24ade503dfSGreg Roachuse Fisharebest\Webtrees\I18N; 25ade503dfSGreg Roachuse Fisharebest\Webtrees\Individual; 26ade503dfSGreg Roachuse Fisharebest\Webtrees\Menu; 274ca7e03cSGreg Roachuse Fisharebest\Webtrees\Services\ModuleService; 28ade503dfSGreg Roachuse Fisharebest\Webtrees\Tree; 29f397d0fdSGreg Roachuse Fisharebest\Webtrees\Webtrees; 306ccdf4f0SGreg Roachuse Psr\Http\Message\ServerRequestInterface; 316ccdf4f0SGreg Roachuse function app; 32ade503dfSGreg Roach 3349a243cbSGreg Roach/** 3449a243cbSGreg Roach * Trait ModuleThemeTrait - default implementation of ModuleThemeInterface 3549a243cbSGreg Roach */ 3649a243cbSGreg Roachtrait ModuleThemeTrait 3749a243cbSGreg Roach{ 38ade503dfSGreg Roach /** 393d8b2a8eSGreg Roach * A sentence describing what this module does. 403d8b2a8eSGreg Roach * 413d8b2a8eSGreg Roach * @return string 423d8b2a8eSGreg Roach */ 433d8b2a8eSGreg Roach public function description(): string 443d8b2a8eSGreg Roach { 453d8b2a8eSGreg Roach return I18N::translate('Theme') . ' — ' . $this->title(); 463d8b2a8eSGreg Roach } 473d8b2a8eSGreg Roach 483d8b2a8eSGreg Roach /** 49ade503dfSGreg Roach * Display an icon for this fact. 50ade503dfSGreg Roach * 51e837ff07SGreg Roach * @TODO use CSS for this 52e837ff07SGreg Roach * 53ade503dfSGreg Roach * @param Fact $fact 54ade503dfSGreg Roach * 55ade503dfSGreg Roach * @return string 56ade503dfSGreg Roach */ 57ade503dfSGreg Roach public function icon(Fact $fact): string 58ade503dfSGreg Roach { 59e837ff07SGreg Roach $asset = 'public/css/' . $this->name() . '/images/facts/' . $fact->getTag() . '.png'; 60f397d0fdSGreg Roach if (file_exists(Webtrees::ROOT_DIR . 'public' . $asset)) { 61e837ff07SGreg Roach return '<img src="' . e(asset($asset)) . '" title="' . GedcomTag::getLabel($fact->getTag()) . '">'; 62ade503dfSGreg Roach } 63ade503dfSGreg Roach 64ade503dfSGreg Roach // Spacer image - for alignment - until we move to a sprite. 65e837ff07SGreg Roach $asset = 'public/css/' . $this->name() . '/images/facts/NULL.png'; 66f397d0fdSGreg Roach if (file_exists(Webtrees::ROOT_DIR . 'public' . $asset)) { 67e837ff07SGreg Roach return '<img src="' . e(asset($asset)) . '">'; 68ade503dfSGreg Roach } 69ade503dfSGreg Roach 70ade503dfSGreg Roach return ''; 71ade503dfSGreg Roach } 72ade503dfSGreg Roach 73ade503dfSGreg Roach /** 74ade503dfSGreg Roach * Generate the facts, for display in charts. 75ade503dfSGreg Roach * 76ade503dfSGreg Roach * @param Individual $individual 77ade503dfSGreg Roach * 78ade503dfSGreg Roach * @return string 79ade503dfSGreg Roach */ 80ade503dfSGreg Roach public function individualBoxFacts(Individual $individual): string 81ade503dfSGreg Roach { 82ade503dfSGreg Roach $html = ''; 83ade503dfSGreg Roach 84ade503dfSGreg Roach $opt_tags = preg_split('/\W/', $individual->tree()->getPreference('CHART_BOX_TAGS'), 0, PREG_SPLIT_NO_EMPTY); 85ade503dfSGreg Roach // Show BIRT or equivalent event 86ade503dfSGreg Roach foreach (Gedcom::BIRTH_EVENTS as $birttag) { 8722d65e5aSGreg Roach if (!in_array($birttag, $opt_tags, true)) { 88820b62dfSGreg Roach $event = $individual->facts([$birttag])->first(); 89820b62dfSGreg Roach if ($event instanceof Fact) { 90ade503dfSGreg Roach $html .= $event->summary(); 91ade503dfSGreg Roach break; 92ade503dfSGreg Roach } 93ade503dfSGreg Roach } 94ade503dfSGreg Roach } 95ade503dfSGreg Roach // Show optional events (before death) 96ade503dfSGreg Roach foreach ($opt_tags as $key => $tag) { 9722d65e5aSGreg Roach if (!in_array($tag, Gedcom::DEATH_EVENTS, true)) { 98820b62dfSGreg Roach $event = $individual->facts([$tag])->first(); 99820b62dfSGreg Roach if ($event instanceof Fact) { 100ade503dfSGreg Roach $html .= $event->summary(); 101ade503dfSGreg Roach unset($opt_tags[$key]); 102ade503dfSGreg Roach } 103ade503dfSGreg Roach } 104ade503dfSGreg Roach } 105ade503dfSGreg Roach // Show DEAT or equivalent event 106ade503dfSGreg Roach foreach (Gedcom::DEATH_EVENTS as $deattag) { 107820b62dfSGreg Roach $event = $individual->facts([$deattag])->first(); 108820b62dfSGreg Roach if ($event instanceof Fact) { 109ade503dfSGreg Roach $html .= $event->summary(); 11022d65e5aSGreg Roach if (in_array($deattag, $opt_tags, true)) { 11122d65e5aSGreg Roach unset($opt_tags[array_search($deattag, $opt_tags, true)]); 112ade503dfSGreg Roach } 113ade503dfSGreg Roach break; 114ade503dfSGreg Roach } 115ade503dfSGreg Roach } 116ade503dfSGreg Roach // Show remaining optional events (after death) 117ade503dfSGreg Roach foreach ($opt_tags as $tag) { 118820b62dfSGreg Roach $event = $individual->facts([$tag])->first(); 119820b62dfSGreg Roach if ($event instanceof Fact) { 120ade503dfSGreg Roach $html .= $event->summary(); 121ade503dfSGreg Roach } 122ade503dfSGreg Roach } 123ade503dfSGreg Roach 124ade503dfSGreg Roach return $html; 125ade503dfSGreg Roach } 126ade503dfSGreg Roach 127ade503dfSGreg Roach /** 128ade503dfSGreg Roach * Links, to show in chart boxes; 129ade503dfSGreg Roach * 130ade503dfSGreg Roach * @param Individual $individual 131ade503dfSGreg Roach * 132ade503dfSGreg Roach * @return Menu[] 133ade503dfSGreg Roach */ 134ade503dfSGreg Roach public function individualBoxMenu(Individual $individual): array 135ade503dfSGreg Roach { 136ade503dfSGreg Roach $menus = array_merge( 137ade503dfSGreg Roach $this->individualBoxMenuCharts($individual), 138ade503dfSGreg Roach $this->individualBoxMenuFamilyLinks($individual) 139ade503dfSGreg Roach ); 140ade503dfSGreg Roach 141ade503dfSGreg Roach return $menus; 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 /** 196ade503dfSGreg Roach * Generate a menu item to change the blocks on the current (index.php) 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 207eb235819SGreg Roach $route = $request->getQueryParams()['route'] ?? ''; 208eb235819SGreg Roach 209eb235819SGreg Roach if (Auth::check() && $route === 'user-page') { 2100c8c69d4SGreg Roach return new Menu(I18N::translate('Customize this page'), route('user-page-edit', ['ged' => $tree->name()]), 'menu-change-blocks'); 211ade503dfSGreg Roach } 212ade503dfSGreg Roach 213eb235819SGreg Roach if (Auth::isManager($tree) && $route === 'tree-page') { 2140c8c69d4SGreg Roach return new Menu(I18N::translate('Customize this page'), route('tree-page-edit', ['ged' => $tree->name()]), 'menu-change-blocks'); 215ade503dfSGreg Roach } 216ade503dfSGreg Roach 217ade503dfSGreg Roach return null; 218ade503dfSGreg Roach } 219ade503dfSGreg Roach 220ade503dfSGreg Roach /** 221ade503dfSGreg Roach * Generate a menu item for the control panel. 222ade503dfSGreg Roach * 2230c8c69d4SGreg Roach * @param Tree $tree 2240c8c69d4SGreg Roach * 225ade503dfSGreg Roach * @return Menu|null 226ade503dfSGreg Roach */ 227e364afe4SGreg Roach public function menuControlPanel(Tree $tree): ?Menu 228ade503dfSGreg Roach { 229ade503dfSGreg Roach if (Auth::isAdmin()) { 230ade503dfSGreg Roach return new Menu(I18N::translate('Control panel'), route('admin-control-panel'), 'menu-admin'); 231ade503dfSGreg Roach } 232ade503dfSGreg Roach 2330c8c69d4SGreg Roach if (Auth::isManager($tree)) { 234ade503dfSGreg Roach return new Menu(I18N::translate('Control panel'), route('admin-control-panel-manager'), 'menu-admin'); 235ade503dfSGreg Roach } 236ade503dfSGreg Roach 237ade503dfSGreg Roach return null; 238ade503dfSGreg Roach } 239ade503dfSGreg Roach 240ade503dfSGreg Roach /** 241ade503dfSGreg Roach * A menu to show a list of available languages. 242ade503dfSGreg Roach * 243ade503dfSGreg Roach * @return Menu|null 244ade503dfSGreg Roach */ 245e364afe4SGreg Roach public function menuLanguages(): ?Menu 246ade503dfSGreg Roach { 247ade503dfSGreg Roach $menu = new Menu(I18N::translate('Language'), '#', 'menu-language'); 248ade503dfSGreg Roach 249ade503dfSGreg Roach foreach (I18N::activeLocales() as $locale) { 250ade503dfSGreg Roach $language_tag = $locale->languageTag(); 251ade503dfSGreg Roach $class = 'menu-language-' . $language_tag . (WT_LOCALE === $language_tag ? ' active' : ''); 252ade503dfSGreg Roach $menu->addSubmenu(new Menu($locale->endonym(), '#', $class, [ 253ade503dfSGreg Roach 'onclick' => 'return false;', 254ade503dfSGreg Roach 'data-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 276ade503dfSGreg Roach // Return to this page after login... 277*add3fa41SGreg Roach $url = app(ServerRequestInterface::class)->getAttribute('request_uri'); 278ade503dfSGreg Roach 279ade503dfSGreg Roach // ...but switch from the tree-page to the user-page 280ade503dfSGreg Roach $url = str_replace('route=tree-page', 'route=user-page', $url); 281ade503dfSGreg Roach 282ade503dfSGreg Roach return new Menu(I18N::translate('Sign in'), route('login', ['url' => $url]), 'menu-login', ['rel' => 'nofollow']); 283ade503dfSGreg Roach } 284ade503dfSGreg Roach 285ade503dfSGreg Roach /** 286ade503dfSGreg Roach * A logout menu option (or null if we are already logged out). 287ade503dfSGreg Roach * 288ade503dfSGreg Roach * @return Menu|null 289ade503dfSGreg Roach */ 290e364afe4SGreg Roach public function menuLogout(): ?Menu 291ade503dfSGreg Roach { 292ade503dfSGreg Roach if (Auth::check()) { 293ade503dfSGreg Roach return new Menu(I18N::translate('Sign out'), route('logout'), 'menu-logout'); 294ade503dfSGreg Roach } 295ade503dfSGreg Roach 296ade503dfSGreg Roach return null; 297ade503dfSGreg Roach } 298ade503dfSGreg Roach 299ade503dfSGreg Roach /** 300ade503dfSGreg Roach * A link to allow users to edit their account settings. 301ade503dfSGreg Roach * 302ade503dfSGreg Roach * @return Menu|null 303ade503dfSGreg Roach */ 304e364afe4SGreg Roach public function menuMyAccount(): ?Menu 305ade503dfSGreg Roach { 306ade503dfSGreg Roach if (Auth::check()) { 307ade503dfSGreg Roach return new Menu(I18N::translate('My account'), route('my-account')); 308ade503dfSGreg Roach } 309ade503dfSGreg Roach 310ade503dfSGreg Roach return null; 311ade503dfSGreg Roach } 312ade503dfSGreg Roach 313ade503dfSGreg Roach /** 314ade503dfSGreg Roach * A link to the user's individual record (individual.php). 315ade503dfSGreg Roach * 3160c8c69d4SGreg Roach * @param Tree $tree 3170c8c69d4SGreg Roach * 318ade503dfSGreg Roach * @return Menu|null 319ade503dfSGreg Roach */ 320e364afe4SGreg Roach public function menuMyIndividualRecord(Tree $tree): ?Menu 321ade503dfSGreg Roach { 3220c8c69d4SGreg Roach $record = Individual::getInstance($tree->getUserPreference(Auth::user(), 'gedcomid'), $tree); 323ade503dfSGreg Roach 324ade503dfSGreg Roach if ($record) { 325ade503dfSGreg Roach return new Menu(I18N::translate('My individual record'), $record->url(), 'menu-myrecord'); 326ade503dfSGreg Roach } 327ade503dfSGreg Roach 328ade503dfSGreg Roach return null; 329ade503dfSGreg Roach } 330ade503dfSGreg Roach 331ade503dfSGreg Roach /** 332ade503dfSGreg Roach * A link to the user's personal home page. 333ade503dfSGreg Roach * 3340c8c69d4SGreg Roach * @param Tree $tree 3350c8c69d4SGreg Roach * 336ade503dfSGreg Roach * @return Menu 337ade503dfSGreg Roach */ 3380c8c69d4SGreg Roach public function menuMyPage(Tree $tree): Menu 339ade503dfSGreg Roach { 3400c8c69d4SGreg Roach return new Menu(I18N::translate('My page'), route('user-page', ['ged' => $tree->name()]), 'menu-mypage'); 341ade503dfSGreg Roach } 342ade503dfSGreg Roach 343ade503dfSGreg Roach /** 344ade503dfSGreg Roach * A menu for the user's personal pages. 345ade503dfSGreg Roach * 3460c8c69d4SGreg Roach * @param Tree|null $tree 3470c8c69d4SGreg Roach * 348ade503dfSGreg Roach * @return Menu|null 349ade503dfSGreg Roach */ 350e364afe4SGreg Roach public function menuMyPages(?Tree $tree): ?Menu 351ade503dfSGreg Roach { 3520c8c69d4SGreg Roach if ($tree instanceof Tree && Auth::id()) { 353ade503dfSGreg Roach return new Menu(I18N::translate('My pages'), '#', 'menu-mymenu', [], array_filter([ 3540c8c69d4SGreg Roach $this->menuMyPage($tree), 3550c8c69d4SGreg Roach $this->menuMyIndividualRecord($tree), 3560c8c69d4SGreg Roach $this->menuMyPedigree($tree), 357ade503dfSGreg Roach $this->menuMyAccount(), 3580c8c69d4SGreg Roach $this->menuControlPanel($tree), 3590c8c69d4SGreg Roach $this->menuChangeBlocks($tree), 360ade503dfSGreg Roach ])); 361ade503dfSGreg Roach } 362ade503dfSGreg Roach 363ade503dfSGreg Roach return null; 364ade503dfSGreg Roach } 365ade503dfSGreg Roach 366ade503dfSGreg Roach /** 367ade503dfSGreg Roach * A link to the user's individual record. 368ade503dfSGreg Roach * 3690c8c69d4SGreg Roach * @param Tree $tree 3700c8c69d4SGreg Roach * 371ade503dfSGreg Roach * @return Menu|null 372ade503dfSGreg Roach */ 373e364afe4SGreg Roach public function menuMyPedigree(Tree $tree): ?Menu 374ade503dfSGreg Roach { 3750c8c69d4SGreg Roach $gedcomid = $tree->getUserPreference(Auth::user(), 'gedcomid'); 376ade503dfSGreg Roach 3770c8c69d4SGreg Roach $pedigree_chart = app(ModuleService::class)->findByComponent(ModuleChartInterface::class, $tree, Auth::user()) 3780b5fd0a6SGreg Roach ->filter(static function (ModuleInterface $module): bool { 379ade503dfSGreg Roach return $module instanceof PedigreeChartModule; 380ade503dfSGreg Roach }); 381ade503dfSGreg Roach 382ade503dfSGreg Roach if ($gedcomid !== '' && $pedigree_chart instanceof PedigreeChartModule) { 383ade503dfSGreg Roach return new Menu( 384ade503dfSGreg Roach I18N::translate('My pedigree'), 385ade503dfSGreg Roach route('pedigree', [ 386ade503dfSGreg Roach 'xref' => $gedcomid, 3870c8c69d4SGreg Roach 'ged' => $tree->name(), 388ade503dfSGreg Roach ]), 389ade503dfSGreg Roach 'menu-mypedigree' 390ade503dfSGreg Roach ); 391ade503dfSGreg Roach } 392ade503dfSGreg Roach 393ade503dfSGreg Roach return null; 394ade503dfSGreg Roach } 395ade503dfSGreg Roach 396ade503dfSGreg Roach /** 397ade503dfSGreg Roach * Create a pending changes menu. 398ade503dfSGreg Roach * 3990c8c69d4SGreg Roach * @param Tree|null $tree 4000c8c69d4SGreg Roach * 401ade503dfSGreg Roach * @return Menu|null 402ade503dfSGreg Roach */ 403e364afe4SGreg Roach public function menuPendingChanges(?Tree $tree): ?Menu 404ade503dfSGreg Roach { 4050c8c69d4SGreg Roach if ($tree instanceof Tree && $tree->hasPendingEdit() && Auth::isModerator($tree)) { 406ade503dfSGreg Roach $url = route('show-pending', [ 4070c8c69d4SGreg Roach 'ged' => $tree->name(), 408cf8c0692SGreg Roach 'url' => (string) app(ServerRequestInterface::class)->getUri(), 409ade503dfSGreg Roach ]); 410ade503dfSGreg Roach 411ade503dfSGreg Roach return new Menu(I18N::translate('Pending changes'), $url, 'menu-pending'); 412ade503dfSGreg Roach } 413ade503dfSGreg Roach 414ade503dfSGreg Roach return null; 415ade503dfSGreg Roach } 416ade503dfSGreg Roach 417ade503dfSGreg Roach /** 418ade503dfSGreg Roach * Themes menu. 419ade503dfSGreg Roach * 420ade503dfSGreg Roach * @return Menu|null 421ade503dfSGreg Roach */ 422e364afe4SGreg Roach public function menuThemes(): ?Menu 423ade503dfSGreg Roach { 424b668782fSGreg Roach $themes = app(ModuleService::class)->findByInterface(ModuleThemeInterface::class, false, true); 425df8baf00SGreg Roach 426cab242e7SGreg Roach $current_theme = app(ModuleThemeInterface::class); 4278136679eSGreg Roach 4288136679eSGreg Roach if ($themes->count() > 1) { 4290b5fd0a6SGreg Roach $submenus = $themes->map(static function (ModuleThemeInterface $theme) use ($current_theme): Menu { 4308136679eSGreg Roach $active = $theme->name() === $current_theme->name(); 4318136679eSGreg Roach $class = 'menu-theme-' . $theme->name() . ($active ? ' active' : ''); 4328136679eSGreg Roach 4338136679eSGreg Roach return new Menu($theme->title(), '#', $class, [ 434ade503dfSGreg Roach 'onclick' => 'return false;', 435ade503dfSGreg Roach 'data-theme' => $theme->name(), 436ade503dfSGreg Roach ]); 437ade503dfSGreg Roach }); 438ade503dfSGreg Roach 4398136679eSGreg Roach return new Menu(I18N::translate('Theme'), '#', 'menu-theme', [], $submenus->all()); 440ade503dfSGreg Roach } 441ade503dfSGreg Roach 442ade503dfSGreg Roach return null; 443ade503dfSGreg Roach } 444ade503dfSGreg Roach 445ade503dfSGreg Roach /** 446ade503dfSGreg Roach * Misecellaneous dimensions, fonts, styles, etc. 447ade503dfSGreg Roach * 448ade503dfSGreg Roach * @param string $parameter_name 449ade503dfSGreg Roach * 450ade503dfSGreg Roach * @return string|int|float 451ade503dfSGreg Roach */ 452ade503dfSGreg Roach public function parameter($parameter_name) 453ade503dfSGreg Roach { 454ade503dfSGreg Roach return ''; 455ade503dfSGreg Roach } 456ade503dfSGreg Roach 457ade503dfSGreg Roach /** 458ade503dfSGreg Roach * Generate a list of items for the main menu. 459ade503dfSGreg Roach * 4600c8c69d4SGreg Roach * @param Tree|null $tree 4610c8c69d4SGreg Roach * 462ade503dfSGreg Roach * @return Menu[] 463ade503dfSGreg Roach */ 4640c8c69d4SGreg Roach public function genealogyMenu(?Tree $tree): array 465ade503dfSGreg Roach { 4660c8c69d4SGreg Roach if ($tree === null) { 4670c8c69d4SGreg Roach return []; 4680c8c69d4SGreg Roach } 4690c8c69d4SGreg Roach 4700c8c69d4SGreg Roach return app(ModuleService::class)->findByComponent(ModuleMenuInterface::class, $tree, Auth::user()) 4710b5fd0a6SGreg Roach ->map(static function (ModuleMenuInterface $menu) use ($tree): ?Menu { 4720c8c69d4SGreg Roach return $menu->getMenu($tree); 473ade503dfSGreg Roach }) 474ade503dfSGreg Roach ->filter() 475ade503dfSGreg Roach ->all(); 476ade503dfSGreg Roach } 477ade503dfSGreg Roach 478ade503dfSGreg Roach /** 4790c8c69d4SGreg Roach * Create the genealogy menu. 480ade503dfSGreg Roach * 481ade503dfSGreg Roach * @param Menu[] $menus 482ade503dfSGreg Roach * 483ade503dfSGreg Roach * @return string 484ade503dfSGreg Roach */ 4850c8c69d4SGreg Roach public function genealogyMenuContent(array $menus): string 486ade503dfSGreg Roach { 4870b5fd0a6SGreg Roach return implode('', array_map(static function (Menu $menu): string { 488ade503dfSGreg Roach return $menu->bootstrap4(); 489ade503dfSGreg Roach }, $menus)); 490ade503dfSGreg Roach } 491ade503dfSGreg Roach 492ade503dfSGreg Roach /** 493ade503dfSGreg Roach * Generate a list of items for the user menu. 494ade503dfSGreg Roach * 4950c8c69d4SGreg Roach * @param Tree|null $tree 4960c8c69d4SGreg Roach * 497ade503dfSGreg Roach * @return Menu[] 498ade503dfSGreg Roach */ 4990c8c69d4SGreg Roach public function userMenu(?Tree $tree): array 500ade503dfSGreg Roach { 501ade503dfSGreg Roach return array_filter([ 5020c8c69d4SGreg Roach $this->menuPendingChanges($tree), 5030c8c69d4SGreg Roach $this->menuMyPages($tree), 504ade503dfSGreg Roach $this->menuThemes(), 505ade503dfSGreg Roach $this->menuLanguages(), 506ade503dfSGreg Roach $this->menuLogin(), 507ade503dfSGreg Roach $this->menuLogout(), 508ade503dfSGreg Roach ]); 509ade503dfSGreg Roach } 510ade503dfSGreg Roach 511ade503dfSGreg Roach /** 512ade503dfSGreg Roach * A list of CSS files to include for this page. 513ade503dfSGreg Roach * 514ade503dfSGreg Roach * @return string[] 515ade503dfSGreg Roach */ 516ade503dfSGreg Roach public function stylesheets(): array 517ade503dfSGreg Roach { 518ade503dfSGreg Roach return []; 519ade503dfSGreg Roach } 52049a243cbSGreg Roach} 521