Completed
Push — master ( a60d7a...4076c0 )
by Morris
108:46 queued 89:41
created

ThemingController::__construct()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 24

Duplication

Lines 27
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 24
c 1
b 0
f 0
nc 1
nop 12
dl 27
loc 27
rs 8.8571

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\ThemingDefaults;
37
use OCP\AppFramework\Controller;
38
use OCP\AppFramework\Http;
39
use OCP\AppFramework\Http\DataDownloadResponse;
40
use OCP\AppFramework\Http\FileDisplayResponse;
41
use OCP\AppFramework\Http\DataResponse;
42
use OCP\AppFramework\Http\NotFoundResponse;
43
use OCP\AppFramework\Utility\ITimeFactory;
44
use OCP\Files\File;
45
use OCP\Files\IAppData;
46
use OCP\Files\NotFoundException;
47
use OCP\Files\NotPermittedException;
48
use OCP\IConfig;
49
use OCP\IL10N;
50
use OCP\IRequest;
51
use OCA\Theming\Util;
52
use OCP\ITempManager;
53
use OCP\IURLGenerator;
54
use OCP\App\IAppManager;
55
56
/**
57
 * Class ThemingController
58
 *
59
 * handle ajax requests to update the theme
60
 *
61
 * @package OCA\Theming\Controller
62
 */
63
class ThemingController extends Controller {
64
	/** @var ThemingDefaults */
65
	private $themingDefaults;
66
	/** @var Util */
67
	private $util;
68
	/** @var ITimeFactory */
69
	private $timeFactory;
70
	/** @var IL10N */
71
	private $l10n;
72
	/** @var IConfig */
73
	private $config;
74
	/** @var ITempManager */
75
	private $tempManager;
76
	/** @var IAppData */
77
	private $appData;
78
	/** @var SCSSCacher */
79
	private $scssCacher;
80
	/** @var IURLGenerator */
81
	private $urlGenerator;
82
	/** @var IAppManager */
83
	private $appManager;
84
85
	/**
86
	 * ThemingController constructor.
87
	 *
88
	 * @param string $appName
89
	 * @param IRequest $request
90
	 * @param IConfig $config
91
	 * @param ThemingDefaults $themingDefaults
92
	 * @param Util $util
93
	 * @param ITimeFactory $timeFactory
94
	 * @param IL10N $l
95
	 * @param ITempManager $tempManager
96
	 * @param IAppData $appData
97
	 * @param SCSSCacher $scssCacher
98
	 * @param IURLGenerator $urlGenerator
99
	 * @param IAppManager $appManager
100
	 */
101 View Code Duplication
	public function __construct(
102
		$appName,
103
		IRequest $request,
104
		IConfig $config,
105
		ThemingDefaults $themingDefaults,
106
		Util $util,
107
		ITimeFactory $timeFactory,
108
		IL10N $l,
109
		ITempManager $tempManager,
110
		IAppData $appData,
111
		SCSSCacher $scssCacher,
112
		IURLGenerator $urlGenerator,
113
		IAppManager $appManager
114
	) {
115
		parent::__construct($appName, $request);
116
117
		$this->themingDefaults = $themingDefaults;
118
		$this->util = $util;
119
		$this->timeFactory = $timeFactory;
120
		$this->l10n = $l;
121
		$this->config = $config;
122
		$this->tempManager = $tempManager;
123
		$this->appData = $appData;
124
		$this->scssCacher = $scssCacher;
125
		$this->urlGenerator = $urlGenerator;
126
		$this->appManager = $appManager;
127
	}
128
129
	/**
130
	 * @param string $setting
131
	 * @param string $value
132
	 * @return DataResponse
133
	 * @internal param string $color
134
	 */
135
	public function updateStylesheet($setting, $value) {
136
		$value = trim($value);
137
		switch ($setting) {
138 View Code Duplication
			case 'name':
139
				if (strlen($value) > 250) {
140
					return new DataResponse([
141
						'data' => [
142
							'message' => $this->l10n->t('The given name is too long'),
143
						],
144
						'status' => 'error'
145
					]);
146
				}
147
				break;
148 View Code Duplication
			case 'url':
149
				if (strlen($value) > 500) {
150
					return new DataResponse([
151
						'data' => [
152
							'message' => $this->l10n->t('The given web address is too long'),
153
						],
154
						'status' => 'error'
155
					]);
156
				}
157
				break;
158 View Code Duplication
			case 'slogan':
159
				if (strlen($value) > 500) {
160
					return new DataResponse([
161
						'data' => [
162
							'message' => $this->l10n->t('The given slogan is too long'),
163
						],
164
						'status' => 'error'
165
					]);
166
				}
167
				break;
168 View Code Duplication
			case 'color':
169
				if (!preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $value)) {
170
					return new DataResponse([
171
						'data' => [
172
							'message' => $this->l10n->t('The given color is invalid'),
173
						],
174
						'status' => 'error'
175
					]);
176
				}
177
				break;
178
		}
179
180
		$this->themingDefaults->set($setting, $value);
181
182
		// reprocess server scss for preview
183
		$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...
184
185
		return new DataResponse(
186
			[
187
				'data' =>
188
					[
189
						'message' => $this->l10n->t('Saved'),
190
						'serverCssUrl' => $this->urlGenerator->linkTo('', $this->scssCacher->getCachedSCSS('core', '/core/css/server.scss'))
191
					],
192
				'status' => 'success'
193
			]
194
		);
195
	}
196
197
	/**
198
	 * Update the logos and background image
199
	 *
200
	 * @return DataResponse
201
	 */
202
	public function updateLogo() {
203
		$backgroundColor = $this->request->getParam('backgroundColor', false);
204
		if($backgroundColor) {
205
			$this->themingDefaults->set('backgroundMime', 'backgroundColor');
206
			return new DataResponse(
207
				[
208
					'data' =>
209
						[
210
							'name' => 'backgroundColor',
211
							'message' => $this->l10n->t('Saved')
212
						],
213
					'status' => 'success'
214
				]
215
			);
216
		}
217
		$newLogo = $this->request->getUploadedFile('uploadlogo');
218
		$newBackgroundLogo = $this->request->getUploadedFile('upload-login-background');
219
		$error = null;
220
		$phpFileUploadErrors = [
221
			UPLOAD_ERR_OK => $this->l10n->t('There is no error, the file uploaded with success'),
222
			UPLOAD_ERR_INI_SIZE => $this->l10n->t('The uploaded file exceeds the upload_max_filesize directive in php.ini'),
223
			UPLOAD_ERR_FORM_SIZE => $this->l10n->t('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form'),
224
			UPLOAD_ERR_PARTIAL => $this->l10n->t('The uploaded file was only partially uploaded'),
225
			UPLOAD_ERR_NO_FILE => $this->l10n->t('No file was uploaded'),
226
			UPLOAD_ERR_NO_TMP_DIR => $this->l10n->t('Missing a temporary folder'),
227
			UPLOAD_ERR_CANT_WRITE => $this->l10n->t('Failed to write file to disk.'),
228
			UPLOAD_ERR_EXTENSION => $this->l10n->t('A PHP extension stopped the file upload.'),
229
		];
230
		if (empty($newLogo) && empty($newBackgroundLogo)) {
231
			$error = $this->l10n->t('No file uploaded');
232
		}
233 View Code Duplication
		if (!empty($newLogo) && array_key_exists('error', $newLogo) && $newLogo['error'] !== UPLOAD_ERR_OK) {
234
			$error = $phpFileUploadErrors[$newLogo['error']];
235
		}
236 View Code Duplication
		if (!empty($newBackgroundLogo) && array_key_exists('error', $newBackgroundLogo) && $newBackgroundLogo['error'] !== UPLOAD_ERR_OK) {
237
			$error = $phpFileUploadErrors[$newBackgroundLogo['error']];
238
		}
239
240
		if ($error !== null) {
241
			return new DataResponse(
242
				[
243
					'data' => [
244
						'message' => $error
245
					],
246
					'status' => 'failure',
247
				],
248
				Http::STATUS_UNPROCESSABLE_ENTITY
249
			);
250
		}
251
252
		$name = '';
253
		try {
254
			$folder = $this->appData->getFolder('images');
255
		} catch (NotFoundException $e) {
256
			$folder = $this->appData->newFolder('images');
257
		}
258
259
		if (!empty($newLogo)) {
260
			$target = $folder->newFile('logo');
261
			$supportedFormats = ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'text/svg'];
262
			if (!in_array($newLogo['type'], $supportedFormats)) {
263
				return new DataResponse(
264
					[
265
						'data' => [
266
							'message' => $this->l10n->t('Unsupported image type'),
267
						],
268
						'status' => 'failure',
269
					],
270
					Http::STATUS_UNPROCESSABLE_ENTITY
271
				);
272
			}
273
			$target->putContent(file_get_contents($newLogo['tmp_name'], 'r'));
274
			$this->themingDefaults->set('logoMime', $newLogo['type']);
275
			$name = $newLogo['name'];
276
		}
277
		if (!empty($newBackgroundLogo)) {
278
			$target = $folder->newFile('background');
279
			$image = @imagecreatefromstring(file_get_contents($newBackgroundLogo['tmp_name'], 'r'));
280
			if ($image === false) {
281
				return new DataResponse(
282
					[
283
						'data' => [
284
							'message' => $this->l10n->t('Unsupported image type'),
285
						],
286
						'status' => 'failure',
287
					],
288
					Http::STATUS_UNPROCESSABLE_ENTITY
289
				);
290
			}
291
292
			// Optimize the image since some people may upload images that will be
293
			// either to big or are not progressive rendering.
294
			$tmpFile = $this->tempManager->getTemporaryFile();
295
			$newWidth = imagesx($image) < 4096 ? imagesx($image) : 4096;
296
			$newHeight = imagesy($image) / (imagesx($image) / $newWidth);
297
			$image = imagescale($image, $newWidth, $newHeight);
298
299
			imageinterlace($image, 1);
300
			imagejpeg($image, $tmpFile, 75);
301
			imagedestroy($image);
302
303
			$target->putContent(file_get_contents($tmpFile, 'r'));
304
			$this->themingDefaults->set('backgroundMime', $newBackgroundLogo['type']);
305
			$name = $newBackgroundLogo['name'];
306
		}
307
308
		return new DataResponse(
309
			[
310
				'data' =>
311
					[
312
						'name' => $name,
313
						'message' => $this->l10n->t('Saved')
314
					],
315
				'status' => 'success'
316
			]
317
		);
318
	}
319
320
	/**
321
	 * Revert setting to default value
322
	 *
323
	 * @param string $setting setting which should be reverted
324
	 * @return DataResponse
325
	 */
326
	public function undo($setting) {
327
		$value = $this->themingDefaults->undo($setting);
328
		// reprocess server scss for preview
329
		$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...
330
331
		if($setting === 'logoMime') {
332
			try {
333
				$file = $this->appData->getFolder('images')->getFile('logo');
334
				$file->delete();
335
			} catch (NotFoundException $e) {
336
			} catch (NotPermittedException $e) {
337
			}
338
		}
339
		if($setting === 'backgroundMime') {
340
			try {
341
				$file = $this->appData->getFolder('images')->getFile('background');
342
				$file->delete();
343
			} catch (NotFoundException $e) {
344
			} catch (NotPermittedException $e) {
345
			}
346
		}
347
348
		return new DataResponse(
349
			[
350
				'data' =>
351
					[
352
						'value' => $value,
353
						'message' => $this->l10n->t('Saved'),
354
						'serverCssUrl' => $this->urlGenerator->linkTo('', $this->scssCacher->getCachedSCSS('core', '/core/css/server.scss'))
355
					],
356
				'status' => 'success'
357
			]
358
		);
359
	}
360
361
	/**
362
	 * @PublicPage
363
	 * @NoCSRFRequired
364
	 *
365
	 * @return FileDisplayResponse|NotFoundResponse
366
	 */
367 View Code Duplication
	public function getLogo() {
368
		try {
369
			/** @var File $file */
370
			$file = $this->appData->getFolder('images')->getFile('logo');
371
		} catch (NotFoundException $e) {
372
			return new NotFoundResponse();
373
		}
374
375
		$response = new FileDisplayResponse($file);
376
		$response->cacheFor(3600);
377
		$expires = new \DateTime();
378
		$expires->setTimestamp($this->timeFactory->getTime());
379
		$expires->add(new \DateInterval('PT24H'));
380
		$response->addHeader('Expires', $expires->format(\DateTime::RFC2822));
381
		$response->addHeader('Pragma', 'cache');
382
		$response->addHeader('Content-Type', $this->config->getAppValue($this->appName, 'logoMime', ''));
383
		return $response;
384
	}
385
386
	/**
387
	 * @PublicPage
388
	 * @NoCSRFRequired
389
	 *
390
	 * @return FileDisplayResponse|NotFoundResponse
391
	 */
392 View Code Duplication
	public function getLoginBackground() {
393
		try {
394
			/** @var File $file */
395
			$file = $this->appData->getFolder('images')->getFile('background');
396
		} catch (NotFoundException $e) {
397
			return new NotFoundResponse();
398
		}
399
400
		$response = new FileDisplayResponse($file);
401
		$response->cacheFor(3600);
402
		$expires = new \DateTime();
403
		$expires->setTimestamp($this->timeFactory->getTime());
404
		$expires->add(new \DateInterval('PT24H'));
405
		$response->addHeader('Expires', $expires->format(\DateTime::RFC2822));
406
		$response->addHeader('Pragma', 'cache');
407
		$response->addHeader('Content-Type', $this->config->getAppValue($this->appName, 'backgroundMime', ''));
408
		return $response;
409
	}
410
411
	/**
412
	 * @NoCSRFRequired
413
	 * @PublicPage
414
	 *
415
	 * @return FileDisplayResponse|NotFoundResponse
416
	 */
417
	public function getStylesheet() {
418
		$appPath = $this->appManager->getAppPath('theming');
419
420
		/* SCSSCacher is required here
421
		 * We cannot rely on automatic caching done by \OC_Util::addStyle,
422
		 * since we need to add the cacheBuster value to the url
423
		 */
424
		$cssCached = $this->scssCacher->process($appPath, 'css/theming.scss', 'theming');
425
		if(!$cssCached) {
426
			return new NotFoundResponse();
427
		}
428
429
		try {
430
			$cssFile = $this->scssCacher->getCachedCSS('theming', 'theming.css');
431
			$response = new FileDisplayResponse($cssFile, Http::STATUS_OK, ['Content-Type' => 'text/css']);
432
			$response->cacheFor(86400);
433
			$expires = new \DateTime();
434
			$expires->setTimestamp($this->timeFactory->getTime());
435
			$expires->add(new \DateInterval('PT24H'));
436
			$response->addHeader('Expires', $expires->format(\DateTime::RFC1123));
437
			$response->addHeader('Pragma', 'cache');
438
			return $response;
439
		} catch (NotFoundException $e) {
440
			return new NotFoundResponse();
441
		}
442
	}
443
444
	/**
445
	 * @NoCSRFRequired
446
	 * @PublicPage
447
	 *
448
	 * @return DataDownloadResponse
449
	 */
450
	public function getJavascript() {
451
		$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
452
		$responseJS = '(function() {
453
	OCA.Theming = {
454
		name: ' . json_encode($this->themingDefaults->getName()) . ',
455
		url: ' . json_encode($this->themingDefaults->getBaseUrl()) . ',
456
		slogan: ' . json_encode($this->themingDefaults->getSlogan()) . ',
457
		color: ' . json_encode($this->themingDefaults->getColorPrimary()) . ',
458
		inverted: ' . json_encode($this->util->invertTextColor($this->themingDefaults->getColorPrimary())) . ',
459
		cacheBuster: ' . json_encode($cacheBusterValue) . '
460
	};
461
})();';
462
		$response = new DataDownloadResponse($responseJS, 'javascript', 'text/javascript');
463
		$response->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime()));
464
		$response->addHeader('Pragma', 'cache');
465
		$response->cacheFor(3600);
466
		return $response;
467
	}
468
469
	/**
470
	 * @NoCSRFRequired
471
	 * @PublicPage
472
	 *
473
	 * @return Http\JSONResponse
474
	 */
475
	public function getManifest($app) {
476
		$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
477
		$responseJS = [
478
			'name' => $this->themingDefaults->getName(),
479
			'start_url' => $this->urlGenerator->getBaseUrl(),
480
			'icons' =>
481
				[
482
					[
483
						'src' => $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon',
484
								['app' => $app]) . '?v=' . $cacheBusterValue,
485
						'type'=> 'image/png',
486
						'sizes'=> '128x128'
487
					],
488
					[
489
						'src' => $this->urlGenerator->linkToRoute('theming.Icon.getFavicon',
490
								['app' => $app]) . '?v=' . $cacheBusterValue,
491
						'type' => 'image/svg+xml',
492
						'sizes' => '16x16'
493
					]
494
				],
495
			'display' => 'standalone'
496
		];
497
		$response = new Http\JSONResponse($responseJS);
498
		$response->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime()));
499
		$response->addHeader('Pragma', 'cache');
500
		$response->cacheFor(3600);
501
		return $response;
502
	}
503
}
504