Completed
Pull Request — master (#590)
by
unknown
32:12 queued 12:16
created

ViewController::index()   D

Complexity

Conditions 16
Paths 126

Size

Total Lines 101
Code Lines 62

Duplication

Lines 8
Ratio 7.92 %

Code Coverage

Tests 38
CRAP Score 16

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 8
loc 101
ccs 38
cts 38
cp 1
rs 4.5663
cc 16
eloc 62
nc 126
nop 0
crap 16

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Calendar App
4
 *
5
 * @author Georg Ehrke
6
 * @copyright 2016 Georg Ehrke <[email protected]>
7
 * @author Raghu Nayyar
8
 * @copyright 2016 Raghu Nayyar <[email protected]>
9
 *
10
 * This library is free software; you can redistribute it and/or
11
 * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
12
 * License as published by the Free Software Foundation; either
13
 * version 3 of the License, or any later version.
14
 *
15
 * This library is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
19
 *
20
 * You should have received a copy of the GNU Affero General Public
21
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
22
 *
23
 */
24
namespace OCA\Calendar\Controller;
25
26
use OC\AppFramework\Http\Request;
27
use OCP\AppFramework\Controller;
28
use OCP\AppFramework\Http\ContentSecurityPolicy;
29
use OCP\AppFramework\Http\TemplateResponse;
30
use OCP\IConfig;
31
use OCP\IRequest;
32
use OCP\IUserSession;
33
use OCP\IURLGenerator;
34
use OCP\IL10N;
35
use OCP\L10N\IFactory;
36
37
class ViewController extends Controller {
38
39
	/**
40
	 * @var IConfig
41
	 */
42
	private $config;
43
44
	/**
45
	 * @var IURLGenerator
46
	 */
47
	private $urlGenerator;
48
49
	/**
50
	 * @var IUserSession
51
	 */
52
	private $userSession;
53
54
	/**
55
	 * @var IFactory
56
	 */
57
	private $l10nFactory;
58
59 15
	// TODO(artur): Duplicate: Refactor Language --> NC:Server:PersonalInfo.php
60
	const COMMON_LANGUAGE_CODES = [
61 15
		'en', 'es', 'fr', 'de', 'de_DE', 'ja', 'ar', 'ru', 'nl', 'it',
62 15
		'pt_BR', 'pt_PT', 'da', 'fi_FI', 'nb_NO', 'sv', 'tr', 'zh_CN', 'ko'
63 15
	];
64 15
65 15
	/**
66
	 * @var [type]
67
	 */
68
	private $l;
69
70
	/**
71
	 * @param string $appName
72
	 * @param IRequest $request an instance of the request
73 7
	 * @param IUserSession $userSession
74 7
	 * @param IConfig $config
75
	 * @param IURLGenerator $urlGenerator
76 7
	 * @param IFactory $l10nFactory
77 7
	 * @param IL10N $l
78 7
	 */
79
	public function __construct(
80 7
		$appName,
81 7
		IRequest $request,
82 7
		IUserSession $userSession,
83 7
		IConfig $config,
84
		IURLGenerator $urlGenerator,
85
		IFactory $l10nFactory,
86
		IL10N $l
87
	) {
88 7
		parent::__construct($appName, $request);
89 2
		$this->config = $config;
90 1
		$this->userSession = $userSession;
91
		$this->urlGenerator = $urlGenerator;
92 1
		$this->l10nFactory = $l10nFactory;
93 1
		$this->l = $l;
94
	}
95
96
	/**
97 7
	 * @NoAdminRequired
98 2
	 * @NoCSRFRequired
99
	 *
100
	 * @return TemplateResponse
101 7
	 */
102 7
	public function index() {
103 7
		$templateParameters = $this->getTemplateParams();
104 7
105 7
		$user = $this->userSession->getUser();
106 7
		$userId = $user->getUID();
107
		$emailAddress = $user->getEMailAddress();
108
109 7
		$initialView = $this->config->getUserValue($userId, $this->appName, 'currentView', null);
110
		$skipPopover = $this->config->getUserValue($userId, $this->appName, 'skipPopover', 'no');
111
		$weekNumbers = $this->config->getUserValue($userId, $this->appName, 'showWeekNr', 'no');
112
		$firstRun = $this->config->getUserValue($userId, $this->appName, 'firstRun', null);
113
114
		// the default view will be saved as soon as a user
115
		// opens the calendar app, therefore this is a good
116
		// indication if the calendar was used before
117
		if ($firstRun === null) {
118
			if ($initialView === null) {
119
				$firstRun = 'yes';
120
			} else {
121 4
				$this->config->setUserValue($userId, $this->appName, 'firstRun', 'no');
122 4
				$firstRun = 'no';
123 4
			}
124 4
		}
125 4
126
		if ($initialView === null) {
127 4
			$initialView = 'month';
128
		}
129
130
		// TODO(artur): Duplicate: Refactor Language --> NC:Server:PersonalInfo.php
131
		$forceLanguage = $this->config->getSystemValue('force_language', false);
132
		if($forceLanguage !== false) {
133
			return [];
0 ignored issues
show
Bug Best Practice introduced by
The return type of return array(); (array) is incompatible with the return type documented by OCA\Calendar\Controller\ViewController::index of type OCP\AppFramework\Http\TemplateResponse.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
134
		}
135
136
		$userLang = $this->config->getUserValue($userId, 'core', 'lang', $this->l10nFactory->findLanguage());
137
		$languageCodes = $this->l10nFactory->findAvailableLanguages();
138
139
		$commonLanguages = [];
140
		$languages = [];
141
142
		foreach($languageCodes as $lang) {
143
			$l = \OC::$server->getL10N('settings', $lang);
144
			// TRANSLATORS this is the language name for the language switcher in the personal settings and should be the localized version
145
			$potentialName = (string) $l->t('__language_name__');
146
			if($l->getLanguageCode() === $lang && substr($potentialName, 0, 1) !== '_') {//first check if the language name is in the translation file
147
				$ln = array('code' => $lang, 'name' => $potentialName);
148
			} elseif ($lang === 'en') {
149
				$ln = ['code' => $lang, 'name' => 'English (US)'];
150 4
			}else{//fallback to language code
151 4
				$ln=array('code'=>$lang, 'name'=>$lang);
152 4
			}
153 4
154 4
			// put appropriate languages into appropriate arrays, to print them sorted
155
			// used language -> common languages -> divider -> other languages
156 4
			if ($lang === $userLang) {
157
				$userLang = $ln;
158 4
			} elseif (in_array($lang, self::COMMON_LANGUAGE_CODES)) {
159 4
				$commonLanguages[array_search($lang, self::COMMON_LANGUAGE_CODES)]=$ln;
160 4
			} else {
161 4
				$languages[]=$ln;
162
			}
163 4
		}
164
165
		// if user language is not available but set somehow: show the actual code as name
166
		if (!is_array($userLang)) {
167
			$userLang = [
168
				'code' => $userLang,
169
				'name' => $userLang,
170
			];
171
		}
172
173
		ksort($commonLanguages);
174
175
		// sort now by displayed language not the iso-code
176
		usort( $languages, function ($a, $b) {
177 View Code Duplication
			if ($a['code'] === $a['name'] && $b['code'] !== $b['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...
178
				// If a doesn't have a name, but b does, list b before a
179
				return 1;
180
			}
181 View Code Duplication
			if ($a['code'] !== $a['name'] && $b['code'] === $b['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...
182 15
				// If a does have a name, but b doesn't, list a before b
183 15
				return -1;
184 15
			}
185
			// Otherwise compare the names
186 15
			return strcmp($a['name'], $b['name']);
187 15
		});
188
189 15
		return new TemplateResponse('calendar', 'main', array_merge($templateParameters, [
190 15
			'initialView' => $initialView,
191 15
			'emailAddress' => $emailAddress,
192 15
			'skipPopover' => $skipPopover,
193
			'weekNumbers' => $weekNumbers,
194
			'firstRun' => $firstRun,
195 15
			'isPublic' => false,
196 15
			'isEmbedded' => false,
197 15
			'token' => '',
198 15
			'activelanguage' => $userLang,
199 15
			'commonlanguages' => $commonLanguages,
200 15
			'languages' => $languages
201
		]));
202
	}
203
204
	/**
205
	 * @PublicPage
206
	 * @NoCSRFRequired
207
	 *
208
	 * @param string $token
209 8
	 *
210 8
	 * @return TemplateResponse
211 8
	 */
212 8
	public function publicIndexWithBranding($token) {
213
		$templateParameters = $this->getTemplateParams();
214 8
		$publicTemplateParameters = $this->getPublicTemplateParameters($token);
215 8
		$params = array_merge($templateParameters, $publicTemplateParameters);
216
		$params['isEmbedded'] = false;
217 8
218 8
		return new TemplateResponse('calendar', 'public', $params, 'base');
219
	}
220 8
221
	/**
222 8
	 * @PublicPage
223 8
	 * @NoCSRFRequired
224
	 *
225
	 * @param string $token
226 8
	 *
227 8
	 * @return TemplateResponse
228 8
	 */
229 8
	public function publicIndexWithBrandingAndFancyName($token) {
230 8
		return $this->publicIndexWithBranding($token);
231
	}
232 8
233 8
	/**
234 8
	 * @PublicPage
235 8
	 * @NoCSRFRequired
236 8
	 *
237
	 * @param string $token
238
	 *
239
	 * @return TemplateResponse
240
	 */
241
	public function publicIndexForEmbedding($token) {
242
		$templateParameters = $this->getTemplateParams();
243
		$publicTemplateParameters = $this->getPublicTemplateParameters($token);
244
		$params = array_merge($templateParameters, $publicTemplateParameters);
245
		$params['isEmbedded'] = true;
246
247
		$response = new TemplateResponse('calendar', 'main', $params, 'public');
248
249
		$response->addHeader('X-Frame-Options', 'ALLOW');
250
		$csp = new ContentSecurityPolicy();
251
		$csp->addAllowedScriptDomain('*');
252
		$response->setContentSecurityPolicy($csp);
253
254
		return $response;
255
	}
256
257
	/**
258
	 * @PublicPage
259
	 * @NoCSRFRequired
260
	 *
261
	 * @param string $token
262
	 *
263
	 * @return TemplateResponse
264
	 */
265
	public function publicIndexForEmbeddingLegacy($token) {
266
		return $this->publicIndexForEmbedding($token);
267
	}
268
269
	/**
270
	 * get common parameters used for all three routes
271
	 * @return array
272
	 */
273
	private function getTemplateParams() {
274
		$runningOn = $this->config->getSystemValue('version');
275
		$runningOnNextcloud12OrLater = version_compare($runningOn, '12', '>=');
276
277
		$shareeCanEditShares = !$runningOnNextcloud12OrLater;
278
		$shareeCanEditCalendarProperties = $runningOnNextcloud12OrLater;
279
280
		$appVersion = $this->config->getAppValue($this->appName, 'installed_version');
281
		$isIE = $this->request->isUserAgent([Request::USER_AGENT_IE]);
282
		$defaultColor = $this->config->getAppValue('theming', 'color', '#0082C9');
283
		$canSharePublicLink = $this->config->getAppValue('core', 'shareapi_allow_links', 'yes');
284
285
		return [
286
			'appVersion' => $appVersion,
287
			'isIE' => $isIE,
288
			'defaultColor' => $defaultColor,
289
			'shareeCanEditShares' => $shareeCanEditShares ? 'yes' : 'no',
290
			'shareeCanEditCalendarProperties' => $shareeCanEditCalendarProperties ? 'yes' : 'no',
291
			'canSharePublicLink' => $canSharePublicLink,
292
		];
293
	}
294
295
	/**
296
	 * get common parameters for public sites
297
	 * @param string $token
298
	 * @return array
299
	 */
300
	private function getPublicTemplateParameters($token) {
301
		$shareURL = $this->request->getServerProtocol() . '://';
302
		$shareURL .= $this->request->getServerHost();
303
		$shareURL .= $this->request->getRequestUri();
304
305
		$relativeImagePath = $this->urlGenerator->imagePath('core', 'favicon-touch.png');
306
		$previewImage = $this->urlGenerator->getAbsoluteURL($relativeImagePath);
307
308
		$remoteBase = $this->urlGenerator->linkTo('', 'remote.php');
309
		$remoteBase .= '/dav/public-calendars/' . $token . '?export';
310
311
		$downloadUrl = $this->urlGenerator->getAbsoluteURL($remoteBase);
312
313
		$protocolLength = strlen($this->request->getServerProtocol()) + 3;
314
		$webcalUrl = 'webcal://' . substr($downloadUrl, $protocolLength);
315
316
		return [
317
			'initialView' => 'month',
318
			'emailAddress' => '',
319
			'skipPopover' => 'no',
320
			'weekNumbers' => 'no',
321
			'firstRun' => 'no',
322
			'isPublic' => true,
323
			'shareURL' => $shareURL,
324
			'previewImage' => $previewImage,
325
			'webcalURL' => $webcalUrl,
326
			'downloadURL' => $downloadUrl,
327
			'token' => $token,
328
		];
329
	}
330
}
331