Completed
Push — master ( c4b9e9...703af4 )
by John
19:03 queued 16s
created
apps/theming/lib/Controller/ThemingController.php 2 patches
Indentation   +418 added lines, -418 removed lines patch added patch discarded remove patch
@@ -41,447 +41,447 @@
 block discarded – undo
41 41
  * @package OCA\Theming\Controller
42 42
  */
43 43
 class ThemingController extends Controller {
44
-	public const VALID_UPLOAD_KEYS = ['header', 'logo', 'logoheader', 'background', 'favicon'];
44
+    public const VALID_UPLOAD_KEYS = ['header', 'logo', 'logoheader', 'background', 'favicon'];
45 45
 
46
-	public function __construct(
47
-		string $appName,
48
-		IRequest $request,
49
-		private IConfig $config,
50
-		private IAppConfig $appConfig,
51
-		private ThemingDefaults $themingDefaults,
52
-		private IL10N $l10n,
53
-		private IURLGenerator $urlGenerator,
54
-		private IAppManager $appManager,
55
-		private ImageManager $imageManager,
56
-		private ThemesService $themesService,
57
-		private INavigationManager $navigationManager,
58
-	) {
59
-		parent::__construct($appName, $request);
60
-	}
46
+    public function __construct(
47
+        string $appName,
48
+        IRequest $request,
49
+        private IConfig $config,
50
+        private IAppConfig $appConfig,
51
+        private ThemingDefaults $themingDefaults,
52
+        private IL10N $l10n,
53
+        private IURLGenerator $urlGenerator,
54
+        private IAppManager $appManager,
55
+        private ImageManager $imageManager,
56
+        private ThemesService $themesService,
57
+        private INavigationManager $navigationManager,
58
+    ) {
59
+        parent::__construct($appName, $request);
60
+    }
61 61
 
62
-	/**
63
-	 * @param string $setting
64
-	 * @param string $value
65
-	 * @return DataResponse
66
-	 * @throws NotPermittedException
67
-	 */
68
-	#[AuthorizedAdminSetting(settings: Admin::class)]
69
-	public function updateStylesheet($setting, $value) {
70
-		$value = trim($value);
71
-		$error = null;
72
-		$saved = false;
73
-		switch ($setting) {
74
-			case 'name':
75
-				if (strlen($value) > 250) {
76
-					$error = $this->l10n->t('The given name is too long');
77
-				}
78
-				break;
79
-			case 'url':
80
-				if (strlen($value) > 500) {
81
-					$error = $this->l10n->t('The given web address is too long');
82
-				}
83
-				if (!$this->isValidUrl($value)) {
84
-					$error = $this->l10n->t('The given web address is not a valid URL');
85
-				}
86
-				break;
87
-			case 'imprintUrl':
88
-				if (strlen($value) > 500) {
89
-					$error = $this->l10n->t('The given legal notice address is too long');
90
-				}
91
-				if (!$this->isValidUrl($value)) {
92
-					$error = $this->l10n->t('The given legal notice address is not a valid URL');
93
-				}
94
-				break;
95
-			case 'privacyUrl':
96
-				if (strlen($value) > 500) {
97
-					$error = $this->l10n->t('The given privacy policy address is too long');
98
-				}
99
-				if (!$this->isValidUrl($value)) {
100
-					$error = $this->l10n->t('The given privacy policy address is not a valid URL');
101
-				}
102
-				break;
103
-			case 'slogan':
104
-				if (strlen($value) > 500) {
105
-					$error = $this->l10n->t('The given slogan is too long');
106
-				}
107
-				break;
108
-			case 'primary_color':
109
-				if (!preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $value)) {
110
-					$error = $this->l10n->t('The given color is invalid');
111
-				} else {
112
-					$this->appConfig->setAppValueString('primary_color', $value);
113
-					$saved = true;
114
-				}
115
-				break;
116
-			case 'background_color':
117
-				if (!preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $value)) {
118
-					$error = $this->l10n->t('The given color is invalid');
119
-				} else {
120
-					$this->appConfig->setAppValueString('background_color', $value);
121
-					$saved = true;
122
-				}
123
-				break;
124
-			case 'disable-user-theming':
125
-				if (!in_array($value, ['yes', 'true', 'no', 'false'])) {
126
-					$error = $this->l10n->t('Disable-user-theming should be true or false');
127
-				} else {
128
-					$this->appConfig->setAppValueBool('disable-user-theming', $value === 'yes' || $value === 'true');
129
-					$saved = true;
130
-				}
131
-				break;
132
-		}
133
-		if ($error !== null) {
134
-			return new DataResponse([
135
-				'data' => [
136
-					'message' => $error,
137
-				],
138
-				'status' => 'error'
139
-			], Http::STATUS_BAD_REQUEST);
140
-		}
62
+    /**
63
+     * @param string $setting
64
+     * @param string $value
65
+     * @return DataResponse
66
+     * @throws NotPermittedException
67
+     */
68
+    #[AuthorizedAdminSetting(settings: Admin::class)]
69
+    public function updateStylesheet($setting, $value) {
70
+        $value = trim($value);
71
+        $error = null;
72
+        $saved = false;
73
+        switch ($setting) {
74
+            case 'name':
75
+                if (strlen($value) > 250) {
76
+                    $error = $this->l10n->t('The given name is too long');
77
+                }
78
+                break;
79
+            case 'url':
80
+                if (strlen($value) > 500) {
81
+                    $error = $this->l10n->t('The given web address is too long');
82
+                }
83
+                if (!$this->isValidUrl($value)) {
84
+                    $error = $this->l10n->t('The given web address is not a valid URL');
85
+                }
86
+                break;
87
+            case 'imprintUrl':
88
+                if (strlen($value) > 500) {
89
+                    $error = $this->l10n->t('The given legal notice address is too long');
90
+                }
91
+                if (!$this->isValidUrl($value)) {
92
+                    $error = $this->l10n->t('The given legal notice address is not a valid URL');
93
+                }
94
+                break;
95
+            case 'privacyUrl':
96
+                if (strlen($value) > 500) {
97
+                    $error = $this->l10n->t('The given privacy policy address is too long');
98
+                }
99
+                if (!$this->isValidUrl($value)) {
100
+                    $error = $this->l10n->t('The given privacy policy address is not a valid URL');
101
+                }
102
+                break;
103
+            case 'slogan':
104
+                if (strlen($value) > 500) {
105
+                    $error = $this->l10n->t('The given slogan is too long');
106
+                }
107
+                break;
108
+            case 'primary_color':
109
+                if (!preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $value)) {
110
+                    $error = $this->l10n->t('The given color is invalid');
111
+                } else {
112
+                    $this->appConfig->setAppValueString('primary_color', $value);
113
+                    $saved = true;
114
+                }
115
+                break;
116
+            case 'background_color':
117
+                if (!preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $value)) {
118
+                    $error = $this->l10n->t('The given color is invalid');
119
+                } else {
120
+                    $this->appConfig->setAppValueString('background_color', $value);
121
+                    $saved = true;
122
+                }
123
+                break;
124
+            case 'disable-user-theming':
125
+                if (!in_array($value, ['yes', 'true', 'no', 'false'])) {
126
+                    $error = $this->l10n->t('Disable-user-theming should be true or false');
127
+                } else {
128
+                    $this->appConfig->setAppValueBool('disable-user-theming', $value === 'yes' || $value === 'true');
129
+                    $saved = true;
130
+                }
131
+                break;
132
+        }
133
+        if ($error !== null) {
134
+            return new DataResponse([
135
+                'data' => [
136
+                    'message' => $error,
137
+                ],
138
+                'status' => 'error'
139
+            ], Http::STATUS_BAD_REQUEST);
140
+        }
141 141
 
142
-		if (!$saved) {
143
-			$this->themingDefaults->set($setting, $value);
144
-		}
142
+        if (!$saved) {
143
+            $this->themingDefaults->set($setting, $value);
144
+        }
145 145
 
146
-		return new DataResponse([
147
-			'data' => [
148
-				'message' => $this->l10n->t('Saved'),
149
-			],
150
-			'status' => 'success'
151
-		]);
152
-	}
146
+        return new DataResponse([
147
+            'data' => [
148
+                'message' => $this->l10n->t('Saved'),
149
+            ],
150
+            'status' => 'success'
151
+        ]);
152
+    }
153 153
 
154
-	/**
155
-	 * @param string $setting
156
-	 * @param mixed $value
157
-	 * @return DataResponse
158
-	 * @throws NotPermittedException
159
-	 */
160
-	#[AuthorizedAdminSetting(settings: Admin::class)]
161
-	public function updateAppMenu($setting, $value) {
162
-		$error = null;
163
-		switch ($setting) {
164
-			case 'defaultApps':
165
-				if (is_array($value)) {
166
-					try {
167
-						$this->navigationManager->setDefaultEntryIds($value);
168
-					} catch (InvalidArgumentException $e) {
169
-						$error = $this->l10n->t('Invalid app given');
170
-					}
171
-				} else {
172
-					$error = $this->l10n->t('Invalid type for setting "defaultApp" given');
173
-				}
174
-				break;
175
-			default:
176
-				$error = $this->l10n->t('Invalid setting key');
177
-		}
178
-		if ($error !== null) {
179
-			return new DataResponse([
180
-				'data' => [
181
-					'message' => $error,
182
-				],
183
-				'status' => 'error'
184
-			], Http::STATUS_BAD_REQUEST);
185
-		}
154
+    /**
155
+     * @param string $setting
156
+     * @param mixed $value
157
+     * @return DataResponse
158
+     * @throws NotPermittedException
159
+     */
160
+    #[AuthorizedAdminSetting(settings: Admin::class)]
161
+    public function updateAppMenu($setting, $value) {
162
+        $error = null;
163
+        switch ($setting) {
164
+            case 'defaultApps':
165
+                if (is_array($value)) {
166
+                    try {
167
+                        $this->navigationManager->setDefaultEntryIds($value);
168
+                    } catch (InvalidArgumentException $e) {
169
+                        $error = $this->l10n->t('Invalid app given');
170
+                    }
171
+                } else {
172
+                    $error = $this->l10n->t('Invalid type for setting "defaultApp" given');
173
+                }
174
+                break;
175
+            default:
176
+                $error = $this->l10n->t('Invalid setting key');
177
+        }
178
+        if ($error !== null) {
179
+            return new DataResponse([
180
+                'data' => [
181
+                    'message' => $error,
182
+                ],
183
+                'status' => 'error'
184
+            ], Http::STATUS_BAD_REQUEST);
185
+        }
186 186
 
187
-		return new DataResponse([
188
-			'data' => [
189
-				'message' => $this->l10n->t('Saved'),
190
-			],
191
-			'status' => 'success'
192
-		]);
193
-	}
187
+        return new DataResponse([
188
+            'data' => [
189
+                'message' => $this->l10n->t('Saved'),
190
+            ],
191
+            'status' => 'success'
192
+        ]);
193
+    }
194 194
 
195
-	/**
196
-	 * Check that a string is a valid http/https url.
197
-	 * Also validates that there is no way for XSS through HTML
198
-	 */
199
-	private function isValidUrl(string $url): bool {
200
-		return ((str_starts_with($url, 'http://') || str_starts_with($url, 'https://'))
201
-			&& filter_var($url, FILTER_VALIDATE_URL) !== false)
202
-			&& !str_contains($url, '"');
203
-	}
195
+    /**
196
+     * Check that a string is a valid http/https url.
197
+     * Also validates that there is no way for XSS through HTML
198
+     */
199
+    private function isValidUrl(string $url): bool {
200
+        return ((str_starts_with($url, 'http://') || str_starts_with($url, 'https://'))
201
+            && filter_var($url, FILTER_VALIDATE_URL) !== false)
202
+            && !str_contains($url, '"');
203
+    }
204 204
 
205
-	/**
206
-	 * @return DataResponse
207
-	 * @throws NotPermittedException
208
-	 */
209
-	#[AuthorizedAdminSetting(settings: Admin::class)]
210
-	public function uploadImage(): DataResponse {
211
-		$key = $this->request->getParam('key');
212
-		if (!in_array($key, self::VALID_UPLOAD_KEYS, true)) {
213
-			return new DataResponse(
214
-				[
215
-					'data' => [
216
-						'message' => 'Invalid key'
217
-					],
218
-					'status' => 'failure',
219
-				],
220
-				Http::STATUS_BAD_REQUEST
221
-			);
222
-		}
223
-		$image = $this->request->getUploadedFile('image');
224
-		$error = null;
225
-		$phpFileUploadErrors = [
226
-			UPLOAD_ERR_OK => $this->l10n->t('The file was uploaded'),
227
-			UPLOAD_ERR_INI_SIZE => $this->l10n->t('The uploaded file exceeds the upload_max_filesize directive in php.ini'),
228
-			UPLOAD_ERR_FORM_SIZE => $this->l10n->t('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form'),
229
-			UPLOAD_ERR_PARTIAL => $this->l10n->t('The file was only partially uploaded'),
230
-			UPLOAD_ERR_NO_FILE => $this->l10n->t('No file was uploaded'),
231
-			UPLOAD_ERR_NO_TMP_DIR => $this->l10n->t('Missing a temporary folder'),
232
-			UPLOAD_ERR_CANT_WRITE => $this->l10n->t('Could not write file to disk'),
233
-			UPLOAD_ERR_EXTENSION => $this->l10n->t('A PHP extension stopped the file upload'),
234
-		];
235
-		if (empty($image)) {
236
-			$error = $this->l10n->t('No file uploaded');
237
-		}
238
-		if (!empty($image) && array_key_exists('error', $image) && $image['error'] !== UPLOAD_ERR_OK) {
239
-			$error = $phpFileUploadErrors[$image['error']];
240
-		}
205
+    /**
206
+     * @return DataResponse
207
+     * @throws NotPermittedException
208
+     */
209
+    #[AuthorizedAdminSetting(settings: Admin::class)]
210
+    public function uploadImage(): DataResponse {
211
+        $key = $this->request->getParam('key');
212
+        if (!in_array($key, self::VALID_UPLOAD_KEYS, true)) {
213
+            return new DataResponse(
214
+                [
215
+                    'data' => [
216
+                        'message' => 'Invalid key'
217
+                    ],
218
+                    'status' => 'failure',
219
+                ],
220
+                Http::STATUS_BAD_REQUEST
221
+            );
222
+        }
223
+        $image = $this->request->getUploadedFile('image');
224
+        $error = null;
225
+        $phpFileUploadErrors = [
226
+            UPLOAD_ERR_OK => $this->l10n->t('The file was uploaded'),
227
+            UPLOAD_ERR_INI_SIZE => $this->l10n->t('The uploaded file exceeds the upload_max_filesize directive in php.ini'),
228
+            UPLOAD_ERR_FORM_SIZE => $this->l10n->t('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form'),
229
+            UPLOAD_ERR_PARTIAL => $this->l10n->t('The file was only partially uploaded'),
230
+            UPLOAD_ERR_NO_FILE => $this->l10n->t('No file was uploaded'),
231
+            UPLOAD_ERR_NO_TMP_DIR => $this->l10n->t('Missing a temporary folder'),
232
+            UPLOAD_ERR_CANT_WRITE => $this->l10n->t('Could not write file to disk'),
233
+            UPLOAD_ERR_EXTENSION => $this->l10n->t('A PHP extension stopped the file upload'),
234
+        ];
235
+        if (empty($image)) {
236
+            $error = $this->l10n->t('No file uploaded');
237
+        }
238
+        if (!empty($image) && array_key_exists('error', $image) && $image['error'] !== UPLOAD_ERR_OK) {
239
+            $error = $phpFileUploadErrors[$image['error']];
240
+        }
241 241
 
242
-		if ($error !== null) {
243
-			return new DataResponse(
244
-				[
245
-					'data' => [
246
-						'message' => $error
247
-					],
248
-					'status' => 'failure',
249
-				],
250
-				Http::STATUS_UNPROCESSABLE_ENTITY
251
-			);
252
-		}
242
+        if ($error !== null) {
243
+            return new DataResponse(
244
+                [
245
+                    'data' => [
246
+                        'message' => $error
247
+                    ],
248
+                    'status' => 'failure',
249
+                ],
250
+                Http::STATUS_UNPROCESSABLE_ENTITY
251
+            );
252
+        }
253 253
 
254
-		try {
255
-			$mime = $this->imageManager->updateImage($key, $image['tmp_name']);
256
-			$this->themingDefaults->set($key . 'Mime', $mime);
257
-		} catch (\Exception $e) {
258
-			return new DataResponse(
259
-				[
260
-					'data' => [
261
-						'message' => $e->getMessage()
262
-					],
263
-					'status' => 'failure',
264
-				],
265
-				Http::STATUS_UNPROCESSABLE_ENTITY
266
-			);
267
-		}
254
+        try {
255
+            $mime = $this->imageManager->updateImage($key, $image['tmp_name']);
256
+            $this->themingDefaults->set($key . 'Mime', $mime);
257
+        } catch (\Exception $e) {
258
+            return new DataResponse(
259
+                [
260
+                    'data' => [
261
+                        'message' => $e->getMessage()
262
+                    ],
263
+                    'status' => 'failure',
264
+                ],
265
+                Http::STATUS_UNPROCESSABLE_ENTITY
266
+            );
267
+        }
268 268
 
269
-		$name = $image['name'];
269
+        $name = $image['name'];
270 270
 
271
-		return new DataResponse(
272
-			[
273
-				'data' =>
274
-					[
275
-						'name' => $name,
276
-						'url' => $this->imageManager->getImageUrl($key),
277
-						'message' => $this->l10n->t('Saved'),
278
-					],
279
-				'status' => 'success'
280
-			]
281
-		);
282
-	}
271
+        return new DataResponse(
272
+            [
273
+                'data' =>
274
+                    [
275
+                        'name' => $name,
276
+                        'url' => $this->imageManager->getImageUrl($key),
277
+                        'message' => $this->l10n->t('Saved'),
278
+                    ],
279
+                'status' => 'success'
280
+            ]
281
+        );
282
+    }
283 283
 
284
-	/**
285
-	 * Revert setting to default value
286
-	 *
287
-	 * @param string $setting setting which should be reverted
288
-	 * @return DataResponse
289
-	 * @throws NotPermittedException
290
-	 */
291
-	#[AuthorizedAdminSetting(settings: Admin::class)]
292
-	public function undo(string $setting): DataResponse {
293
-		$value = $this->themingDefaults->undo($setting);
284
+    /**
285
+     * Revert setting to default value
286
+     *
287
+     * @param string $setting setting which should be reverted
288
+     * @return DataResponse
289
+     * @throws NotPermittedException
290
+     */
291
+    #[AuthorizedAdminSetting(settings: Admin::class)]
292
+    public function undo(string $setting): DataResponse {
293
+        $value = $this->themingDefaults->undo($setting);
294 294
 
295
-		return new DataResponse(
296
-			[
297
-				'data' =>
298
-					[
299
-						'value' => $value,
300
-						'message' => $this->l10n->t('Saved'),
301
-					],
302
-				'status' => 'success'
303
-			]
304
-		);
305
-	}
295
+        return new DataResponse(
296
+            [
297
+                'data' =>
298
+                    [
299
+                        'value' => $value,
300
+                        'message' => $this->l10n->t('Saved'),
301
+                    ],
302
+                'status' => 'success'
303
+            ]
304
+        );
305
+    }
306 306
 
307
-	/**
308
-	 * Revert all theming settings to their default values
309
-	 *
310
-	 * @return DataResponse
311
-	 * @throws NotPermittedException
312
-	 */
313
-	#[AuthorizedAdminSetting(settings: Admin::class)]
314
-	public function undoAll(): DataResponse {
315
-		$this->themingDefaults->undoAll();
316
-		$this->navigationManager->setDefaultEntryIds([]);
307
+    /**
308
+     * Revert all theming settings to their default values
309
+     *
310
+     * @return DataResponse
311
+     * @throws NotPermittedException
312
+     */
313
+    #[AuthorizedAdminSetting(settings: Admin::class)]
314
+    public function undoAll(): DataResponse {
315
+        $this->themingDefaults->undoAll();
316
+        $this->navigationManager->setDefaultEntryIds([]);
317 317
 
318
-		return new DataResponse(
319
-			[
320
-				'data' =>
321
-					[
322
-						'message' => $this->l10n->t('Saved'),
323
-					],
324
-				'status' => 'success'
325
-			]
326
-		);
327
-	}
318
+        return new DataResponse(
319
+            [
320
+                'data' =>
321
+                    [
322
+                        'message' => $this->l10n->t('Saved'),
323
+                    ],
324
+                'status' => 'success'
325
+            ]
326
+        );
327
+    }
328 328
 
329
-	/**
330
-	 * @NoSameSiteCookieRequired
331
-	 *
332
-	 * Get an image
333
-	 *
334
-	 * @param string $key Key of the image
335
-	 * @param bool $useSvg Return image as SVG
336
-	 * @return FileDisplayResponse<Http::STATUS_OK, array{}>|NotFoundResponse<Http::STATUS_NOT_FOUND, array{}>
337
-	 * @throws NotPermittedException
338
-	 *
339
-	 * 200: Image returned
340
-	 * 404: Image not found
341
-	 */
342
-	#[PublicPage]
343
-	#[NoCSRFRequired]
344
-	#[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT)]
345
-	public function getImage(string $key, bool $useSvg = true) {
346
-		try {
347
-			$file = $this->imageManager->getImage($key, $useSvg);
348
-		} catch (NotFoundException $e) {
349
-			return new NotFoundResponse();
350
-		}
329
+    /**
330
+     * @NoSameSiteCookieRequired
331
+     *
332
+     * Get an image
333
+     *
334
+     * @param string $key Key of the image
335
+     * @param bool $useSvg Return image as SVG
336
+     * @return FileDisplayResponse<Http::STATUS_OK, array{}>|NotFoundResponse<Http::STATUS_NOT_FOUND, array{}>
337
+     * @throws NotPermittedException
338
+     *
339
+     * 200: Image returned
340
+     * 404: Image not found
341
+     */
342
+    #[PublicPage]
343
+    #[NoCSRFRequired]
344
+    #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT)]
345
+    public function getImage(string $key, bool $useSvg = true) {
346
+        try {
347
+            $file = $this->imageManager->getImage($key, $useSvg);
348
+        } catch (NotFoundException $e) {
349
+            return new NotFoundResponse();
350
+        }
351 351
 
352
-		$response = new FileDisplayResponse($file);
353
-		$csp = new ContentSecurityPolicy();
354
-		$csp->allowInlineStyle();
355
-		$response->setContentSecurityPolicy($csp);
356
-		$response->cacheFor(3600);
357
-		$response->addHeader('Content-Type', $this->config->getAppValue($this->appName, $key . 'Mime', ''));
358
-		$response->addHeader('Content-Disposition', 'attachment; filename="' . $key . '"');
359
-		if (!$useSvg) {
360
-			$response->addHeader('Content-Type', 'image/png');
361
-		} else {
362
-			$response->addHeader('Content-Type', $this->config->getAppValue($this->appName, $key . 'Mime', ''));
363
-		}
364
-		return $response;
365
-	}
352
+        $response = new FileDisplayResponse($file);
353
+        $csp = new ContentSecurityPolicy();
354
+        $csp->allowInlineStyle();
355
+        $response->setContentSecurityPolicy($csp);
356
+        $response->cacheFor(3600);
357
+        $response->addHeader('Content-Type', $this->config->getAppValue($this->appName, $key . 'Mime', ''));
358
+        $response->addHeader('Content-Disposition', 'attachment; filename="' . $key . '"');
359
+        if (!$useSvg) {
360
+            $response->addHeader('Content-Type', 'image/png');
361
+        } else {
362
+            $response->addHeader('Content-Type', $this->config->getAppValue($this->appName, $key . 'Mime', ''));
363
+        }
364
+        return $response;
365
+    }
366 366
 
367
-	/**
368
-	 * @NoSameSiteCookieRequired
369
-	 * @NoTwoFactorRequired
370
-	 *
371
-	 * Get the CSS stylesheet for a theme
372
-	 *
373
-	 * @param string $themeId ID of the theme
374
-	 * @param bool $plain Let the browser decide the CSS priority
375
-	 * @param bool $withCustomCss Include custom CSS
376
-	 * @return DataDisplayResponse<Http::STATUS_OK, array{Content-Type: 'text/css'}>|NotFoundResponse<Http::STATUS_NOT_FOUND, array{}>
377
-	 *
378
-	 * 200: Stylesheet returned
379
-	 * 404: Theme not found
380
-	 */
381
-	#[PublicPage]
382
-	#[NoCSRFRequired]
383
-	#[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT)]
384
-	public function getThemeStylesheet(string $themeId, bool $plain = false, bool $withCustomCss = false) {
385
-		$themes = $this->themesService->getThemes();
386
-		if (!in_array($themeId, array_keys($themes))) {
387
-			return new NotFoundResponse();
388
-		}
367
+    /**
368
+     * @NoSameSiteCookieRequired
369
+     * @NoTwoFactorRequired
370
+     *
371
+     * Get the CSS stylesheet for a theme
372
+     *
373
+     * @param string $themeId ID of the theme
374
+     * @param bool $plain Let the browser decide the CSS priority
375
+     * @param bool $withCustomCss Include custom CSS
376
+     * @return DataDisplayResponse<Http::STATUS_OK, array{Content-Type: 'text/css'}>|NotFoundResponse<Http::STATUS_NOT_FOUND, array{}>
377
+     *
378
+     * 200: Stylesheet returned
379
+     * 404: Theme not found
380
+     */
381
+    #[PublicPage]
382
+    #[NoCSRFRequired]
383
+    #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT)]
384
+    public function getThemeStylesheet(string $themeId, bool $plain = false, bool $withCustomCss = false) {
385
+        $themes = $this->themesService->getThemes();
386
+        if (!in_array($themeId, array_keys($themes))) {
387
+            return new NotFoundResponse();
388
+        }
389 389
 
390
-		$theme = $themes[$themeId];
391
-		$customCss = $theme->getCustomCss();
390
+        $theme = $themes[$themeId];
391
+        $customCss = $theme->getCustomCss();
392 392
 
393
-		// Generate variables
394
-		$variables = '';
395
-		foreach ($theme->getCSSVariables() as $variable => $value) {
396
-			$variables .= "$variable:$value; ";
397
-		};
393
+        // Generate variables
394
+        $variables = '';
395
+        foreach ($theme->getCSSVariables() as $variable => $value) {
396
+            $variables .= "$variable:$value; ";
397
+        };
398 398
 
399
-		// If plain is set, the browser decides of the css priority
400
-		if ($plain) {
401
-			$css = ":root { $variables } " . $customCss;
402
-		} else {
403
-			// If not set, we'll rely on the body class
404
-			$css = "[data-theme-$themeId] { $variables $customCss }";
405
-		}
399
+        // If plain is set, the browser decides of the css priority
400
+        if ($plain) {
401
+            $css = ":root { $variables } " . $customCss;
402
+        } else {
403
+            // If not set, we'll rely on the body class
404
+            $css = "[data-theme-$themeId] { $variables $customCss }";
405
+        }
406 406
 
407
-		try {
408
-			$response = new DataDisplayResponse($css, Http::STATUS_OK, ['Content-Type' => 'text/css']);
409
-			$response->cacheFor(86400);
410
-			return $response;
411
-		} catch (NotFoundException $e) {
412
-			return new NotFoundResponse();
413
-		}
414
-	}
407
+        try {
408
+            $response = new DataDisplayResponse($css, Http::STATUS_OK, ['Content-Type' => 'text/css']);
409
+            $response->cacheFor(86400);
410
+            return $response;
411
+        } catch (NotFoundException $e) {
412
+            return new NotFoundResponse();
413
+        }
414
+    }
415 415
 
416
-	/**
417
-	 * Get the manifest for an app
418
-	 *
419
-	 * @param string $app ID of the app
420
-	 * @psalm-suppress LessSpecificReturnStatement The content of the Manifest doesn't need to be described in the return type
421
-	 * @return JSONResponse<Http::STATUS_OK, array{name: string, short_name: string, start_url: string, theme_color: string, background_color: string, description: string, icons: list<array{src: non-empty-string, type: string, sizes: string}>, display_override: list<string>, display: string}, array{}>|JSONResponse<Http::STATUS_NOT_FOUND, array{}, array{}>
422
-	 *
423
-	 * 200: Manifest returned
424
-	 * 404: App not found
425
-	 */
426
-	#[PublicPage]
427
-	#[NoCSRFRequired]
428
-	#[BruteForceProtection(action: 'manifest')]
429
-	#[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT)]
430
-	public function getManifest(string $app): JSONResponse {
431
-		$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
432
-		if ($app === 'core' || $app === 'settings') {
433
-			$name = $this->themingDefaults->getName();
434
-			$shortName = $this->themingDefaults->getName();
435
-			$startUrl = $this->urlGenerator->getBaseUrl();
436
-			$description = $this->themingDefaults->getSlogan();
437
-		} else {
438
-			if (!$this->appManager->isEnabledForUser($app)) {
439
-				$response = new JSONResponse([], Http::STATUS_NOT_FOUND);
440
-				$response->throttle(['action' => 'manifest', 'app' => $app]);
441
-				return $response;
442
-			}
416
+    /**
417
+     * Get the manifest for an app
418
+     *
419
+     * @param string $app ID of the app
420
+     * @psalm-suppress LessSpecificReturnStatement The content of the Manifest doesn't need to be described in the return type
421
+     * @return JSONResponse<Http::STATUS_OK, array{name: string, short_name: string, start_url: string, theme_color: string, background_color: string, description: string, icons: list<array{src: non-empty-string, type: string, sizes: string}>, display_override: list<string>, display: string}, array{}>|JSONResponse<Http::STATUS_NOT_FOUND, array{}, array{}>
422
+     *
423
+     * 200: Manifest returned
424
+     * 404: App not found
425
+     */
426
+    #[PublicPage]
427
+    #[NoCSRFRequired]
428
+    #[BruteForceProtection(action: 'manifest')]
429
+    #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT)]
430
+    public function getManifest(string $app): JSONResponse {
431
+        $cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
432
+        if ($app === 'core' || $app === 'settings') {
433
+            $name = $this->themingDefaults->getName();
434
+            $shortName = $this->themingDefaults->getName();
435
+            $startUrl = $this->urlGenerator->getBaseUrl();
436
+            $description = $this->themingDefaults->getSlogan();
437
+        } else {
438
+            if (!$this->appManager->isEnabledForUser($app)) {
439
+                $response = new JSONResponse([], Http::STATUS_NOT_FOUND);
440
+                $response->throttle(['action' => 'manifest', 'app' => $app]);
441
+                return $response;
442
+            }
443 443
 
444
-			$info = $this->appManager->getAppInfo($app, false, $this->l10n->getLanguageCode());
445
-			$name = $info['name'] . ' - ' . $this->themingDefaults->getName();
446
-			$shortName = $info['name'];
447
-			if (str_contains($this->request->getRequestUri(), '/index.php/')) {
448
-				$startUrl = $this->urlGenerator->getBaseUrl() . '/index.php/apps/' . $app . '/';
449
-			} else {
450
-				$startUrl = $this->urlGenerator->getBaseUrl() . '/apps/' . $app . '/';
451
-			}
452
-			$description = $info['summary'] ?? '';
453
-		}
454
-		/**
455
-		 * @var string $description
456
-		 * @var string $shortName
457
-		 */
458
-		$responseJS = [
459
-			'name' => $name,
460
-			'short_name' => $shortName,
461
-			'start_url' => $startUrl,
462
-			'theme_color' => $this->themingDefaults->getColorPrimary(),
463
-			'background_color' => $this->themingDefaults->getColorPrimary(),
464
-			'description' => $description,
465
-			'icons' =>
466
-				[
467
-					[
468
-						'src' => $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon',
469
-							['app' => $app]) . '?v=' . $cacheBusterValue,
470
-						'type' => 'image/png',
471
-						'sizes' => '512x512'
472
-					],
473
-					[
474
-						'src' => $this->urlGenerator->linkToRoute('theming.Icon.getFavicon',
475
-							['app' => $app]) . '?v=' . $cacheBusterValue,
476
-						'type' => 'image/svg+xml',
477
-						'sizes' => '16x16'
478
-					]
479
-				],
480
-			'display_override' => [$this->config->getSystemValueBool('theming.standalone_window.enabled', true) ? 'minimal-ui' : ''],
481
-			'display' => $this->config->getSystemValueBool('theming.standalone_window.enabled', true) ? 'standalone' : 'browser'
482
-		];
483
-		$response = new JSONResponse($responseJS);
484
-		$response->cacheFor(3600);
485
-		return $response;
486
-	}
444
+            $info = $this->appManager->getAppInfo($app, false, $this->l10n->getLanguageCode());
445
+            $name = $info['name'] . ' - ' . $this->themingDefaults->getName();
446
+            $shortName = $info['name'];
447
+            if (str_contains($this->request->getRequestUri(), '/index.php/')) {
448
+                $startUrl = $this->urlGenerator->getBaseUrl() . '/index.php/apps/' . $app . '/';
449
+            } else {
450
+                $startUrl = $this->urlGenerator->getBaseUrl() . '/apps/' . $app . '/';
451
+            }
452
+            $description = $info['summary'] ?? '';
453
+        }
454
+        /**
455
+         * @var string $description
456
+         * @var string $shortName
457
+         */
458
+        $responseJS = [
459
+            'name' => $name,
460
+            'short_name' => $shortName,
461
+            'start_url' => $startUrl,
462
+            'theme_color' => $this->themingDefaults->getColorPrimary(),
463
+            'background_color' => $this->themingDefaults->getColorPrimary(),
464
+            'description' => $description,
465
+            'icons' =>
466
+                [
467
+                    [
468
+                        'src' => $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon',
469
+                            ['app' => $app]) . '?v=' . $cacheBusterValue,
470
+                        'type' => 'image/png',
471
+                        'sizes' => '512x512'
472
+                    ],
473
+                    [
474
+                        'src' => $this->urlGenerator->linkToRoute('theming.Icon.getFavicon',
475
+                            ['app' => $app]) . '?v=' . $cacheBusterValue,
476
+                        'type' => 'image/svg+xml',
477
+                        'sizes' => '16x16'
478
+                    ]
479
+                ],
480
+            'display_override' => [$this->config->getSystemValueBool('theming.standalone_window.enabled', true) ? 'minimal-ui' : ''],
481
+            'display' => $this->config->getSystemValueBool('theming.standalone_window.enabled', true) ? 'standalone' : 'browser'
482
+        ];
483
+        $response = new JSONResponse($responseJS);
484
+        $response->cacheFor(3600);
485
+        return $response;
486
+    }
487 487
 }
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -253,7 +253,7 @@  discard block
 block discarded – undo
253 253
 
254 254
 		try {
255 255
 			$mime = $this->imageManager->updateImage($key, $image['tmp_name']);
256
-			$this->themingDefaults->set($key . 'Mime', $mime);
256
+			$this->themingDefaults->set($key.'Mime', $mime);
257 257
 		} catch (\Exception $e) {
258 258
 			return new DataResponse(
259 259
 				[
@@ -354,12 +354,12 @@  discard block
 block discarded – undo
354 354
 		$csp->allowInlineStyle();
355 355
 		$response->setContentSecurityPolicy($csp);
356 356
 		$response->cacheFor(3600);
357
-		$response->addHeader('Content-Type', $this->config->getAppValue($this->appName, $key . 'Mime', ''));
358
-		$response->addHeader('Content-Disposition', 'attachment; filename="' . $key . '"');
357
+		$response->addHeader('Content-Type', $this->config->getAppValue($this->appName, $key.'Mime', ''));
358
+		$response->addHeader('Content-Disposition', 'attachment; filename="'.$key.'"');
359 359
 		if (!$useSvg) {
360 360
 			$response->addHeader('Content-Type', 'image/png');
361 361
 		} else {
362
-			$response->addHeader('Content-Type', $this->config->getAppValue($this->appName, $key . 'Mime', ''));
362
+			$response->addHeader('Content-Type', $this->config->getAppValue($this->appName, $key.'Mime', ''));
363 363
 		}
364 364
 		return $response;
365 365
 	}
@@ -398,7 +398,7 @@  discard block
 block discarded – undo
398 398
 
399 399
 		// If plain is set, the browser decides of the css priority
400 400
 		if ($plain) {
401
-			$css = ":root { $variables } " . $customCss;
401
+			$css = ":root { $variables } ".$customCss;
402 402
 		} else {
403 403
 			// If not set, we'll rely on the body class
404 404
 			$css = "[data-theme-$themeId] { $variables $customCss }";
@@ -442,12 +442,12 @@  discard block
 block discarded – undo
442 442
 			}
443 443
 
444 444
 			$info = $this->appManager->getAppInfo($app, false, $this->l10n->getLanguageCode());
445
-			$name = $info['name'] . ' - ' . $this->themingDefaults->getName();
445
+			$name = $info['name'].' - '.$this->themingDefaults->getName();
446 446
 			$shortName = $info['name'];
447 447
 			if (str_contains($this->request->getRequestUri(), '/index.php/')) {
448
-				$startUrl = $this->urlGenerator->getBaseUrl() . '/index.php/apps/' . $app . '/';
448
+				$startUrl = $this->urlGenerator->getBaseUrl().'/index.php/apps/'.$app.'/';
449 449
 			} else {
450
-				$startUrl = $this->urlGenerator->getBaseUrl() . '/apps/' . $app . '/';
450
+				$startUrl = $this->urlGenerator->getBaseUrl().'/apps/'.$app.'/';
451 451
 			}
452 452
 			$description = $info['summary'] ?? '';
453 453
 		}
@@ -466,13 +466,13 @@  discard block
 block discarded – undo
466 466
 				[
467 467
 					[
468 468
 						'src' => $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon',
469
-							['app' => $app]) . '?v=' . $cacheBusterValue,
469
+							['app' => $app]).'?v='.$cacheBusterValue,
470 470
 						'type' => 'image/png',
471 471
 						'sizes' => '512x512'
472 472
 					],
473 473
 					[
474 474
 						'src' => $this->urlGenerator->linkToRoute('theming.Icon.getFavicon',
475
-							['app' => $app]) . '?v=' . $cacheBusterValue,
475
+							['app' => $app]).'?v='.$cacheBusterValue,
476 476
 						'type' => 'image/svg+xml',
477 477
 						'sizes' => '16x16'
478 478
 					]
Please login to merge, or discard this patch.