1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2023 webtrees development team 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <https://www.gnu.org/licenses/>. 16 */ 17 18declare(strict_types=1); 19 20namespace Fisharebest\Webtrees\Module; 21 22use Fisharebest\Webtrees\Auth; 23use Fisharebest\Webtrees\I18N; 24use Fisharebest\Webtrees\Menu; 25use Fisharebest\Webtrees\Session; 26use Fisharebest\Webtrees\Site; 27use Fisharebest\Webtrees\Tree; 28use Fisharebest\Webtrees\Validator; 29use Psr\Http\Message\ResponseInterface; 30use Psr\Http\Message\ServerRequestInterface; 31 32use function asset; 33use function is_string; 34use function response; 35use function uasort; 36 37/** 38 * The colors theme. 39 */ 40class ColorsTheme extends CloudsTheme 41{ 42 // If no valid palette has been selected, use this one. 43 private const DEFAULT_PALETTE = 'ash'; 44 45 /** 46 * How should this module be identified in the control panel, etc.? 47 * 48 * @return string 49 */ 50 public function title(): string 51 { 52 /* I18N: Name of a theme. */ 53 return I18N::translate('colors'); 54 } 55 56 /** 57 * Generate a list of items for the user menu. 58 * 59 * @param Tree|null $tree 60 * 61 * @return array<Menu> 62 */ 63 public function userMenu(Tree|null $tree): array 64 { 65 return array_filter([ 66 $this->menuPendingChanges($tree), 67 $this->menuMyPages($tree), 68 $this->menuThemes(), 69 $this->menuPalette(), 70 $this->menuLanguages(), 71 $this->menuLogin(), 72 $this->menuLogout(), 73 ]); 74 } 75 76 /** 77 * Switch to a new palette 78 * 79 * @param ServerRequestInterface $request 80 * 81 * @return ResponseInterface 82 */ 83 public function postPaletteAction(ServerRequestInterface $request): ResponseInterface 84 { 85 $user = Validator::attributes($request)->user(); 86 $palette = Validator::queryParams($request)->isInArrayKeys($this->palettes())->string('palette'); 87 88 $user->setPreference('themecolor', $palette); 89 90 // If we are the admin, then use our selection as the site default. 91 if (Auth::isAdmin($user)) { 92 Site::setPreference('DEFAULT_COLOR_PALETTE', $palette); 93 } 94 95 Session::put('palette', $palette); 96 97 return response(); 98 } 99 100 /** 101 * A list of CSS files to include for this page. 102 * 103 * @return array<string> 104 */ 105 public function stylesheets(): array 106 { 107 return [ 108 asset('css/colors.min.css'), 109 asset('css/colors/' . $this->palette() . '.min.css'), 110 ]; 111 } 112 113 /** 114 * Create a menu of palette options 115 * 116 * @return Menu 117 */ 118 protected function menuPalette(): Menu 119 { 120 /* I18N: A colour scheme */ 121 $menu = new Menu(I18N::translate('Palette'), '#', 'menu-color'); 122 123 $palette = $this->palette(); 124 125 foreach ($this->palettes() as $palette_id => $palette_name) { 126 $url = route('module', ['module' => $this->name(), 'action' => 'Palette', 'palette' => $palette_id]); 127 128 $submenu = new Menu( 129 $palette_name, 130 '#', 131 'menu-color-' . $palette_id . ($palette === $palette_id ? ' active' : ''), 132 [ 133 'data-wt-post-url' => $url, 134 ] 135 ); 136 137 $menu->addSubmenu($submenu); 138 } 139 140 return $menu; 141 } 142 143 /** 144 * @return array<string> 145 */ 146 private function palettes(): array 147 { 148 $palettes = [ 149 /* I18N: The name of a colour-scheme */ 150 'aquamarine' => I18N::translate('Aqua Marine'), 151 /* I18N: The name of a colour-scheme */ 152 'ash' => I18N::translate('Ash'), 153 /* I18N: The name of a colour-scheme */ 154 'belgianchocolate' => I18N::translate('Belgian Chocolate'), 155 /* I18N: The name of a colour-scheme */ 156 'bluelagoon' => I18N::translate('Blue Lagoon'), 157 /* I18N: The name of a colour-scheme */ 158 'bluemarine' => I18N::translate('Blue Marine'), 159 /* I18N: The name of a colour-scheme */ 160 'coffeeandcream' => I18N::translate('Coffee and Cream'), 161 /* I18N: The name of a colour-scheme */ 162 'coldday' => I18N::translate('Cold Day'), 163 /* I18N: The name of a colour-scheme */ 164 'greenbeam' => I18N::translate('Green Beam'), 165 /* I18N: The name of a colour-scheme */ 166 'mediterranio' => I18N::translate('Mediterranio'), 167 /* I18N: The name of a colour-scheme */ 168 'mercury' => I18N::translate('Mercury'), 169 /* I18N: The name of a colour-scheme */ 170 'nocturnal' => I18N::translate('Nocturnal'), 171 /* I18N: The name of a colour-scheme */ 172 'olivia' => I18N::translate('Olivia'), 173 /* I18N: The name of a colour-scheme */ 174 'pinkplastic' => I18N::translate('Pink Plastic'), 175 /* I18N: The name of a colour-scheme */ 176 'sage' => I18N::translate('Sage'), 177 /* I18N: The name of a colour-scheme */ 178 'shinytomato' => I18N::translate('Shiny Tomato'), 179 /* I18N: The name of a colour-scheme */ 180 'tealtop' => I18N::translate('Teal Top'), 181 ]; 182 183 uasort($palettes, I18N::comparator()); 184 185 return $palettes; 186 } 187 188 /** 189 * @return string 190 */ 191 private function palette(): string 192 { 193 // If we are logged in, use our preference 194 $palette = Auth::user()->getPreference('themecolor'); 195 196 // If not logged in or no preference, use one we selected earlier in the session. 197 if ($palette === '') { 198 $palette = Session::get('palette'); 199 $palette = is_string($palette) ? $palette : ''; 200 } 201 202 // We haven't selected one this session? Use the site default 203 if ($palette === '') { 204 $palette = Site::getPreference('DEFAULT_COLOR_PALETTE'); 205 } 206 207 if ($palette === '') { 208 $palette = self::DEFAULT_PALETTE; 209 } 210 211 return $palette; 212 } 213} 214