@@ -38,6 +38,7 @@ public function __construct(
3838 * availableLanguages: array<string, string>,
3939 * enabledFeatures: array<string, bool>,
4040 * publicLogoUrl: string,
41+ * themeColors: array<string, array<string, string>>,
4142 * oauthDiscovery: array<string, bool|string|string[]>
4243 * }
4344 */
@@ -50,6 +51,7 @@ public function getPublicMetadata(): array
5051 'availableLanguages ' => LanguageHelper::getAvailableLanguages (),
5152 'enabledFeatures ' => $ this ->buildEnabledFeatures (),
5253 'publicLogoUrl ' => $ this ->buildPublicLogoUrl (),
54+ 'themeColors ' => $ this ->buildThemeColors (),
5355 'oauthDiscovery ' => $ this ->oAuthDiscoveryService ->getMetaDiscovery (),
5456 ];
5557 }
@@ -76,6 +78,61 @@ private function buildPublicLogoUrl(): string
7678 return rtrim ($ this ->configuration ->getDefaultUrl (), characters: '/ ' ) . '/assets/images/logo-transparent.svg ' ;
7779 }
7880
81+ /**
82+ * @return array<string, array<string, string>>
83+ */
84+ private function buildThemeColors (): array
85+ {
86+ $ themeCssPath = PMF_ROOT_DIR . '/assets/templates/default/theme.css ' ;
87+ if (!is_readable ($ themeCssPath )) {
88+ return [
89+ 'light ' => [],
90+ 'dark ' => [],
91+ 'highContrast ' => [],
92+ ];
93+ }
94+
95+ $ themeCss = file_get_contents ($ themeCssPath );
96+ if ($ themeCss === false ) {
97+ return [
98+ 'light ' => [],
99+ 'dark ' => [],
100+ 'highContrast ' => [],
101+ ];
102+ }
103+
104+ return [
105+ 'light ' => $ this ->extractThemeVariables ($ themeCss , ":root, \n[data-bs-theme='light'] " ),
106+ 'dark ' => $ this ->extractThemeVariables ($ themeCss , "[data-bs-theme='dark'] " ),
107+ 'highContrast ' => $ this ->extractThemeVariables ($ themeCss , "[data-bs-theme='high-contrast'] " ),
108+ ];
109+ }
110+
111+ /**
112+ * @return array<string, string>
113+ */
114+ private function extractThemeVariables (string $ themeCss , string $ selector ): array
115+ {
116+ $ pattern = sprintf ('/%s\s*\{(?P<body>.*?)^\}/ms ' , preg_quote ($ selector , delimiter: '/ ' ));
117+ if (preg_match ($ pattern , $ themeCss , $ matches ) !== 1 ) {
118+ return [];
119+ }
120+
121+ preg_match_all (
122+ '/(?P<name>--[A-Za-z0-9\-]+)\s*:\s*(?P<value>[^;]+);/ ' ,
123+ $ matches ['body ' ],
124+ $ variableMatches ,
125+ PREG_SET_ORDER ,
126+ );
127+
128+ $ variables = [];
129+ foreach ($ variableMatches as $ variableMatch ) {
130+ $ variables [$ variableMatch ['name ' ]] = trim ($ variableMatch ['value ' ]);
131+ }
132+
133+ return $ variables ;
134+ }
135+
79136 private function toBool (mixed $ value ): bool
80137 {
81138 return $ value === true || $ value === 1 || $ value === '1 ' || $ value === 'true ' ;
0 commit comments