1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2021 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\Contracts\UserInterface; 24use Fisharebest\Webtrees\I18N; 25use Fisharebest\Webtrees\Menu; 26use Fisharebest\Webtrees\Session; 27use Fisharebest\Webtrees\Site; 28use Fisharebest\Webtrees\Tree; 29use Psr\Http\Message\ResponseInterface; 30use Psr\Http\Message\ServerRequestInterface; 31 32use function assert; 33use function asset; 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 Menu[] 62 */ 63 public function userMenu(?Tree $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 = $request->getAttribute('user'); 86 assert($user instanceof UserInterface); 87 88 $palette = $request->getQueryParams()['palette']; 89 assert(array_key_exists($palette, $this->palettes())); 90 91 $user->setPreference('themecolor', $palette); 92 93 // If we are the admin, then use our selection as the site default. 94 if (Auth::isAdmin($user)) { 95 Site::setPreference('DEFAULT_COLOR_PALETTE', $palette); 96 } 97 98 Session::put('palette', $palette); 99 100 return response(); 101 } 102 103 /** 104 * A list of CSS files to include for this page. 105 * 106 * @return array<string> 107 */ 108 public function stylesheets(): array 109 { 110 return [ 111 asset('css/colors.min.css'), 112 asset('css/colors/' . $this->palette() . '.min.css'), 113 ]; 114 } 115 116 /** 117 * Create a menu of palette options 118 * 119 * @return Menu 120 */ 121 protected function menuPalette(): Menu 122 { 123 /* I18N: A colour scheme */ 124 $menu = new Menu(I18N::translate('Palette'), '#', 'menu-color'); 125 126 $palette = $this->palette(); 127 128 foreach ($this->palettes() as $palette_id => $palette_name) { 129 $url = route('module', ['module' => $this->name(), 'action' => 'Palette', 'palette' => $palette_id]); 130 131 $submenu = new Menu( 132 $palette_name, 133 '#', 134 'menu-color-' . $palette_id . ($palette === $palette_id ? ' active' : ''), 135 [ 136 'data-post-url' => $url, 137 ] 138 ); 139 140 $menu->addSubmenu($submenu); 141 } 142 143 return $menu; 144 } 145 146 /** 147 * @return array<string> 148 */ 149 private function palettes(): array 150 { 151 $palettes = [ 152 /* I18N: The name of a colour-scheme */ 153 'aquamarine' => I18N::translate('Aqua Marine'), 154 /* I18N: The name of a colour-scheme */ 155 'ash' => I18N::translate('Ash'), 156 /* I18N: The name of a colour-scheme */ 157 'belgianchocolate' => I18N::translate('Belgian Chocolate'), 158 /* I18N: The name of a colour-scheme */ 159 'bluelagoon' => I18N::translate('Blue Lagoon'), 160 /* I18N: The name of a colour-scheme */ 161 'bluemarine' => I18N::translate('Blue Marine'), 162 /* I18N: The name of a colour-scheme */ 163 'coffeeandcream' => I18N::translate('Coffee and Cream'), 164 /* I18N: The name of a colour-scheme */ 165 'coldday' => I18N::translate('Cold Day'), 166 /* I18N: The name of a colour-scheme */ 167 'greenbeam' => I18N::translate('Green Beam'), 168 /* I18N: The name of a colour-scheme */ 169 'mediterranio' => I18N::translate('Mediterranio'), 170 /* I18N: The name of a colour-scheme */ 171 'mercury' => I18N::translate('Mercury'), 172 /* I18N: The name of a colour-scheme */ 173 'nocturnal' => I18N::translate('Nocturnal'), 174 /* I18N: The name of a colour-scheme */ 175 'olivia' => I18N::translate('Olivia'), 176 /* I18N: The name of a colour-scheme */ 177 'pinkplastic' => I18N::translate('Pink Plastic'), 178 /* I18N: The name of a colour-scheme */ 179 'sage' => I18N::translate('Sage'), 180 /* I18N: The name of a colour-scheme */ 181 'shinytomato' => I18N::translate('Shiny Tomato'), 182 /* I18N: The name of a colour-scheme */ 183 'tealtop' => I18N::translate('Teal Top'), 184 ]; 185 186 uasort($palettes, I18N::comparator()); 187 188 return $palettes; 189 } 190 191 /** 192 * @return string 193 */ 194 private function palette(): string 195 { 196 // If we are logged in, use our preference 197 $palette = Auth::user()->getPreference('themecolor', ''); 198 199 // If not logged in or no preference, use one we selected earlier in the session. 200 if ($palette === '') { 201 $palette = Session::get('palette', ''); 202 } 203 204 // We haven't selected one this session? Use the site default 205 if ($palette === '') { 206 $palette = Site::getPreference('DEFAULT_COLOR_PALETTE', self::DEFAULT_PALETTE); 207 } 208 209 return $palette; 210 } 211} 212