Completed
Push — master ( 15bd89...2794d6 )
by Morris
89:38 queued 58:38
created

ThemingController::__construct()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 29
Code Lines 26

Duplication

Lines 29
Ratio 100 %

Importance

Changes 0
Metric Value
cc 1
eloc 26
nc 1
nop 13
dl 29
loc 29
rs 8.8571
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016 Bjoern Schiessle <[email protected]>
4
 * @copyright Copyright (c) 2016 Lukas Reschke <[email protected]>
5
 *
6
 * @author Arthur Schiwon <[email protected]>
7
 * @author Bjoern Schiessle <[email protected]>
8
 * @author Daniel Calviño Sánchez <[email protected]>
9
 * @author Jan-Christoph Borchardt <[email protected]>
10
 * @author Joas Schilling <[email protected]>
11
 * @author Julius Haertl <[email protected]>
12
 * @author Julius Härtl <[email protected]>
13
 * @author Lukas Reschke <[email protected]>
14
 * @author Robin Appelman <[email protected]>
15
 *
16
 * @license GNU AGPL version 3 or any later version
17
 *
18
 * This program is free software: you can redistribute it and/or modify
19
 * it under the terms of the GNU Affero General Public License as
20
 * published by the Free Software Foundation, either version 3 of the
21
 * License, or (at your option) any later version.
22
 *
23
 * This program is distributed in the hope that it will be useful,
24
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26
 * GNU Affero General Public License for more details.
27
 *
28
 * You should have received a copy of the GNU Affero General Public License
29
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
30
 *
31
 */
32
33
namespace OCA\Theming\Controller;
34
35
use OC\Template\SCSSCacher;
36
use OCA\Theming\ImageManager;
37
use OCA\Theming\ThemingDefaults;
38
use OCP\AppFramework\Controller;
39
use OCP\AppFramework\Http;
40
use OCP\AppFramework\Http\DataDownloadResponse;
41
use OCP\AppFramework\Http\FileDisplayResponse;
42
use OCP\AppFramework\Http\DataResponse;
43
use OCP\AppFramework\Http\NotFoundResponse;
44
use OCP\AppFramework\Utility\ITimeFactory;
45
use OCP\Files\File;
46
use OCP\Files\IAppData;
47
use OCP\Files\NotFoundException;
48
use OCP\Files\NotPermittedException;
49
use OCP\IConfig;
50
use OCP\IL10N;
51
use OCP\IRequest;
52
use OCA\Theming\Util;
53
use OCP\ITempManager;
54
use OCP\IURLGenerator;
55
use OCP\App\IAppManager;
56
57
/**
58
 * Class ThemingController
59
 *
60
 * handle ajax requests to update the theme
61
 *
62
 * @package OCA\Theming\Controller
63
 */
64
class ThemingController extends Controller {
65
	/** @var ThemingDefaults */
66
	private $themingDefaults;
67
	/** @var Util */
68
	private $util;
69
	/** @var ITimeFactory */
70
	private $timeFactory;
71
	/** @var IL10N */
72
	private $l10n;
73
	/** @var IConfig */
74
	private $config;
75
	/** @var ITempManager */
76
	private $tempManager;
77
	/** @var IAppData */
78
	private $appData;
79
	/** @var SCSSCacher */
80
	private $scssCacher;
81
	/** @var IURLGenerator */
82
	private $urlGenerator;
83
	/** @var IAppManager */
84
	private $appManager;
85
	/** @var ImageManager */
86
	private $imageManager;
87
88
	/**
89
	 * ThemingController constructor.
90
	 *
91
	 * @param string $appName
92
	 * @param IRequest $request
93
	 * @param IConfig $config
94
	 * @param ThemingDefaults $themingDefaults
95
	 * @param Util $util
96
	 * @param ITimeFactory $timeFactory
97
	 * @param IL10N $l
98
	 * @param ITempManager $tempManager
99
	 * @param IAppData $appData
100
	 * @param SCSSCacher $scssCacher
101
	 * @param IURLGenerator $urlGenerator
102
	 * @param IAppManager $appManager
103
	 * @param ImageManager $imageManager
104
	 */
105 View Code Duplication
	public function __construct(
106
		$appName,
107
		IRequest $request,
108
		IConfig $config,
109
		ThemingDefaults $themingDefaults,
110
		Util $util,
111
		ITimeFactory $timeFactory,
112
		IL10N $l,
113
		ITempManager $tempManager,
114
		IAppData $appData,
115
		SCSSCacher $scssCacher,
116
		IURLGenerator $urlGenerator,
117
		IAppManager $appManager,
118
		ImageManager $imageManager
119
	) {
120
		parent::__construct($appName, $request);
121
122
		$this->themingDefaults = $themingDefaults;
123
		$this->util = $util;
124
		$this->timeFactory = $timeFactory;
125
		$this->l10n = $l;
126
		$this->config = $config;
127
		$this->tempManager = $tempManager;
128
		$this->appData = $appData;
129
		$this->scssCacher = $scssCacher;
130
		$this->urlGenerator = $urlGenerator;
131
		$this->appManager = $appManager;
132
		$this->imageManager = $imageManager;
133
	}
134
135
	/**
136
	 * @param string $setting
137
	 * @param string $value
138
	 * @return DataResponse
139
	 * @throws NotPermittedException
140
	 */
141
	public function updateStylesheet($setting, $value) {
142
		$value = trim($value);
143
		switch ($setting) {
144 View Code Duplication
			case 'name':
145
				if (strlen($value) > 250) {
146
					return new DataResponse([
147
						'data' => [
148
							'message' => $this->l10n->t('The given name is too long'),
149
						],
150
						'status' => 'error'
151
					]);
152
				}
153
				break;
154 View Code Duplication
			case 'url':
155
				if (strlen($value) > 500) {
156
					return new DataResponse([
157
						'data' => [
158
							'message' => $this->l10n->t('The given web address is too long'),
159
						],
160
						'status' => 'error'
161
					]);
162
				}
163
				break;
164 View Code Duplication
			case 'imprintUrl':
165
				if (strlen($value) > 500) {
166
					return new DataResponse([
167
						'data' => [
168
							'message' => $this->l10n->t('The given legal notice address is too long'),
169
						],
170
						'status' => 'error'
171
					]);
172
				}
173
				break;
174 View Code Duplication
			case 'privacyUrl':
175
				if (strlen($value) > 500) {
176
					return new DataResponse([
177
						'data' => [
178
							'message' => $this->l10n->t('The given privacy policy address is too long'),
179
						],
180
						'status' => 'error'
181
					]);
182
				}
183
				break;
184 View Code Duplication
			case 'slogan':
185
				if (strlen($value) > 500) {
186
					return new DataResponse([
187
						'data' => [
188
							'message' => $this->l10n->t('The given slogan is too long'),
189
						],
190
						'status' => 'error'
191
					]);
192
				}
193
				break;
194 View Code Duplication
			case 'color':
195
				if (!preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $value)) {
196
					return new DataResponse([
197
						'data' => [
198
							'message' => $this->l10n->t('The given color is invalid'),
199
						],
200
						'status' => 'error'
201
					]);
202
				}
203
				break;
204
		}
205
206
		$this->themingDefaults->set($setting, $value);
207
208
		// reprocess server scss for preview
209
		$cssCached = $this->scssCacher->process(\OC::$SERVERROOT, 'core/css/server.scss', 'core');
0 ignored issues
show
Unused Code introduced by
$cssCached is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
210
211
		return new DataResponse(
212
			[
213
				'data' =>
214
					[
215
						'message' => $this->l10n->t('Saved'),
216
						'serverCssUrl' => $this->urlGenerator->linkTo('', $this->scssCacher->getCachedSCSS('core', '/core/css/server.scss'))
217
					],
218
				'status' => 'success'
219
			]
220
		);
221
	}
222
223
	/**
224
	 * @return DataResponse
225
	 * @throws NotPermittedException
226
	 */
227
	public function uploadImage(): DataResponse {
228
		// logo / background
229
		// new: favicon logo-header
230
		//
231
		$key = $this->request->getParam('key');
232
		$image = $this->request->getUploadedFile('image');
233
		$error = null;
234
		$phpFileUploadErrors = [
235
			UPLOAD_ERR_OK => $this->l10n->t('The file was uploaded'),
236
			UPLOAD_ERR_INI_SIZE => $this->l10n->t('The uploaded file exceeds the upload_max_filesize directive in php.ini'),
237
			UPLOAD_ERR_FORM_SIZE => $this->l10n->t('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form'),
238
			UPLOAD_ERR_PARTIAL => $this->l10n->t('The file was only partially uploaded'),
239
			UPLOAD_ERR_NO_FILE => $this->l10n->t('No file was uploaded'),
240
			UPLOAD_ERR_NO_TMP_DIR => $this->l10n->t('Missing a temporary folder'),
241
			UPLOAD_ERR_CANT_WRITE => $this->l10n->t('Could not write file to disk'),
242
			UPLOAD_ERR_EXTENSION => $this->l10n->t('A PHP extension stopped the file upload'),
243
		];
244
		if (empty($image)) {
245
			$error = $this->l10n->t('No file uploaded');
246
		}
247
		if (!empty($image) && array_key_exists('error', $image) && $image['error'] !== UPLOAD_ERR_OK) {
248
			$error = $phpFileUploadErrors[$image['error']];
249
		}
250
251
		if ($error !== null) {
252
			return new DataResponse(
253
				[
254
					'data' => [
255
						'message' => $error
256
					],
257
					'status' => 'failure',
258
				],
259
				Http::STATUS_UNPROCESSABLE_ENTITY
260
			);
261
		}
262
263
		$name = '';
0 ignored issues
show
Unused Code introduced by
$name is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
264
		try {
265
			$folder = $this->appData->getFolder('images');
266
		} catch (NotFoundException $e) {
267
			$folder = $this->appData->newFolder('images');
268
		}
269
270
		$target = $folder->newFile($key);
271
		$supportedFormats = ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'image/svg'];
272
		$detectedMimeType = mime_content_type($image['tmp_name']);
273
		if (!in_array($image['type'], $supportedFormats) || !in_array($detectedMimeType, $supportedFormats)) {
274
			return new DataResponse(
275
				[
276
					'data' => [
277
						'message' => $this->l10n->t('Unsupported image type'),
278
					],
279
					'status' => 'failure',
280
				],
281
				Http::STATUS_UNPROCESSABLE_ENTITY
282
			);
283
		}
284
285
		$resizeKeys = ['background'];
286
		if (in_array($key, $resizeKeys, true)) {
287
			// Optimize the image since some people may upload images that will be
288
			// either to big or are not progressive rendering.
289
			$newImage = @imagecreatefromstring(file_get_contents($image['tmp_name'], 'r'));
290
291
			$tmpFile = $this->tempManager->getTemporaryFile();
292
			$newWidth = imagesx($newImage) < 4096 ? imagesx($newImage) : 4096;
293
			$newHeight = imagesy($newImage) / (imagesx($newImage) / $newWidth);
294
			$outputImage = imagescale($newImage, $newWidth, $newHeight);
295
296
			imageinterlace($outputImage, 1);
297
			imagejpeg($outputImage, $tmpFile, 75);
298
			imagedestroy($outputImage);
299
300
			$target->putContent(file_get_contents($tmpFile, 'r'));
301
		} else {
302
			$target->putContent(file_get_contents($image['tmp_name'], 'r'));
303
		}
304
		$name = $image['name'];
305
306
		$this->themingDefaults->set($key.'Mime', $image['type']);
307
308
		$cssCached = $this->scssCacher->process(\OC::$SERVERROOT, 'core/css/server.scss', 'core');
0 ignored issues
show
Unused Code introduced by
$cssCached is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
309
310
		return new DataResponse(
311
			[
312
				'data' =>
313
					[
314
						'name' => $name,
315
						'url' => $this->imageManager->getImageUrl($key),
316
						'message' => $this->l10n->t('Saved'),
317
						'serverCssUrl' => $this->urlGenerator->linkTo('', $this->scssCacher->getCachedSCSS('core', '/core/css/server.scss'))
318
					],
319
				'status' => 'success'
320
			]
321
		);
322
	}
323
324
	/**
325
	 * Revert setting to default value
326
	 *
327
	 * @param string $setting setting which should be reverted
328
	 * @return DataResponse
329
	 * @throws NotPermittedException
330
	 */
331
	public function undo(string $setting): DataResponse {
332
		$value = $this->themingDefaults->undo($setting);
333
		// reprocess server scss for preview
334
		$cssCached = $this->scssCacher->process(\OC::$SERVERROOT, 'core/css/server.scss', 'core');
0 ignored issues
show
Unused Code introduced by
$cssCached is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
335
336
		if (strpos($setting, 'Mime') !== -1) {
337
			$imageKey = str_replace('Mime', '', $setting);
338
			$this->imageManager->delete($imageKey);
339
		}
340
341
		return new DataResponse(
342
			[
343
				'data' =>
344
					[
345
						'value' => $value,
346
						'message' => $this->l10n->t('Saved'),
347
						'serverCssUrl' => $this->urlGenerator->linkTo('', $this->scssCacher->getCachedSCSS('core', '/core/css/server.scss'))
348
					],
349
				'status' => 'success'
350
			]
351
		);
352
	}
353
354
	/**
355
	 * @PublicPage
356
	 * @NoCSRFRequired
357
	 *
358
	 * @param string $key
359
	 * @return FileDisplayResponse|NotFoundResponse
360
	 * @throws \Exception
361
	 */
362
	public function getImage(string $key) {
363
		try {
364
			$file = $this->imageManager->getImage($key);
365
		} catch (NotFoundException $e) {
366
			return new NotFoundResponse();
367
		}
368
369
		$response = new FileDisplayResponse($file);
370
		$response->cacheFor(3600);
371
		$response->addHeader('Content-Type', $this->config->getAppValue($this->appName, $key . 'Mime', ''));
372
		$response->addHeader('Content-Disposition', 'attachment; filename="' . $key . '"');
373
		return $response;
374
	}
375
376
	/**
377
	 * @NoCSRFRequired
378
	 * @PublicPage
379
	 *
380
	 * @return FileDisplayResponse|NotFoundResponse
381
	 * @throws NotPermittedException
382
	 * @throws \Exception
383
	 * @throws \OCP\App\AppPathNotFoundException
384
	 */
385
	public function getStylesheet() {
386
		$appPath = $this->appManager->getAppPath('theming');
387
388
		/* SCSSCacher is required here
389
		 * We cannot rely on automatic caching done by \OC_Util::addStyle,
390
		 * since we need to add the cacheBuster value to the url
391
		 */
392
		$cssCached = $this->scssCacher->process($appPath, 'css/theming.scss', 'theming');
393
		if(!$cssCached) {
394
			return new NotFoundResponse();
395
		}
396
397
		try {
398
			$cssFile = $this->scssCacher->getCachedCSS('theming', 'theming.css');
399
			$response = new FileDisplayResponse($cssFile, Http::STATUS_OK, ['Content-Type' => 'text/css']);
400
			$response->cacheFor(86400);
401
			return $response;
402
		} catch (NotFoundException $e) {
403
			return new NotFoundResponse();
404
		}
405
	}
406
407
	/**
408
	 * @NoCSRFRequired
409
	 * @PublicPage
410
	 *
411
	 * @return DataDownloadResponse
412
	 */
413
	public function getJavascript() {
414
		$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
415
		$responseJS = '(function() {
416
	OCA.Theming = {
417
		name: ' . json_encode($this->themingDefaults->getName()) . ',
418
		url: ' . json_encode($this->themingDefaults->getBaseUrl()) . ',
419
		slogan: ' . json_encode($this->themingDefaults->getSlogan()) . ',
420
		color: ' . json_encode($this->themingDefaults->getColorPrimary()) . ',
421
		imprintUrl: ' . json_encode($this->themingDefaults->getImprintUrl()) . ',
422
		privacyUrl: ' . json_encode($this->themingDefaults->getPrivacyUrl()) . ',
423
		inverted: ' . json_encode($this->util->invertTextColor($this->themingDefaults->getColorPrimary())) . ',
424
		cacheBuster: ' . json_encode($cacheBusterValue) . '
425
	};
426
})();';
427
		$response = new DataDownloadResponse($responseJS, 'javascript', 'text/javascript');
428
		$response->cacheFor(3600);
429
		return $response;
430
	}
431
432
	/**
433
	 * @NoCSRFRequired
434
	 * @PublicPage
435
	 *
436
	 * @return Http\JSONResponse
437
	 */
438
	public function getManifest($app) {
439
		$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
440
		$responseJS = [
441
			'name' => $this->themingDefaults->getName(),
442
			'start_url' => $this->urlGenerator->getBaseUrl(),
443
			'icons' =>
444
				[
445
					[
446
						'src' => $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon',
447
								['app' => $app]) . '?v=' . $cacheBusterValue,
448
						'type'=> 'image/png',
449
						'sizes'=> '128x128'
450
					],
451
					[
452
						'src' => $this->urlGenerator->linkToRoute('theming.Icon.getFavicon',
453
								['app' => $app]) . '?v=' . $cacheBusterValue,
454
						'type' => 'image/svg+xml',
455
						'sizes' => '16x16'
456
					]
457
				],
458
			'display' => 'standalone'
459
		];
460
		$response = new Http\JSONResponse($responseJS);
461
		$response->cacheFor(3600);
462
		return $response;
463
	}
464
}
465