Completed
Push — stable10 ( f4f43d...efe8f7 )
by Julius
09:42
created

ThemingController   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 286
Duplicated Lines 27.27 %

Coupling/Cohesion

Components 2
Dependencies 13

Importance

Changes 13
Bugs 4 Features 0
Metric Value
c 13
b 4
f 0
dl 78
loc 286
rs 10
wmc 25
lcom 2
cbo 13

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 19 1
B updateStylesheet() 40 56 9
A undo() 0 13 1
A getLogo() 13 13 2
A getLoginBackground() 13 13 2
B updateLogo() 12 37 5
B getStylesheet() 0 67 5

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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 OCA\Theming\Template;
31
use OCP\AppFramework\Controller;
32
use OCP\AppFramework\Http;
33
use OCP\AppFramework\Http\DataDownloadResponse;
34
use OCP\AppFramework\Http\DataResponse;
35
use OCP\AppFramework\Http\StreamResponse;
36
use OCP\AppFramework\Utility\ITimeFactory;
37
use OCP\Files\IRootFolder;
38
use OCP\IConfig;
39
use OCP\IL10N;
40
use OCP\IRequest;
41
use OCA\Theming\Util;
42
43
/**
44
 * Class ThemingController
45
 *
46
 * handle ajax requests to update the theme
47
 *
48
 * @package OCA\Theming\Controller
49
 */
50
class ThemingController extends Controller {
51
	/** @var Template */
52
	private $template;
53
	/** @var Util */
54
	private $util;
55
	/** @var ITimeFactory */
56
	private $timeFactory;
57
	/** @var IL10N */
58
	private $l;
59
	/** @var IConfig */
60
	private $config;
61
	/** @var IRootFolder */
62
	private $rootFolder;
63
64
	/**
65
	 * ThemingController constructor.
66
	 *
67
	 * @param string $appName
68
	 * @param IRequest $request
69
	 * @param IConfig $config
70
	 * @param Template $template
71
	 * @param Util $util
72
	 * @param ITimeFactory $timeFactory
73
	 * @param IL10N $l
74
	 * @param IRootFolder $rootFolder
75
	 */
76
	public function __construct(
77
		$appName,
78
		IRequest $request,
79
		IConfig $config,
80
		Template $template,
81
		Util $util,
82
		ITimeFactory $timeFactory,
83
		IL10N $l,
84
		IRootFolder $rootFolder
85
	) {
86
		parent::__construct($appName, $request);
87
88
		$this->template = $template;
89
		$this->util = $util;
90
		$this->timeFactory = $timeFactory;
91
		$this->l = $l;
92
		$this->config = $config;
93
		$this->rootFolder = $rootFolder;
94
	}
95
96
	/**
97
	 * @param string $setting
98
	 * @param string $value
99
	 * @return DataResponse
100
	 * @internal param string $color
101
	 */
102
	public function updateStylesheet($setting, $value) {
103
		$value = trim($value);
104
		switch ($setting) {
105 View Code Duplication
			case 'name':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
106
				if (strlen($value) > 250) {
107
					return new DataResponse([
108
						'data' => [
109
							'message' => $this->l->t('The given name is too long'),
110
						],
111
						'status' => 'error'
112
					]);
113
				}
114
				break;
115 View Code Duplication
			case 'url':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
116
				if (strlen($value) > 500) {
117
					return new DataResponse([
118
						'data' => [
119
							'message' => $this->l->t('The given web address is too long'),
120
						],
121
						'status' => 'error'
122
					]);
123
				}
124
				break;
125 View Code Duplication
			case 'slogan':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
126
				if (strlen($value) > 500) {
127
					return new DataResponse([
128
						'data' => [
129
							'message' => $this->l->t('The given slogan is too long'),
130
						],
131
						'status' => 'error'
132
					]);
133
				}
134
				break;
135 View Code Duplication
			case 'color':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
136
				if (!preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $value)) {
137
					return new DataResponse([
138
						'data' => [
139
							'message' => $this->l->t('The given color is invalid'),
140
						],
141
						'status' => 'error'
142
					]);
143
				}
144
				break;
145
		}
146
147
		$this->template->set($setting, $value);
148
		return new DataResponse(
149
			[
150
				'data' =>
151
					[
152
						'message' => $this->l->t('Saved')
153
					],
154
				'status' => 'success'
155
			]
156
		);
157
	}
158
159
	/**
160
	 * Update the logos and background image
161
	 *
162
	 * @return DataResponse
163
	 */
164
	public function updateLogo() {
165
		$newLogo = $this->request->getUploadedFile('uploadlogo');
166
		$newBackgroundLogo = $this->request->getUploadedFile('upload-login-background');
167
		if (empty($newLogo) && empty($newBackgroundLogo)) {
168
			return new DataResponse(
169
				[
170
					'data' => [
171
						'message' => $this->l->t('No file uploaded')
172
					]
173
				],
174
				Http::STATUS_UNPROCESSABLE_ENTITY);
175
		}
176
		$name = '';
177 View Code Duplication
		if(!empty($newLogo)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
178
			$target = $this->rootFolder->newFile('themedinstancelogo');
179
			stream_copy_to_stream(fopen($newLogo['tmp_name'], 'r'), $target->fopen('w'));
180
			$this->template->set('logoMime', $newLogo['type']);
181
			$name = $newLogo['name'];
182
		}
183 View Code Duplication
		if(!empty($newBackgroundLogo)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
184
			$target = $this->rootFolder->newFile('themedbackgroundlogo');
185
			stream_copy_to_stream(fopen($newBackgroundLogo['tmp_name'], 'r'), $target->fopen('w'));
186
			$this->template->set('backgroundMime', $newBackgroundLogo['type']);
187
			$name = $newBackgroundLogo['name'];
188
		}
189
190
		return new DataResponse(
191
			[
192
				'data' =>
193
					[
194
						'name' => $name,
195
						'message' => $this->l->t('Saved')
196
					],
197
				'status' => 'success'
198
			]
199
		);
200
	}
201
202
	/**
203
	 * Revert setting to default value
204
	 *
205
	 * @param string $setting setting which should be reverted
206
	 * @return DataResponse
207
	 */
208
	public function undo($setting) {
209
		$value = $this->template->undo($setting);
210
		return new DataResponse(
211
			[
212
				'data' =>
213
					[
214
						'value' => $value,
215
						'message' => $this->l->t('Saved')
216
					],
217
				'status' => 'success'
218
			]
219
		);
220
	}
221
222
	/**
223
	 * @PublicPage
224
	 * @NoCSRFRequired
225
	 *
226
	 * @return StreamResponse|DataResponse
227
	 */
228 View Code Duplication
	public function getLogo() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
229
		$pathToLogo = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/') . '/themedinstancelogo';
230
		if(!file_exists($pathToLogo)) {
231
			return new DataResponse();
232
		}
233
234
		$response = new Http\StreamResponse($pathToLogo);
235
		$response->cacheFor(3600);
236
		$response->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime()));
237
		$response->addHeader('Content-Disposition', 'attachment');
238
		$response->addHeader('Content-Type', $this->config->getAppValue($this->appName, 'logoMime', ''));
239
		return $response;
240
	}
241
242
	/**
243
	 * @PublicPage
244
	 * @NoCSRFRequired
245
	 *
246
	 * @return StreamResponse|DataResponse
247
	 */
248 View Code Duplication
	public function getLoginBackground() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
249
		$pathToLogo = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/') . '/themedbackgroundlogo';
250
		if(!file_exists($pathToLogo)) {
251
			return new DataResponse();
252
		}
253
254
		$response = new StreamResponse($pathToLogo);
255
		$response->cacheFor(3600);
256
		$response->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime()));
257
		$response->addHeader('Content-Disposition', 'attachment');
258
		$response->addHeader('Content-Type', $this->config->getAppValue($this->appName, 'backgroundMime', ''));
259
		return $response;
260
	}
261
262
	/**
263
	 * @NoCSRFRequired
264
	 * @PublicPage
265
	 *
266
	 * @return DataDownloadResponse
267
	 */
268
	public function getStylesheet() {
269
		$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
270
		$responseCss = '';
271
		$color = $this->config->getAppValue($this->appName, 'color');
272
		$elementColor = $this->util->elementColor($color);
273
		if($color !== '') {
274
			$responseCss .= sprintf(
275
				'#body-user #header,#body-settings #header,#body-public #header,#body-login,.searchbox input[type="search"]:focus,.searchbox input[type="search"]:active,.searchbox input[type="search"]:valid {background-color: %s}' . "\n",
276
				$color
277
			);
278
			$responseCss .= sprintf('input[type="checkbox"].checkbox:checked:enabled:not(.checkbox--white) + label:before {' .
279
				'background-image:url(\'%s/core/img/actions/checkmark-white.svg\');' .
280
				'background-color: %s; background-position: center center; background-size:contain;' .
281
				'width:12px; height:12px; padding:0; margin:2px 6px 6px 2px; border-radius:1px;' .
282
				"}\n",
283
				\OC::$WEBROOT,
284
				$elementColor
285
			);
286
			$responseCss .= 'input[type="radio"].radio:checked:not(.radio--white):not(:disabled) + label:before {' .
287
				'background-image: url(\'data:image/svg+xml;base64,'.$this->util->generateRadioButton($elementColor).'\');' .
288
				"}\n";
289
			$responseCss .= '
290
				#firstrunwizard .firstrunwizard-header {
291
					background-color: ' . $color . ';
292
				}
293
				#firstrunwizard p a {
294
					color: ' . $color . ';
295
				}
296
				';
297
298
		}
299
		$logo = $this->config->getAppValue($this->appName, 'logoMime');
300
		if($logo !== '') {
301
			$responseCss .= sprintf(
302
				'#header .logo {' .
303
				'background-image: url(\'./logo?v='.$cacheBusterValue.'\');' .
304
				'background-size: contain;' .
305
				'}' . "\n" .
306
				'#header .logo-icon {' .
307
				'background-image: url(\'./logo?v='.$cacheBusterValue.'\');' .
308
				'background-size: contain;' .
309
				'}' . "\n" .
310
				'#firstrunwizard .firstrunwizard-header .logo {' .
311
				'background-image: url(\'./logo?v='.$cacheBusterValue.'\');' .
312
				'background-size: contain;' .
313
				'}' . "\n"
314
			);
315
		}
316
		$backgroundLogo = $this->config->getAppValue($this->appName, 'backgroundMime');
317
		if($backgroundLogo !== '') {
318
			$responseCss .= '#body-login {background-image: url(\'./loginbackground?v='.$cacheBusterValue.'\');}' . "\n";
319
			$responseCss .= '#firstrunwizard .firstrunwizard-header {' .
320
				'background-image: url(\'./loginbackground?v='.$cacheBusterValue.'\');' .
321
			'}' . "\n";
322
		}
323
		if($this->util->invertTextColor($color)) {
324
			$responseCss .= '#header .header-appname, #expandDisplayName { color: #000000; }' . "\n";
325
			$responseCss .= '#header .icon-caret { background-image: url(\'' . \OC::$WEBROOT . '/core/img/actions/caret-dark.svg\'); }' . "\n";
326
			$responseCss .= '.searchbox input[type="search"] { background: transparent url(\'' . \OC::$WEBROOT . '/core/img/actions/search.svg\') no-repeat 6px center; color: #000; }' . "\n";
327
			$responseCss .= '.searchbox input[type="search"]:focus,.searchbox input[type="search"]:active,.searchbox input[type="search"]:valid { color: #000; border: 1px solid rgba(0, 0, 0, .5); }' . "\n";
328
		}
329
330
		$response = new DataDownloadResponse($responseCss, 'style', 'text/css');
331
		$response->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime()));
332
		$response->cacheFor(3600);
333
		return $response;
334
	}
335
}
336