ThemesService.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2022 John Molakvoæ <skjnldsv@protonmail.com>
  4. *
  5. * @author John Molakvoæ <skjnldsv@protonmail.com>
  6. *
  7. * @license GNU AGPL version 3 or any later version
  8. *
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Affero General Public License as
  11. * published by the Free Software Foundation, either version 3 of the
  12. * License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Affero General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Affero General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. *
  22. */
  23. namespace OCA\Theming\Service;
  24. use OCA\Theming\AppInfo\Application;
  25. use OCA\Theming\ITheme;
  26. use OCA\Theming\Themes\DarkHighContrastTheme;
  27. use OCA\Theming\Themes\DarkTheme;
  28. use OCA\Theming\Themes\DefaultTheme;
  29. use OCA\Theming\Themes\DyslexiaFont;
  30. use OCA\Theming\Themes\HighContrastTheme;
  31. use OCA\Theming\Themes\LightTheme;
  32. use OCP\IConfig;
  33. use OCP\IUser;
  34. use OCP\IUserSession;
  35. use Psr\Log\LoggerInterface;
  36. class ThemesService {
  37. /** @var ITheme[] */
  38. private array $themesProviders;
  39. public function __construct(
  40. private IUserSession $userSession,
  41. private IConfig $config,
  42. private LoggerInterface $logger,
  43. private DefaultTheme $defaultTheme,
  44. LightTheme $lightTheme,
  45. private DarkTheme $darkTheme,
  46. HighContrastTheme $highContrastTheme,
  47. DarkHighContrastTheme $darkHighContrastTheme,
  48. DyslexiaFont $dyslexiaFont) {
  49. // Register themes
  50. $this->themesProviders = [
  51. $defaultTheme->getId() => $defaultTheme,
  52. $lightTheme->getId() => $lightTheme,
  53. $darkTheme->getId() => $darkTheme,
  54. $highContrastTheme->getId() => $highContrastTheme,
  55. $darkHighContrastTheme->getId() => $darkHighContrastTheme,
  56. $dyslexiaFont->getId() => $dyslexiaFont,
  57. ];
  58. }
  59. /**
  60. * Get the list of all registered themes
  61. *
  62. * @return ITheme[]
  63. */
  64. public function getThemes(): array {
  65. // Enforced theme if configured
  66. $enforcedTheme = $this->config->getSystemValueString('enforce_theme', '');
  67. if ($enforcedTheme !== '') {
  68. if (!isset($this->themesProviders[$enforcedTheme])) {
  69. $this->logger->error('Enforced theme not found', ['theme' => $enforcedTheme]);
  70. return $this->themesProviders;
  71. }
  72. $defaultTheme = $this->themesProviders[$this->defaultTheme->getId()];
  73. $darkTheme = $this->themesProviders[$this->darkTheme->getId()];
  74. $theme = $this->themesProviders[$enforcedTheme];
  75. return [
  76. // Leave the default theme as a fallback
  77. $defaultTheme->getId() => $defaultTheme,
  78. // Make sure we also have the dark theme to allow apps
  79. // to scope sections of their UI to the dark theme
  80. $darkTheme->getId() => $darkTheme,
  81. // Finally, the enforced theme
  82. $theme->getId() => $theme,
  83. ];
  84. }
  85. return $this->themesProviders;
  86. }
  87. /**
  88. * Enable a theme for the logged-in user
  89. *
  90. * @param ITheme $theme the theme to enable
  91. * @return string[] the enabled themes
  92. */
  93. public function enableTheme(ITheme $theme): array {
  94. $themesIds = $this->getEnabledThemes();
  95. // If already enabled, ignore
  96. if (in_array($theme->getId(), $themesIds)) {
  97. return $themesIds;
  98. }
  99. /** @var ITheme[] */
  100. $themes = array_filter(array_map(function ($themeId) {
  101. return $this->getThemes()[$themeId];
  102. }, $themesIds));
  103. // Filtering all themes with the same type
  104. $filteredThemes = array_filter($themes, function (ITheme $t) use ($theme) {
  105. return $theme->getType() === $t->getType();
  106. });
  107. // Retrieve IDs only
  108. /** @var string[] */
  109. $filteredThemesIds = array_map(function (ITheme $t) {
  110. return $t->getId();
  111. }, array_values($filteredThemes));
  112. $enabledThemes = array_merge(array_diff($themesIds, $filteredThemesIds), [$theme->getId()]);
  113. $this->setEnabledThemes($enabledThemes);
  114. return $enabledThemes;
  115. }
  116. /**
  117. * Disable a theme for the logged-in user
  118. *
  119. * @param ITheme $theme the theme to disable
  120. * @return string[] the enabled themes
  121. */
  122. public function disableTheme(ITheme $theme): array {
  123. $themesIds = $this->getEnabledThemes();
  124. // If enabled, removing it
  125. if (in_array($theme->getId(), $themesIds)) {
  126. $enabledThemes = array_diff($themesIds, [$theme->getId()]);
  127. $this->setEnabledThemes($enabledThemes);
  128. return $enabledThemes;
  129. }
  130. return $themesIds;
  131. }
  132. /**
  133. * Check whether a theme is enabled or not
  134. * for the logged-in user
  135. *
  136. * @return bool
  137. */
  138. public function isEnabled(ITheme $theme): bool {
  139. $user = $this->userSession->getUser();
  140. if ($user instanceof IUser) {
  141. // Using keys as it's faster
  142. $themes = $this->getEnabledThemes();
  143. return in_array($theme->getId(), $themes);
  144. }
  145. return false;
  146. }
  147. /**
  148. * Get the list of all enabled themes IDs
  149. * for the logged-in user
  150. *
  151. * @return string[]
  152. */
  153. public function getEnabledThemes(): array {
  154. $user = $this->userSession->getUser();
  155. if ($user === null) {
  156. return [];
  157. }
  158. $enforcedTheme = $this->config->getSystemValueString('enforce_theme', '');
  159. $enabledThemes = json_decode($this->config->getUserValue($user->getUID(), Application::APP_ID, 'enabled-themes', '[]'));
  160. if ($enforcedTheme !== '') {
  161. return array_merge([$enforcedTheme], $enabledThemes);
  162. }
  163. try {
  164. return $enabledThemes;
  165. } catch (\Exception $e) {
  166. return [];
  167. }
  168. }
  169. /**
  170. * Set the list of enabled themes
  171. * for the logged-in user
  172. *
  173. * @param string[] $themes the list of enabled themes IDs
  174. */
  175. private function setEnabledThemes(array $themes): void {
  176. $user = $this->userSession->getUser();
  177. $this->config->setUserValue($user->getUID(), Application::APP_ID, 'enabled-themes', json_encode(array_values(array_unique($themes))));
  178. }
  179. }