ThemesService.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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. // Register themes
  33. $this->themesProviders = [
  34. $defaultTheme->getId() => $defaultTheme,
  35. $lightTheme->getId() => $lightTheme,
  36. $darkTheme->getId() => $darkTheme,
  37. $highContrastTheme->getId() => $highContrastTheme,
  38. $darkHighContrastTheme->getId() => $darkHighContrastTheme,
  39. $dyslexiaFont->getId() => $dyslexiaFont,
  40. ];
  41. }
  42. /**
  43. * Get the list of all registered themes
  44. *
  45. * @return ITheme[]
  46. */
  47. public function getThemes(): array {
  48. // Enforced theme if configured
  49. $enforcedTheme = $this->config->getSystemValueString('enforce_theme', '');
  50. if ($enforcedTheme !== '') {
  51. if (!isset($this->themesProviders[$enforcedTheme])) {
  52. $this->logger->error('Enforced theme not found', ['theme' => $enforcedTheme]);
  53. return $this->themesProviders;
  54. }
  55. $defaultTheme = $this->themesProviders[$this->defaultTheme->getId()];
  56. $darkTheme = $this->themesProviders[$this->darkTheme->getId()];
  57. $theme = $this->themesProviders[$enforcedTheme];
  58. return [
  59. // Leave the default theme as a fallback
  60. $defaultTheme->getId() => $defaultTheme,
  61. // Make sure we also have the dark theme to allow apps
  62. // to scope sections of their UI to the dark theme
  63. $darkTheme->getId() => $darkTheme,
  64. // Finally, the enforced theme
  65. $theme->getId() => $theme,
  66. ];
  67. }
  68. return $this->themesProviders;
  69. }
  70. /**
  71. * Enable a theme for the logged-in user
  72. *
  73. * @param ITheme $theme the theme to enable
  74. * @return string[] the enabled themes
  75. */
  76. public function enableTheme(ITheme $theme): array {
  77. $themesIds = $this->getEnabledThemes();
  78. // If already enabled, ignore
  79. if (in_array($theme->getId(), $themesIds)) {
  80. return $themesIds;
  81. }
  82. /** @var ITheme[] */
  83. $themes = array_filter(array_map(function ($themeId) {
  84. return $this->getThemes()[$themeId];
  85. }, $themesIds));
  86. // Filtering all themes with the same type
  87. $filteredThemes = array_filter($themes, function (ITheme $t) use ($theme) {
  88. return $theme->getType() === $t->getType();
  89. });
  90. // Retrieve IDs only
  91. /** @var string[] */
  92. $filteredThemesIds = array_map(function (ITheme $t) {
  93. return $t->getId();
  94. }, array_values($filteredThemes));
  95. $enabledThemes = array_merge(array_diff($themesIds, $filteredThemesIds), [$theme->getId()]);
  96. $this->setEnabledThemes($enabledThemes);
  97. return $enabledThemes;
  98. }
  99. /**
  100. * Disable a theme for the logged-in user
  101. *
  102. * @param ITheme $theme the theme to disable
  103. * @return string[] the enabled themes
  104. */
  105. public function disableTheme(ITheme $theme): array {
  106. $themesIds = $this->getEnabledThemes();
  107. // If enabled, removing it
  108. if (in_array($theme->getId(), $themesIds)) {
  109. $enabledThemes = array_diff($themesIds, [$theme->getId()]);
  110. $this->setEnabledThemes($enabledThemes);
  111. return $enabledThemes;
  112. }
  113. return $themesIds;
  114. }
  115. /**
  116. * Check whether a theme is enabled or not
  117. * for the logged-in user
  118. *
  119. * @return bool
  120. */
  121. public function isEnabled(ITheme $theme): bool {
  122. $user = $this->userSession->getUser();
  123. if ($user instanceof IUser) {
  124. // Using keys as it's faster
  125. $themes = $this->getEnabledThemes();
  126. return in_array($theme->getId(), $themes);
  127. }
  128. return false;
  129. }
  130. /**
  131. * Get the list of all enabled themes IDs
  132. * for the logged-in user
  133. *
  134. * @return string[]
  135. */
  136. public function getEnabledThemes(): array {
  137. $user = $this->userSession->getUser();
  138. if ($user === null) {
  139. return [];
  140. }
  141. $enforcedTheme = $this->config->getSystemValueString('enforce_theme', '');
  142. $enabledThemes = json_decode($this->config->getUserValue($user->getUID(), Application::APP_ID, 'enabled-themes', '[]'));
  143. if ($enforcedTheme !== '') {
  144. return array_merge([$enforcedTheme], $enabledThemes);
  145. }
  146. try {
  147. return $enabledThemes;
  148. } catch (\Exception $e) {
  149. return [];
  150. }
  151. }
  152. /**
  153. * Set the list of enabled themes
  154. * for the logged-in user
  155. *
  156. * @param string[] $themes the list of enabled themes IDs
  157. */
  158. private function setEnabledThemes(array $themes): void {
  159. $user = $this->userSession->getUser();
  160. $this->config->setUserValue($user->getUID(), Application::APP_ID, 'enabled-themes', json_encode(array_values(array_unique($themes))));
  161. }
  162. }