Completed
Push — master ( ff2730...83508d )
by Morris
36s
created

ThemingController::__construct()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 25
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 22
nc 1
nop 11
dl 0
loc 25
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 Bjoern Schiessle <[email protected]>
7
 * @author Julius Haertl <[email protected]>
8
 * @author Lukas Reschke <[email protected]>
9
 * @author oparoz <[email protected]>
10
 *
11
 * @license GNU AGPL version 3 or any later version
12
 *
13
 * This program is free software: you can redistribute it and/or modify
14
 * it under the terms of the GNU Affero General Public License as
15
 * published by the Free Software Foundation, either version 3 of the
16
 * License, or (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU Affero General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU Affero General Public License
24
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
25
 *
26
 */
27
28
namespace OCA\Theming\Controller;
29
30
use OC\Files\AppData\Factory;
31
use OC\Template\SCSSCacher;
32
use OCA\Theming\ThemingDefaults;
33
use OCP\AppFramework\Controller;
34
use OCP\AppFramework\Http;
35
use OCP\AppFramework\Http\DataDownloadResponse;
36
use OCP\AppFramework\Http\FileDisplayResponse;
37
use OCP\AppFramework\Http\DataResponse;
38
use OCP\AppFramework\Http\NotFoundResponse;
39
use OCP\AppFramework\Utility\ITimeFactory;
40
use OCP\Files\File;
41
use OCP\Files\IAppData;
42
use OCP\Files\NotFoundException;
43
use OCP\Files\NotPermittedException;
44
use OCP\IConfig;
45
use OCP\IL10N;
46
use OCP\ILogger;
47
use OCP\IRequest;
48
use OCA\Theming\Util;
49
use OCP\ITempManager;
50
use OCP\IURLGenerator;
51
52
/**
53
 * Class ThemingController
54
 *
55
 * handle ajax requests to update the theme
56
 *
57
 * @package OCA\Theming\Controller
58
 */
59
class ThemingController extends Controller {
60
	/** @var ThemingDefaults */
61
	private $themingDefaults;
62
	/** @var Util */
63
	private $util;
64
	/** @var ITimeFactory */
65
	private $timeFactory;
66
	/** @var IL10N */
67
	private $l10n;
68
	/** @var IConfig */
69
	private $config;
70
	/** @var ITempManager */
71
	private $tempManager;
72
	/** @var IAppData */
73
	private $appData;
74
	/** @var SCSSCacher */
75
	private $scssCacher;
76
	/** @var IURLGenerator */
77
	private $urlGenerator;
78
79
	/**
80
	 * ThemingController constructor.
81
	 *
82
	 * @param string $appName
83
	 * @param IRequest $request
84
	 * @param IConfig $config
85
	 * @param ThemingDefaults $themingDefaults
86
	 * @param Util $util
87
	 * @param ITimeFactory $timeFactory
88
	 * @param IL10N $l
89
	 * @param ITempManager $tempManager
90
	 * @param IAppData $appData
91
	 * @param SCSSCacher $scssCacher
92
	 * @param IURLGenerator $urlGenerator
93
	 */
94
	public function __construct(
95
		$appName,
96
		IRequest $request,
97
		IConfig $config,
98
		ThemingDefaults $themingDefaults,
99
		Util $util,
100
		ITimeFactory $timeFactory,
101
		IL10N $l,
102
		ITempManager $tempManager,
103
		IAppData $appData,
104
		SCSSCacher $scssCacher,
105
		IURLGenerator $urlGenerator
106
	) {
107
		parent::__construct($appName, $request);
108
109
		$this->themingDefaults = $themingDefaults;
110
		$this->util = $util;
111
		$this->timeFactory = $timeFactory;
112
		$this->l10n = $l;
113
		$this->config = $config;
114
		$this->tempManager = $tempManager;
115
		$this->appData = $appData;
116
		$this->scssCacher = $scssCacher;
117
		$this->urlGenerator = $urlGenerator;
118
	}
119
120
	/**
121
	 * @param string $setting
122
	 * @param string $value
123
	 * @return DataResponse
124
	 * @internal param string $color
125
	 */
126
	public function updateStylesheet($setting, $value) {
127
		$value = trim($value);
128
		switch ($setting) {
129 View Code Duplication
			case 'name':
130
				if (strlen($value) > 250) {
131
					return new DataResponse([
132
						'data' => [
133
							'message' => $this->l10n->t('The given name is too long'),
134
						],
135
						'status' => 'error'
136
					]);
137
				}
138
				break;
139 View Code Duplication
			case 'url':
140
				if (strlen($value) > 500) {
141
					return new DataResponse([
142
						'data' => [
143
							'message' => $this->l10n->t('The given web address is too long'),
144
						],
145
						'status' => 'error'
146
					]);
147
				}
148
				break;
149 View Code Duplication
			case 'slogan':
150
				if (strlen($value) > 500) {
151
					return new DataResponse([
152
						'data' => [
153
							'message' => $this->l10n->t('The given slogan is too long'),
154
						],
155
						'status' => 'error'
156
					]);
157
				}
158
				break;
159 View Code Duplication
			case 'color':
160
				if (!preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $value)) {
161
					return new DataResponse([
162
						'data' => [
163
							'message' => $this->l10n->t('The given color is invalid'),
164
						],
165
						'status' => 'error'
166
					]);
167
				}
168
				break;
169
		}
170
171
		$this->themingDefaults->set($setting, $value);
172
173
		// reprocess server scss for preview
174
		$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...
175
176
		return new DataResponse(
177
			[
178
				'data' =>
179
					[
180
						'message' => $this->l10n->t('Saved'),
181
						'serverCssUrl' => $this->urlGenerator->linkTo('', $this->scssCacher->getCachedSCSS('core', '/core/css/server.scss'))
182
					],
183
				'status' => 'success'
184
			]
185
		);
186
	}
187
188
	/**
189
	 * Update the logos and background image
190
	 *
191
	 * @return DataResponse
192
	 */
193
	public function updateLogo() {
194
		$backgroundColor = $this->request->getParam('backgroundColor', false);
195
		if($backgroundColor) {
196
			$this->themingDefaults->set('backgroundMime', 'backgroundColor');
197
			return new DataResponse(
198
				[
199
					'data' =>
200
						[
201
							'name' => 'backgroundColor',
202
							'message' => $this->l10n->t('Saved')
203
						],
204
					'status' => 'success'
205
				]
206
			);
207
		}
208
		$newLogo = $this->request->getUploadedFile('uploadlogo');
209
		$newBackgroundLogo = $this->request->getUploadedFile('upload-login-background');
210 View Code Duplication
		if (empty($newLogo) && empty($newBackgroundLogo)) {
211
			return new DataResponse(
212
				[
213
					'data' => [
214
						'message' => $this->l10n->t('No file uploaded')
215
					]
216
				],
217
				Http::STATUS_UNPROCESSABLE_ENTITY
218
			);
219
		}
220
221
		$name = '';
222
		try {
223
			$folder = $this->appData->getFolder('images');
224
		} catch (NotFoundException $e) {
225
			$folder = $this->appData->newFolder('images');
226
		}
227
228
		if (!empty($newLogo)) {
229
			$target = $folder->newFile('logo');
230
			$target->putContent(file_get_contents($newLogo['tmp_name'], 'r'));
231
			$this->themingDefaults->set('logoMime', $newLogo['type']);
232
			$name = $newLogo['name'];
233
		}
234
		if (!empty($newBackgroundLogo)) {
235
			$target = $folder->newFile('background');
236
			$image = @imagecreatefromstring(file_get_contents($newBackgroundLogo['tmp_name'], 'r'));
237
			if ($image === false) {
238
				return new DataResponse(
239
					[
240
						'data' => [
241
							'message' => $this->l10n->t('Unsupported image type'),
242
						],
243
						'status' => 'failure',
244
					],
245
					Http::STATUS_UNPROCESSABLE_ENTITY
246
				);
247
			}
248
249
			// Optimize the image since some people may upload images that will be
250
			// either to big or are not progressive rendering.
251
			$tmpFile = $this->tempManager->getTemporaryFile();
252
			if (function_exists('imagescale')) {
253
				// FIXME: Once PHP 5.5.0 is a requirement the above check can be removed
254
				// Workaround for https://bugs.php.net/bug.php?id=65171
255
				$newHeight = imagesy($image) / (imagesx($image) / 1920);
256
				$image = imagescale($image, 1920, $newHeight);
257
			}
258
			imageinterlace($image, 1);
259
			imagejpeg($image, $tmpFile, 75);
260
			imagedestroy($image);
261
262
			$target->putContent(file_get_contents($tmpFile, 'r'));
263
			$this->themingDefaults->set('backgroundMime', $newBackgroundLogo['type']);
264
			$name = $newBackgroundLogo['name'];
265
		}
266
267
		return new DataResponse(
268
			[
269
				'data' =>
270
					[
271
						'name' => $name,
272
						'message' => $this->l10n->t('Saved')
273
					],
274
				'status' => 'success'
275
			]
276
		);
277
	}
278
279
	/**
280
	 * Revert setting to default value
281
	 *
282
	 * @param string $setting setting which should be reverted
283
	 * @return DataResponse
284
	 */
285
	public function undo($setting) {
286
		$value = $this->themingDefaults->undo($setting);
287
		// reprocess server scss for preview
288
		$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...
289
290
		if($setting === 'logoMime') {
291
			try {
292
				$file = $this->appData->getFolder('images')->getFile('logo');
293
				$file->delete();
294
			} catch (NotFoundException $e) {
295
			} catch (NotPermittedException $e) {
296
			}
297
		}
298
		if($setting === 'backgroundMime') {
299
			try {
300
				$file = $this->appData->getFolder('images')->getFile('background');
301
				$file->delete();
302
			} catch (NotFoundException $e) {
303
			} catch (NotPermittedException $e) {
304
			}
305
		}
306
307
		return new DataResponse(
308
			[
309
				'data' =>
310
					[
311
						'value' => $value,
312
						'message' => $this->l10n->t('Saved'),
313
						'serverCssUrl' => $this->urlGenerator->linkTo('', $this->scssCacher->getCachedSCSS('core', '/core/css/server.scss'))
314
					],
315
				'status' => 'success'
316
			]
317
		);
318
	}
319
320
	/**
321
	 * @PublicPage
322
	 * @NoCSRFRequired
323
	 *
324
	 * @return FileDisplayResponse|NotFoundResponse
325
	 */
326 View Code Duplication
	public function getLogo() {
327
		try {
328
			/** @var File $file */
329
			$file = $this->appData->getFolder('images')->getFile('logo');
330
		} catch (NotFoundException $e) {
331
			return new NotFoundResponse();
332
		}
333
334
		$response = new FileDisplayResponse($file);
335
		$response->cacheFor(3600);
336
		$expires = new \DateTime();
337
		$expires->setTimestamp($this->timeFactory->getTime());
338
		$expires->add(new \DateInterval('PT24H'));
339
		$response->addHeader('Expires', $expires->format(\DateTime::RFC2822));
340
		$response->addHeader('Pragma', 'cache');
341
		$response->addHeader('Content-Type', $this->config->getAppValue($this->appName, 'logoMime', ''));
342
		return $response;
343
	}
344
345
	/**
346
	 * @PublicPage
347
	 * @NoCSRFRequired
348
	 *
349
	 * @return FileDisplayResponse|NotFoundResponse
350
	 */
351 View Code Duplication
	public function getLoginBackground() {
352
		try {
353
			/** @var File $file */
354
			$file = $this->appData->getFolder('images')->getFile('background');
355
		} catch (NotFoundException $e) {
356
			return new NotFoundResponse();
357
		}
358
359
		$response = new FileDisplayResponse($file);
360
		$response->cacheFor(3600);
361
		$expires = new \DateTime();
362
		$expires->setTimestamp($this->timeFactory->getTime());
363
		$expires->add(new \DateInterval('PT24H'));
364
		$response->addHeader('Expires', $expires->format(\DateTime::RFC2822));
365
		$response->addHeader('Pragma', 'cache');
366
		$response->addHeader('Content-Type', $this->config->getAppValue($this->appName, 'backgroundMime', ''));
367
		return $response;
368
	}
369
370
	/**
371
	 * @NoCSRFRequired
372
	 * @PublicPage
373
	 *
374
	 * @return FileDisplayResponse|NotFoundResponse
375
	 */
376
	public function getStylesheet() {
377
		$appPath = substr(\OC::$server->getAppManager()->getAppPath('theming'), strlen(\OC::$SERVERROOT) + 1);
378
		/* SCSSCacher is required here
379
		 * We cannot rely on automatic caching done by \OC_Util::addStyle,
380
		 * since we need to add the cacheBuster value to the url
381
		 */
382
		$cssCached = $this->scssCacher->process(\OC::$SERVERROOT, $appPath . '/css/theming.scss', 'theming');
383
		if(!$cssCached) {
384
			return new NotFoundResponse();
385
		}
386
387
		try {
388
			$cssFile = $this->scssCacher->getCachedCSS('theming', 'theming.css');
389
			$response = new FileDisplayResponse($cssFile, Http::STATUS_OK, ['Content-Type' => 'text/css']);
390
			$response->cacheFor(86400);
391
			$expires = new \DateTime();
392
			$expires->setTimestamp($this->timeFactory->getTime());
393
			$expires->add(new \DateInterval('PT24H'));
394
			$response->addHeader('Expires', $expires->format(\DateTime::RFC1123));
395
			$response->addHeader('Pragma', 'cache');
396
			return $response;
397
		} catch (NotFoundException $e) {
398
			return new NotFoundResponse();
399
		}
400
	}
401
402
	/**
403
	 * @NoCSRFRequired
404
	 * @PublicPage
405
	 *
406
	 * @return DataDownloadResponse
407
	 */
408
	public function getJavascript() {
409
		$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
410
		$responseJS = '(function() {
411
	OCA.Theming = {
412
		name: ' . json_encode($this->themingDefaults->getName()) . ',
413
		url: ' . json_encode($this->themingDefaults->getBaseUrl()) . ',
414
		slogan: ' . json_encode($this->themingDefaults->getSlogan()) . ',
415
		color: ' . json_encode($this->themingDefaults->getColorPrimary()) . ',
416
		inverted: ' . json_encode($this->util->invertTextColor($this->themingDefaults->getColorPrimary())) . ',
417
		cacheBuster: ' . json_encode($cacheBusterValue) . '
418
	};
419
})();';
420
		$response = new DataDownloadResponse($responseJS, 'javascript', 'text/javascript');
421
		$response->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime()));
422
		$response->addHeader('Pragma', 'cache');
423
		$response->cacheFor(3600);
424
		return $response;
425
	}
426
427
	/**
428
	 * @NoCSRFRequired
429
	 * @PublicPage
430
	 *
431
	 * @return Http\JSONResponse
432
	 */
433
	public function getManifest($app) {
434
		$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
435
		$responseJS = [
436
			'name' => $this->themingDefaults->getName(),
437
			'start_url' => $this->urlGenerator->getBaseUrl(),
438
			'icons' =>
439
				[
440
					[
441
						'src' => $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon',
442
								['app' => $app]) . '?v=' . $cacheBusterValue,
443
						'type'=> 'image/png',
444
						'sizes'=> '128x128'
445
					],
446
					[
447
						'src' => $this->urlGenerator->linkToRoute('theming.Icon.getFavicon',
448
								['app' => $app]) . '?v=' . $cacheBusterValue,
449
						'type' => 'image/svg+xml',
450
						'sizes' => '16x16'
451
					]
452
				],
453
			'display' => 'standalone'
454
		];
455
		$response = new Http\JSONResponse($responseJS);
456
		$response->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime()));
457
		$response->addHeader('Pragma', 'cache');
458
		$response->cacheFor(3600);
459
		return $response;
460
	}
461
}
462