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; 29ade503dfSGreg Roachuse Symfony\Component\HttpFoundation\Request; 30ade503dfSGreg Roach 3149a243cbSGreg Roach/** 3249a243cbSGreg Roach * Trait ModuleThemeTrait - default implementation of ModuleThemeInterface 3349a243cbSGreg Roach */ 3449a243cbSGreg Roachtrait ModuleThemeTrait 3549a243cbSGreg Roach{ 36ade503dfSGreg Roach /** @var Request */ 37ade503dfSGreg Roach protected $request; 38ade503dfSGreg Roach 39ade503dfSGreg Roach /** 40ade503dfSGreg Roach * @param Request $request 41ade503dfSGreg Roach */ 420c8c69d4SGreg Roach public function __construct(Request $request) 43ade503dfSGreg Roach { 44ade503dfSGreg Roach $this->request = $request; 45ade503dfSGreg Roach } 46ade503dfSGreg Roach 47ade503dfSGreg Roach /** 48ade503dfSGreg Roach * Add markup to the secondary menu. 49ade503dfSGreg Roach * 500c8c69d4SGreg Roach * @param Tree|null $tree 510c8c69d4SGreg Roach * 52ade503dfSGreg Roach * @return string 53ade503dfSGreg Roach */ 540c8c69d4SGreg Roach public function formatUserMenu(?Tree $tree): string 55ade503dfSGreg Roach { 56ade503dfSGreg Roach return 570c8c69d4SGreg Roach '<ul class="nav wt-user-menu">' . 58f79c9408SGreg Roach implode('', array_map(function (Menu $menu): string { 590c8c69d4SGreg Roach return $this->formatUserMenuItem($menu); 600c8c69d4SGreg Roach }, $this->userMenu($tree))) . 61ade503dfSGreg Roach '</ul>'; 62ade503dfSGreg Roach } 63ade503dfSGreg Roach 64ade503dfSGreg Roach /** 65ade503dfSGreg Roach * Add markup to an item in the secondary menu. 66ade503dfSGreg Roach * 67ade503dfSGreg Roach * @param Menu $menu 68ade503dfSGreg Roach * 69ade503dfSGreg Roach * @return string 70ade503dfSGreg Roach */ 710c8c69d4SGreg Roach public function formatUserMenuItem(Menu $menu): string 72ade503dfSGreg Roach { 73ade503dfSGreg Roach return $menu->bootstrap4(); 74ade503dfSGreg Roach } 75ade503dfSGreg Roach 76ade503dfSGreg Roach /** 77ade503dfSGreg Roach * Display an icon for this fact. 78ade503dfSGreg Roach * 79e837ff07SGreg Roach * @TODO use CSS for this 80e837ff07SGreg Roach * 81ade503dfSGreg Roach * @param Fact $fact 82ade503dfSGreg Roach * 83ade503dfSGreg Roach * @return string 84ade503dfSGreg Roach */ 85ade503dfSGreg Roach public function icon(Fact $fact): string 86ade503dfSGreg Roach { 87e837ff07SGreg Roach $asset = 'public/css/' . $this->name() . '/images/facts/' . $fact->getTag() . '.png'; 88e837ff07SGreg Roach if (file_exists(WT_ROOT . 'public' . $asset)) { 89e837ff07SGreg Roach return '<img src="' . e(asset($asset)) . '" title="' . GedcomTag::getLabel($fact->getTag()) . '">'; 90ade503dfSGreg Roach } 91ade503dfSGreg Roach 92ade503dfSGreg Roach // Spacer image - for alignment - until we move to a sprite. 93e837ff07SGreg Roach $asset = 'public/css/' . $this->name() . '/images/facts/NULL.png'; 94e837ff07SGreg Roach if (file_exists(WT_ROOT . 'public' . $asset)) { 95e837ff07SGreg Roach return '<img src="' . e(asset($asset)) . '">'; 96ade503dfSGreg Roach } 97ade503dfSGreg Roach 98ade503dfSGreg Roach return ''; 99ade503dfSGreg Roach } 100ade503dfSGreg Roach 101ade503dfSGreg Roach /** 102ade503dfSGreg Roach * Display an individual in a box - for charts, etc. 103ade503dfSGreg Roach * 104ade503dfSGreg Roach * @param Individual $individual 105ade503dfSGreg Roach * 106ade503dfSGreg Roach * @return string 107ade503dfSGreg Roach */ 108ade503dfSGreg Roach public function individualBox(Individual $individual): string 109ade503dfSGreg Roach { 110242a7862SGreg Roach return view('chart-box', ['individual' => $individual]); 111ade503dfSGreg Roach } 112ade503dfSGreg Roach 113ade503dfSGreg Roach /** 114ade503dfSGreg Roach * Display an empty box - for a missing individual in a chart. 115ade503dfSGreg Roach * 116ade503dfSGreg Roach * @return string 117ade503dfSGreg Roach */ 118ade503dfSGreg Roach public function individualBoxEmpty(): string 119ade503dfSGreg Roach { 120242a7862SGreg Roach return '<div class="wt-chart-box"></div>'; 121ade503dfSGreg Roach } 122ade503dfSGreg Roach 123ade503dfSGreg Roach /** 124ade503dfSGreg Roach * Display an individual in a box - for charts, etc. 125ade503dfSGreg Roach * 126ade503dfSGreg Roach * @param Individual $individual 127ade503dfSGreg Roach * 128ade503dfSGreg Roach * @return string 129ade503dfSGreg Roach */ 130ade503dfSGreg Roach public function individualBoxLarge(Individual $individual): string 131ade503dfSGreg Roach { 132242a7862SGreg Roach return $this->individualBox($individual); 133ade503dfSGreg Roach } 134ade503dfSGreg Roach 135ade503dfSGreg Roach /** 136ade503dfSGreg Roach * Display an individual in a box - for charts, etc. 137ade503dfSGreg Roach * 138ade503dfSGreg Roach * @param Individual $individual 139ade503dfSGreg Roach * 140ade503dfSGreg Roach * @return string 141ade503dfSGreg Roach */ 142ade503dfSGreg Roach public function individualBoxSmall(Individual $individual): string 143ade503dfSGreg Roach { 144242a7862SGreg Roach return $this->individualBox($individual); 145ade503dfSGreg Roach } 146ade503dfSGreg Roach 147ade503dfSGreg Roach /** 148ade503dfSGreg Roach * Display an individual in a box - for charts, etc. 149ade503dfSGreg Roach * 150ade503dfSGreg Roach * @return string 151ade503dfSGreg Roach */ 152ade503dfSGreg Roach public function individualBoxSmallEmpty(): string 153ade503dfSGreg Roach { 154242a7862SGreg Roach return '<div class="wt-chart-box"></div>'; 155ade503dfSGreg Roach } 156ade503dfSGreg Roach 157ade503dfSGreg Roach /** 158ade503dfSGreg Roach * Generate the facts, for display in charts. 159ade503dfSGreg Roach * 160ade503dfSGreg Roach * @param Individual $individual 161ade503dfSGreg Roach * 162ade503dfSGreg Roach * @return string 163ade503dfSGreg Roach */ 164ade503dfSGreg Roach public function individualBoxFacts(Individual $individual): string 165ade503dfSGreg Roach { 166ade503dfSGreg Roach $html = ''; 167ade503dfSGreg Roach 168ade503dfSGreg Roach $opt_tags = preg_split('/\W/', $individual->tree()->getPreference('CHART_BOX_TAGS'), 0, PREG_SPLIT_NO_EMPTY); 169ade503dfSGreg Roach // Show BIRT or equivalent event 170ade503dfSGreg Roach foreach (Gedcom::BIRTH_EVENTS as $birttag) { 171ade503dfSGreg Roach if (!in_array($birttag, $opt_tags)) { 172820b62dfSGreg Roach $event = $individual->facts([$birttag])->first(); 173820b62dfSGreg Roach if ($event instanceof Fact) { 174ade503dfSGreg Roach $html .= $event->summary(); 175ade503dfSGreg Roach break; 176ade503dfSGreg Roach } 177ade503dfSGreg Roach } 178ade503dfSGreg Roach } 179ade503dfSGreg Roach // Show optional events (before death) 180ade503dfSGreg Roach foreach ($opt_tags as $key => $tag) { 181ade503dfSGreg Roach if (!in_array($tag, Gedcom::DEATH_EVENTS)) { 182820b62dfSGreg Roach $event = $individual->facts([$tag])->first(); 183820b62dfSGreg Roach if ($event instanceof Fact) { 184ade503dfSGreg Roach $html .= $event->summary(); 185ade503dfSGreg Roach unset($opt_tags[$key]); 186ade503dfSGreg Roach } 187ade503dfSGreg Roach } 188ade503dfSGreg Roach } 189ade503dfSGreg Roach // Show DEAT or equivalent event 190ade503dfSGreg Roach foreach (Gedcom::DEATH_EVENTS as $deattag) { 191820b62dfSGreg Roach $event = $individual->facts([$deattag])->first(); 192820b62dfSGreg Roach if ($event instanceof Fact) { 193ade503dfSGreg Roach $html .= $event->summary(); 194ade503dfSGreg Roach if (in_array($deattag, $opt_tags)) { 195ade503dfSGreg Roach unset($opt_tags[array_search($deattag, $opt_tags)]); 196ade503dfSGreg Roach } 197ade503dfSGreg Roach break; 198ade503dfSGreg Roach } 199ade503dfSGreg Roach } 200ade503dfSGreg Roach // Show remaining optional events (after death) 201ade503dfSGreg Roach foreach ($opt_tags as $tag) { 202820b62dfSGreg Roach $event = $individual->facts([$tag])->first(); 203820b62dfSGreg Roach if ($event instanceof Fact) { 204ade503dfSGreg Roach $html .= $event->summary(); 205ade503dfSGreg Roach } 206ade503dfSGreg Roach } 207ade503dfSGreg Roach 208ade503dfSGreg Roach return $html; 209ade503dfSGreg Roach } 210ade503dfSGreg Roach 211ade503dfSGreg Roach /** 212ade503dfSGreg Roach * Links, to show in chart boxes; 213ade503dfSGreg Roach * 214ade503dfSGreg Roach * @param Individual $individual 215ade503dfSGreg Roach * 216ade503dfSGreg Roach * @return Menu[] 217ade503dfSGreg Roach */ 218ade503dfSGreg Roach public function individualBoxMenu(Individual $individual): array 219ade503dfSGreg Roach { 220ade503dfSGreg Roach $menus = array_merge( 221ade503dfSGreg Roach $this->individualBoxMenuCharts($individual), 222ade503dfSGreg Roach $this->individualBoxMenuFamilyLinks($individual) 223ade503dfSGreg Roach ); 224ade503dfSGreg Roach 225ade503dfSGreg Roach return $menus; 226ade503dfSGreg Roach } 227ade503dfSGreg Roach 228ade503dfSGreg Roach /** 229ade503dfSGreg Roach * Chart links, to show in chart boxes; 230ade503dfSGreg Roach * 231ade503dfSGreg Roach * @param Individual $individual 232ade503dfSGreg Roach * 233ade503dfSGreg Roach * @return Menu[] 234ade503dfSGreg Roach */ 235ade503dfSGreg Roach public function individualBoxMenuCharts(Individual $individual): array 236ade503dfSGreg Roach { 237ade503dfSGreg Roach $menus = []; 238*f39638cfSGreg Roach foreach (app(ModuleService::class)->findByComponent(ModuleChartInterface::class, $individual->tree(), Auth::user()) as $chart) { 239ade503dfSGreg Roach $menu = $chart->chartBoxMenu($individual); 240ade503dfSGreg Roach if ($menu) { 241ade503dfSGreg Roach $menus[] = $menu; 242ade503dfSGreg Roach } 243ade503dfSGreg Roach } 244ade503dfSGreg Roach 245ade503dfSGreg Roach usort($menus, function (Menu $x, Menu $y) { 246ade503dfSGreg Roach return I18N::strcasecmp($x->getLabel(), $y->getLabel()); 247ade503dfSGreg Roach }); 248ade503dfSGreg Roach 249ade503dfSGreg Roach return $menus; 250ade503dfSGreg Roach } 251ade503dfSGreg Roach 252ade503dfSGreg Roach /** 253ade503dfSGreg Roach * Family links, to show in chart boxes. 254ade503dfSGreg Roach * 255ade503dfSGreg Roach * @param Individual $individual 256ade503dfSGreg Roach * 257ade503dfSGreg Roach * @return Menu[] 258ade503dfSGreg Roach */ 259ade503dfSGreg Roach public function individualBoxMenuFamilyLinks(Individual $individual): array 260ade503dfSGreg Roach { 261ade503dfSGreg Roach $menus = []; 262ade503dfSGreg Roach 26339ca88baSGreg Roach foreach ($individual->spouseFamilies() as $family) { 264ade503dfSGreg Roach $menus[] = new Menu('<strong>' . I18N::translate('Family with spouse') . '</strong>', $family->url()); 26539ca88baSGreg Roach $spouse = $family->spouse($individual); 266ade503dfSGreg Roach if ($spouse && $spouse->canShowName()) { 26739ca88baSGreg Roach $menus[] = new Menu($spouse->fullName(), $spouse->url()); 268ade503dfSGreg Roach } 26939ca88baSGreg Roach foreach ($family->children() as $child) { 270ade503dfSGreg Roach if ($child->canShowName()) { 27139ca88baSGreg Roach $menus[] = new Menu($child->fullName(), $child->url()); 272ade503dfSGreg Roach } 273ade503dfSGreg Roach } 274ade503dfSGreg Roach } 275ade503dfSGreg Roach 276ade503dfSGreg Roach return $menus; 277ade503dfSGreg Roach } 278ade503dfSGreg Roach 279ade503dfSGreg Roach /** 280ade503dfSGreg Roach * Generate a menu item to change the blocks on the current (index.php) page. 281ade503dfSGreg Roach * 2820c8c69d4SGreg Roach * @param Tree $tree 2830c8c69d4SGreg Roach * 284ade503dfSGreg Roach * @return Menu|null 285ade503dfSGreg Roach */ 2860c8c69d4SGreg Roach public function menuChangeBlocks(Tree $tree) 287ade503dfSGreg Roach { 288ade503dfSGreg Roach if (Auth::check() && $this->request->get('route') === 'user-page') { 2890c8c69d4SGreg Roach return new Menu(I18N::translate('Customize this page'), route('user-page-edit', ['ged' => $tree->name()]), 'menu-change-blocks'); 290ade503dfSGreg Roach } 291ade503dfSGreg Roach 2920c8c69d4SGreg Roach if (Auth::isManager($tree) && $this->request->get('route') === 'tree-page') { 2930c8c69d4SGreg Roach return new Menu(I18N::translate('Customize this page'), route('tree-page-edit', ['ged' => $tree->name()]), 'menu-change-blocks'); 294ade503dfSGreg Roach } 295ade503dfSGreg Roach 296ade503dfSGreg Roach return null; 297ade503dfSGreg Roach } 298ade503dfSGreg Roach 299ade503dfSGreg Roach /** 300ade503dfSGreg Roach * Generate a menu item for the control panel. 301ade503dfSGreg Roach * 3020c8c69d4SGreg Roach * @param Tree $tree 3030c8c69d4SGreg Roach * 304ade503dfSGreg Roach * @return Menu|null 305ade503dfSGreg Roach */ 3060c8c69d4SGreg Roach public function menuControlPanel(Tree $tree) 307ade503dfSGreg Roach { 308ade503dfSGreg Roach if (Auth::isAdmin()) { 309ade503dfSGreg Roach return new Menu(I18N::translate('Control panel'), route('admin-control-panel'), 'menu-admin'); 310ade503dfSGreg Roach } 311ade503dfSGreg Roach 3120c8c69d4SGreg Roach if (Auth::isManager($tree)) { 313ade503dfSGreg Roach return new Menu(I18N::translate('Control panel'), route('admin-control-panel-manager'), 'menu-admin'); 314ade503dfSGreg Roach } 315ade503dfSGreg Roach 316ade503dfSGreg Roach return null; 317ade503dfSGreg Roach } 318ade503dfSGreg Roach 319ade503dfSGreg Roach /** 320ade503dfSGreg Roach * A menu to show a list of available languages. 321ade503dfSGreg Roach * 322ade503dfSGreg Roach * @return Menu|null 323ade503dfSGreg Roach */ 324ade503dfSGreg Roach public function menuLanguages() 325ade503dfSGreg Roach { 326ade503dfSGreg Roach $menu = new Menu(I18N::translate('Language'), '#', 'menu-language'); 327ade503dfSGreg Roach 328ade503dfSGreg Roach foreach (I18N::activeLocales() as $locale) { 329ade503dfSGreg Roach $language_tag = $locale->languageTag(); 330ade503dfSGreg Roach $class = 'menu-language-' . $language_tag . (WT_LOCALE === $language_tag ? ' active' : ''); 331ade503dfSGreg Roach $menu->addSubmenu(new Menu($locale->endonym(), '#', $class, [ 332ade503dfSGreg Roach 'onclick' => 'return false;', 333ade503dfSGreg Roach 'data-language' => $language_tag, 334ade503dfSGreg Roach ])); 335ade503dfSGreg Roach } 336ade503dfSGreg Roach 337ade503dfSGreg Roach if (count($menu->getSubmenus()) > 1) { 338ade503dfSGreg Roach return $menu; 339ade503dfSGreg Roach } 340ade503dfSGreg Roach 341ade503dfSGreg Roach return null; 342ade503dfSGreg Roach } 343ade503dfSGreg Roach 344ade503dfSGreg Roach /** 345ade503dfSGreg Roach * A login menu option (or null if we are already logged in). 346ade503dfSGreg Roach * 347ade503dfSGreg Roach * @return Menu|null 348ade503dfSGreg Roach */ 349ade503dfSGreg Roach public function menuLogin() 350ade503dfSGreg Roach { 351ade503dfSGreg Roach if (Auth::check()) { 352ade503dfSGreg Roach return null; 353ade503dfSGreg Roach } 354ade503dfSGreg Roach 355ade503dfSGreg Roach // Return to this page after login... 356ade503dfSGreg Roach $url = $this->request->getRequestUri(); 357ade503dfSGreg Roach 358ade503dfSGreg Roach // ...but switch from the tree-page to the user-page 359ade503dfSGreg Roach $url = str_replace('route=tree-page', 'route=user-page', $url); 360ade503dfSGreg Roach 361ade503dfSGreg Roach return new Menu(I18N::translate('Sign in'), route('login', ['url' => $url]), 'menu-login', ['rel' => 'nofollow']); 362ade503dfSGreg Roach } 363ade503dfSGreg Roach 364ade503dfSGreg Roach /** 365ade503dfSGreg Roach * A logout menu option (or null if we are already logged out). 366ade503dfSGreg Roach * 367ade503dfSGreg Roach * @return Menu|null 368ade503dfSGreg Roach */ 369ade503dfSGreg Roach public function menuLogout() 370ade503dfSGreg Roach { 371ade503dfSGreg Roach if (Auth::check()) { 372ade503dfSGreg Roach return new Menu(I18N::translate('Sign out'), route('logout'), 'menu-logout'); 373ade503dfSGreg Roach } 374ade503dfSGreg Roach 375ade503dfSGreg Roach return null; 376ade503dfSGreg Roach } 377ade503dfSGreg Roach 378ade503dfSGreg Roach /** 379ade503dfSGreg Roach * A link to allow users to edit their account settings. 380ade503dfSGreg Roach * 381ade503dfSGreg Roach * @return Menu|null 382ade503dfSGreg Roach */ 383ade503dfSGreg Roach public function menuMyAccount() 384ade503dfSGreg Roach { 385ade503dfSGreg Roach if (Auth::check()) { 386ade503dfSGreg Roach return new Menu(I18N::translate('My account'), route('my-account')); 387ade503dfSGreg Roach } 388ade503dfSGreg Roach 389ade503dfSGreg Roach return null; 390ade503dfSGreg Roach } 391ade503dfSGreg Roach 392ade503dfSGreg Roach /** 393ade503dfSGreg Roach * A link to the user's individual record (individual.php). 394ade503dfSGreg Roach * 3950c8c69d4SGreg Roach * @param Tree $tree 3960c8c69d4SGreg Roach * 397ade503dfSGreg Roach * @return Menu|null 398ade503dfSGreg Roach */ 3990c8c69d4SGreg Roach public function menuMyIndividualRecord(Tree $tree) 400ade503dfSGreg Roach { 4010c8c69d4SGreg Roach $record = Individual::getInstance($tree->getUserPreference(Auth::user(), 'gedcomid'), $tree); 402ade503dfSGreg Roach 403ade503dfSGreg Roach if ($record) { 404ade503dfSGreg Roach return new Menu(I18N::translate('My individual record'), $record->url(), 'menu-myrecord'); 405ade503dfSGreg Roach } 406ade503dfSGreg Roach 407ade503dfSGreg Roach return null; 408ade503dfSGreg Roach } 409ade503dfSGreg Roach 410ade503dfSGreg Roach /** 411ade503dfSGreg Roach * A link to the user's personal home page. 412ade503dfSGreg Roach * 4130c8c69d4SGreg Roach * @param Tree $tree 4140c8c69d4SGreg Roach * 415ade503dfSGreg Roach * @return Menu 416ade503dfSGreg Roach */ 4170c8c69d4SGreg Roach public function menuMyPage(Tree $tree): Menu 418ade503dfSGreg Roach { 4190c8c69d4SGreg Roach return new Menu(I18N::translate('My page'), route('user-page', ['ged' => $tree->name()]), 'menu-mypage'); 420ade503dfSGreg Roach } 421ade503dfSGreg Roach 422ade503dfSGreg Roach /** 423ade503dfSGreg Roach * A menu for the user's personal pages. 424ade503dfSGreg Roach * 4250c8c69d4SGreg Roach * @param Tree|null $tree 4260c8c69d4SGreg Roach * 427ade503dfSGreg Roach * @return Menu|null 428ade503dfSGreg Roach */ 4290c8c69d4SGreg Roach public function menuMyPages(?Tree $tree) 430ade503dfSGreg Roach { 4310c8c69d4SGreg Roach if ($tree instanceof Tree && Auth::id()) { 432ade503dfSGreg Roach return new Menu(I18N::translate('My pages'), '#', 'menu-mymenu', [], array_filter([ 4330c8c69d4SGreg Roach $this->menuMyPage($tree), 4340c8c69d4SGreg Roach $this->menuMyIndividualRecord($tree), 4350c8c69d4SGreg Roach $this->menuMyPedigree($tree), 436ade503dfSGreg Roach $this->menuMyAccount(), 4370c8c69d4SGreg Roach $this->menuControlPanel($tree), 4380c8c69d4SGreg Roach $this->menuChangeBlocks($tree), 439ade503dfSGreg Roach ])); 440ade503dfSGreg Roach } 441ade503dfSGreg Roach 442ade503dfSGreg Roach return null; 443ade503dfSGreg Roach } 444ade503dfSGreg Roach 445ade503dfSGreg Roach /** 446ade503dfSGreg Roach * A link to the user's individual record. 447ade503dfSGreg Roach * 4480c8c69d4SGreg Roach * @param Tree $tree 4490c8c69d4SGreg Roach * 450ade503dfSGreg Roach * @return Menu|null 451ade503dfSGreg Roach */ 4520c8c69d4SGreg Roach public function menuMyPedigree(Tree $tree) 453ade503dfSGreg Roach { 4540c8c69d4SGreg Roach $gedcomid = $tree->getUserPreference(Auth::user(), 'gedcomid'); 455ade503dfSGreg Roach 4560c8c69d4SGreg Roach $pedigree_chart = app(ModuleService::class)->findByComponent(ModuleChartInterface::class, $tree, Auth::user()) 457ade503dfSGreg Roach ->filter(function (ModuleInterface $module): bool { 458ade503dfSGreg Roach return $module instanceof PedigreeChartModule; 459ade503dfSGreg Roach }); 460ade503dfSGreg Roach 461ade503dfSGreg Roach if ($gedcomid !== '' && $pedigree_chart instanceof PedigreeChartModule) { 462ade503dfSGreg Roach return new Menu( 463ade503dfSGreg Roach I18N::translate('My pedigree'), 464ade503dfSGreg Roach route('pedigree', [ 465ade503dfSGreg Roach 'xref' => $gedcomid, 4660c8c69d4SGreg Roach 'ged' => $tree->name(), 467ade503dfSGreg Roach ]), 468ade503dfSGreg Roach 'menu-mypedigree' 469ade503dfSGreg Roach ); 470ade503dfSGreg Roach } 471ade503dfSGreg Roach 472ade503dfSGreg Roach return null; 473ade503dfSGreg Roach } 474ade503dfSGreg Roach 475ade503dfSGreg Roach /** 476ade503dfSGreg Roach * Create a pending changes menu. 477ade503dfSGreg Roach * 4780c8c69d4SGreg Roach * @param Tree|null $tree 4790c8c69d4SGreg Roach * 480ade503dfSGreg Roach * @return Menu|null 481ade503dfSGreg Roach */ 4820c8c69d4SGreg Roach public function menuPendingChanges(?Tree $tree) 483ade503dfSGreg Roach { 4840c8c69d4SGreg Roach if ($tree instanceof Tree && $tree->hasPendingEdit() && Auth::isModerator($tree)) { 485ade503dfSGreg Roach $url = route('show-pending', [ 4860c8c69d4SGreg Roach 'ged' => $tree->name(), 487ade503dfSGreg Roach 'url' => $this->request->getRequestUri(), 488ade503dfSGreg Roach ]); 489ade503dfSGreg Roach 490ade503dfSGreg Roach return new Menu(I18N::translate('Pending changes'), $url, 'menu-pending'); 491ade503dfSGreg Roach } 492ade503dfSGreg Roach 493ade503dfSGreg Roach return null; 494ade503dfSGreg Roach } 495ade503dfSGreg Roach 496ade503dfSGreg Roach /** 497ade503dfSGreg Roach * Themes menu. 498ade503dfSGreg Roach * 499ade503dfSGreg Roach * @return Menu|null 500ade503dfSGreg Roach */ 501ade503dfSGreg Roach public function menuThemes() 502ade503dfSGreg Roach { 5034ca7e03cSGreg Roach $themes = app(ModuleService::class)->findByInterface(ModuleThemeInterface::class); 504df8baf00SGreg Roach 505cab242e7SGreg Roach $current_theme = app(ModuleThemeInterface::class); 5068136679eSGreg Roach 5078136679eSGreg Roach if ($themes->count() > 1) { 5088136679eSGreg Roach $submenus = $themes->map(function (ModuleThemeInterface $theme) use ($current_theme): Menu { 5098136679eSGreg Roach $active = $theme->name() === $current_theme->name(); 5108136679eSGreg Roach $class = 'menu-theme-' . $theme->name() . ($active ? ' active' : ''); 5118136679eSGreg Roach 5128136679eSGreg Roach return new Menu($theme->title(), '#', $class, [ 513ade503dfSGreg Roach 'onclick' => 'return false;', 514ade503dfSGreg Roach 'data-theme' => $theme->name(), 515ade503dfSGreg Roach ]); 516ade503dfSGreg Roach }); 517ade503dfSGreg Roach 5188136679eSGreg Roach return new Menu(I18N::translate('Theme'), '#', 'menu-theme', [], $submenus->all()); 519ade503dfSGreg Roach } 520ade503dfSGreg Roach 521ade503dfSGreg Roach return null; 522ade503dfSGreg Roach } 523ade503dfSGreg Roach 524ade503dfSGreg Roach /** 525ade503dfSGreg Roach * Misecellaneous dimensions, fonts, styles, etc. 526ade503dfSGreg Roach * 527ade503dfSGreg Roach * @param string $parameter_name 528ade503dfSGreg Roach * 529ade503dfSGreg Roach * @return string|int|float 530ade503dfSGreg Roach */ 531ade503dfSGreg Roach public function parameter($parameter_name) 532ade503dfSGreg Roach { 533ade503dfSGreg Roach return ''; 534ade503dfSGreg Roach } 535ade503dfSGreg Roach 536ade503dfSGreg Roach /** 537ade503dfSGreg Roach * Generate a list of items for the main menu. 538ade503dfSGreg Roach * 5390c8c69d4SGreg Roach * @param Tree|null $tree 5400c8c69d4SGreg Roach * 541ade503dfSGreg Roach * @return Menu[] 542ade503dfSGreg Roach */ 5430c8c69d4SGreg Roach public function genealogyMenu(?Tree $tree): array 544ade503dfSGreg Roach { 5450c8c69d4SGreg Roach if ($tree === null) { 5460c8c69d4SGreg Roach return []; 5470c8c69d4SGreg Roach } 5480c8c69d4SGreg Roach 5490c8c69d4SGreg Roach return app(ModuleService::class)->findByComponent(ModuleMenuInterface::class, $tree, Auth::user()) 5500c8c69d4SGreg Roach ->map(function (ModuleMenuInterface $menu) use ($tree): ?Menu { 5510c8c69d4SGreg Roach return $menu->getMenu($tree); 552ade503dfSGreg Roach }) 553ade503dfSGreg Roach ->filter() 554ade503dfSGreg Roach ->all(); 555ade503dfSGreg Roach } 556ade503dfSGreg Roach 557ade503dfSGreg Roach /** 5580c8c69d4SGreg Roach * Create the genealogy menu. 559ade503dfSGreg Roach * 560ade503dfSGreg Roach * @param Menu[] $menus 561ade503dfSGreg Roach * 562ade503dfSGreg Roach * @return string 563ade503dfSGreg Roach */ 5640c8c69d4SGreg Roach public function genealogyMenuContent(array $menus): string 565ade503dfSGreg Roach { 566ade503dfSGreg Roach return implode('', array_map(function (Menu $menu): string { 567ade503dfSGreg Roach return $menu->bootstrap4(); 568ade503dfSGreg Roach }, $menus)); 569ade503dfSGreg Roach } 570ade503dfSGreg Roach 571ade503dfSGreg Roach /** 572ade503dfSGreg Roach * Generate a list of items for the user menu. 573ade503dfSGreg Roach * 5740c8c69d4SGreg Roach * @param Tree|null $tree 5750c8c69d4SGreg Roach * 576ade503dfSGreg Roach * @return Menu[] 577ade503dfSGreg Roach */ 5780c8c69d4SGreg Roach public function userMenu(?Tree $tree): array 579ade503dfSGreg Roach { 580ade503dfSGreg Roach return array_filter([ 5810c8c69d4SGreg Roach $this->menuPendingChanges($tree), 5820c8c69d4SGreg Roach $this->menuMyPages($tree), 583ade503dfSGreg Roach $this->menuThemes(), 584ade503dfSGreg Roach $this->menuLanguages(), 585ade503dfSGreg Roach $this->menuLogin(), 586ade503dfSGreg Roach $this->menuLogout(), 587ade503dfSGreg Roach ]); 588ade503dfSGreg Roach } 589ade503dfSGreg Roach 590ade503dfSGreg Roach /** 591ade503dfSGreg Roach * A list of CSS files to include for this page. 592ade503dfSGreg Roach * 593ade503dfSGreg Roach * @return string[] 594ade503dfSGreg Roach */ 595ade503dfSGreg Roach public function stylesheets(): array 596ade503dfSGreg Roach { 597ade503dfSGreg Roach return []; 598ade503dfSGreg Roach } 59949a243cbSGreg Roach} 600