ThemesService.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-License-Identifier: AGPL-3.0-or-later
  5. */
  6. namespace OCA\Theming\Service;
  7. use OCA\Theming\AppInfo\Application;
  8. use OCA\Theming\ITheme;
  9. use OCA\Theming\Themes\DarkHighContrastTheme;
  10. use OCA\Theming\Themes\DarkTheme;
  11. use OCA\Theming\Themes\DefaultTheme;
  12. use OCA\Theming\Themes\DyslexiaFont;
  13. use OCA\Theming\Themes\HighContrastTheme;
  14. use OCA\Theming\Themes\LightTheme;
  15. use OCP\IConfig;
  16. use OCP\IUser;
  17. use OCP\IUserSession;
  18. use Psr\Log\LoggerInterface;
  19. class ThemesService {
  20. /** @var ITheme[] */
  21. private array $themesProviders;
  22. public function __construct(
  23. private IUserSession $userSession,
  24. private IConfig $config,
  25. private LoggerInterface $logger,
  26. private DefaultTheme $defaultTheme,
  27. LightTheme $lightTheme,
  28. private DarkTheme $darkTheme,
  29. HighContrastTheme $highContrastTheme,
  30. DarkHighContrastTheme $darkHighContrastTheme,
  31. DyslexiaFont $dyslexiaFont,
  32. ) {
  33. // Register themes
  34. $this->themesProviders = [
  35. $defaultTheme->getId() => $defaultTheme,
  36. $lightTheme->getId() => $lightTheme,
  37. $darkTheme->getId() => $darkTheme,
  38. $highContrastTheme->getId() => $highContrastTheme,
  39. $darkHighContrastTheme->getId() => $darkHighContrastTheme,
  40. $dyslexiaFont->getId() => $dyslexiaFont,
  41. ];
  42. }
  43. /**
  44. * Get the list of all registered themes
  45. *
  46. * @return ITheme[]
  47. */
  48. public function getThemes(): array {
  49. // Enforced theme if configured
  50. $enforcedTheme = $this->config->getSystemValueString('enforce_theme', '');
  51. if ($enforcedTheme !== '') {
  52. if (!isset($this->themesProviders[$enforcedTheme])) {
  53. $this->logger->error('Enforced theme not found', ['theme' => $enforcedTheme]);
  54. return $this->themesProviders;
  55. }
  56. $defaultTheme = $this->themesProviders[$this->defaultTheme->getId()];
  57. $darkTheme = $this->themesProviders[$this->darkTheme->getId()];
  58. $theme = $this->themesProviders[$enforcedTheme];
  59. return [
  60. // Leave the default theme as a fallback
  61. $defaultTheme->getId() => $defaultTheme,
  62. // Make sure we also have the dark theme to allow apps
  63. // to scope sections of their UI to the dark theme
  64. $darkTheme->getId() => $darkTheme,
  65. // Finally, the enforced theme
  66. $theme->getId() => $theme,
  67. ];
  68. }
  69. return $this->themesProviders;
  70. }
  71. /**
  72. * Enable a theme for the logged-in user
  73. *
  74. * @param ITheme $theme the theme to enable
  75. * @return string[] the enabled themes
  76. */
  77. public function enableTheme(ITheme $theme): array {
  78. $themesIds = $this->getEnabledThemes();
  79. // If already enabled, ignore
  80. if (in_array($theme->getId(), $themesIds)) {
  81. return $themesIds;
  82. }
  83. /** @var ITheme[] */
  84. $themes = array_filter(array_map(function ($themeId) {
  85. return $this->getThemes()[$themeId];
  86. }, $themesIds));
  87. // Filtering all themes with the same type
  88. $filteredThemes = array_filter($themes, function (ITheme $t) use ($theme) {
  89. return $theme->getType() === $t->getType();
  90. });
  91. // Retrieve IDs only
  92. /** @var string[] */
  93. $filteredThemesIds = array_map(function (ITheme $t) {
  94. return $t->getId();
  95. }, array_values($filteredThemes));
  96. $enabledThemes = array_merge(array_diff($themesIds, $filteredThemesIds), [$theme->getId()]);
  97. $this->setEnabledThemes($enabledThemes);
  98. return $enabledThemes;
  99. }
  100. /**
  101. * Disable a theme for the logged-in user
  102. *
  103. * @param ITheme $theme the theme to disable
  104. * @return string[] the enabled themes
  105. */
  106. public function disableTheme(ITheme $theme): array {
  107. $themesIds = $this->getEnabledThemes();
  108. // If enabled, removing it
  109. if (in_array($theme->getId(), $themesIds)) {
  110. $enabledThemes = array_diff($themesIds, [$theme->getId()]);
  111. $this->setEnabledThemes($enabledThemes);
  112. return $enabledThemes;
  113. }
  114. return $themesIds;
  115. }
  116. /**
  117. * Check whether a theme is enabled or not
  118. * for the logged-in user
  119. *
  120. * @return bool
  121. */
  122. public function isEnabled(ITheme $theme): bool {
  123. $user = $this->userSession->getUser();
  124. if ($user instanceof IUser) {
  125. // Using keys as it's faster
  126. $themes = $this->getEnabledThemes();
  127. return in_array($theme->getId(), $themes);
  128. }
  129. return false;
  130. }
  131. /**
  132. * Get the list of all enabled themes IDs
  133. * for the logged-in user
  134. *
  135. * @return string[]
  136. */
  137. public function getEnabledThemes(): array {
  138. $user = $this->userSession->getUser();
  139. if ($user === null) {
  140. return [];
  141. }
  142. $enforcedTheme = $this->config->getSystemValueString('enforce_theme', '');
  143. $enabledThemes = json_decode($this->config->getUserValue($user->getUID(), Application::APP_ID, 'enabled-themes', '["default"]'));
  144. if ($enforcedTheme !== '') {
  145. return array_merge([$enforcedTheme], $enabledThemes);
  146. }
  147. try {
  148. return $enabledThemes;
  149. } catch (\Exception $e) {
  150. return [];
  151. }
  152. }
  153. /**
  154. * Set the list of enabled themes
  155. * for the logged-in user
  156. *
  157. * @param string[] $themes the list of enabled themes IDs
  158. */
  159. private function setEnabledThemes(array $themes): void {
  160. $user = $this->userSession->getUser();
  161. $this->config->setUserValue($user->getUID(), Application::APP_ID, 'enabled-themes', json_encode(array_values(array_unique($themes))));
  162. }
  163. }