Completed
Pull Request — master (#565)
by
unknown
19:23
created

ViewController::getPublicTemplateParameters()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 30
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 30
rs 8.8571
c 0
b 0
f 0
ccs 0
cts 0
cp 0
cc 1
eloc 23
nc 1
nop 1
crap 2
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 OCP\AppFramework\Controller;
27
use OCP\AppFramework\Http\ContentSecurityPolicy;
28
use OCP\AppFramework\Http\TemplateResponse;
29
use OCP\App\IAppManager;
30
use OCP\IConfig;
31
use OCP\IRequest;
32
use OCP\IURLGenerator;
33
use OCP\IUserSession;
34
use OC\AppFramework\Http\Request;
35
use OCP\IL10N;
36
use OCP\L10N\IFactory;
37
38
class ViewController extends Controller {
39
40
	/**
41
	 * @var IConfig
42
	 */
43
	private $config;
44
45
	/**
46
	 * @var IURLGenerator
47
	 */
48
	private $urlGenerator;
49
50
	/**
51
	 * @var IUserSession
52
	 */
53
	private $userSession;
54
55
	/**
56
	 * @var IAppManager
57
	 */
58
	private $appManager;
59 15
60
	/**
61 15
	 * @var IFactory
62 15
	 */
63 15
	private $l10nFactory;
64 15
65 15
	// TODO(artur): Duplicate: Refactor Language --> NC:Server:PersonalInfo.php
66
	const COMMON_LANGUAGE_CODES = [
67
		'en', 'es', 'fr', 'de', 'de_DE', 'ja', 'ar', 'ru', 'nl', 'it',
68
		'pt_BR', 'pt_PT', 'da', 'fi_FI', 'nb_NO', 'sv', 'tr', 'zh_CN', 'ko'
69
	];
70
71
	/**
72
	 * @var [type]
73 7
	 */
74 7
	private $l;
75
76 7
	/**
77 7
	 * @param string $appName
78 7
	 * @param IRequest $request an instance of the request
79
	 * @param IUserSession $userSession
80 7
	 * @param IConfig $config
81 7
	 * @param IURLGenerator $urlGenerator
82 7
	 * @param IAppManager $appManager
83 7
	 * @param IFactory $l10nFactory
84
	 * @param IL10N $l
85
	 */
86
	public function __construct(
87
		$appName,
88 7
		IRequest $request,
89 2
		IUserSession $userSession,
90 1
		IConfig $config,
91
		IURLGenerator $urlGenerator,
92 1
		IAppManager $appManager,
93 1
		IFactory $l10nFactory,
94
		IL10N $l
95
	) {
96
		parent::__construct($appName, $request);
97 7
		$this->config = $config;
98 2
		$this->userSession = $userSession;
99
		$this->urlGenerator = $urlGenerator;
100
		$this->appManager = $appManager;
101 7
		$this->l10nFactory = $l10nFactory;
102 7
		$this->l = $l;
103 7
	}
104 7
105 7
	/**
106 7
	 * @NoAdminRequired
107
	 * @NoCSRFRequired
108
	 *
109 7
	 * @return TemplateResponse
110
	 */
111
		public function index() {
112
		$templateParameters = $this->getTemplateParams();
113
114
		$userSession = $this->userSession->getUser();
115
		$userId = $userSession->getUID();
116
		$emailAddress = $userSession->getEMailAddress();
117
118
		$initialView = $this->config->getUserValue($userId, $this->appName, 'currentView', null);
119
		$skipPopover = $this->config->getUserValue($userId, $this->appName, 'skipPopover', 'no');
120
		$weekNumbers = $this->config->getUserValue($userId, $this->appName, 'showWeekNr', 'no');
121 4
		$firstRun = $this->config->getUserValue($userId, $this->appName, 'firstRun', null);
122 4
123 4
		// the default view will be saved as soon as a user
124 4
		// opens the calendar app, therefore this is a good
125 4
		// indication if the calendar was used before
126
		if ($firstRun === null) {
127 4
			if ($initialView === null) {
128
				$firstRun = 'yes';
129
			} else {
130
				$this->config->setUserValue($userId, $this->appName, 'firstRun', 'no');
131
				$firstRun = 'no';
132
			}
133
		}
134
135
		if ($initialView === null) {
136
			$initialView = 'month';
137
		}
138
139
		// TODO(artur): Duplicate: Refactor Language --> NC:Server:PersonalInfo.php
140
		$forceLanguage = $this->config->getSystemValue('force_language', false);
141
		if($forceLanguage !== false) {
142
			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...
143
		}
144
145
		$userLang = $this->config->getUserValue($userId, 'core', 'lang', $this->l10nFactory->findLanguage());
146
		$languageCodes = $this->l10nFactory->findAvailableLanguages();
147
148
		$commonLanguages = [];
149
		$languages = [];
150 4
151 4
		foreach($languageCodes as $lang) {
152 4
			$l = \OC::$server->getL10N('settings', $lang);
153 4
			// TRANSLATORS this is the language name for the language switcher in the personal settings and should be the localized version
154 4
			$potentialName = (string) $l->t('__language_name__');
155
			if($l->getLanguageCode() === $lang && substr($potentialName, 0, 1) !== '_') {//first check if the language name is in the translation file
156 4
				$ln = array('code' => $lang, 'name' => $potentialName);
157
			} elseif ($lang === 'en') {
158 4
				$ln = ['code' => $lang, 'name' => 'English (US)'];
159 4
			}else{//fallback to language code
160 4
				$ln=array('code'=>$lang, 'name'=>$lang);
161 4
			}
162
163 4
			// put appropriate languages into appropriate arrays, to print them sorted
164
			// used language -> common languages -> divider -> other languages
165
			if ($lang === $userLang) {
166
				$userLang = $ln;
167
			} elseif (in_array($lang, self::COMMON_LANGUAGE_CODES)) {
168
				$commonLanguages[array_search($lang, self::COMMON_LANGUAGE_CODES)]=$ln;
169
			} else {
170
				$languages[]=$ln;
171
			}
172
		}
173
174
		// if user language is not available but set somehow: show the actual code as name
175
		if (!is_array($userLang)) {
176
			$userLang = [
177
				'code' => $userLang,
178
				'name' => $userLang,
179
			];
180
		}
181
182 15
		ksort($commonLanguages);
183 15
184 15
		// sort now by displayed language not the iso-code
185
		usort( $languages, function ($a, $b) {
186 15 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...
187 15
				// If a doesn't have a name, but b does, list b before a
188
				return 1;
189 15
			}
190 15 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...
191 15
				// If a does have a name, but b doesn't, list a before b
192 15
				return -1;
193
			}
194
			// Otherwise compare the names
195 15
			return strcmp($a['name'], $b['name']);
196 15
		});
197 15
198 15
		return new TemplateResponse('calendar', 'main', array_merge($templateParameters, [
199 15
			'initialView' => $initialView,
200 15
			'emailAddress' => $emailAddress,
201
			'skipPopover' => $skipPopover,
202
			'weekNumbers' => $weekNumbers,
203
			'firstRun' => $firstRun,
204
			'isPublic' => false,
205
			'isEmbedded' => false,
206
			'token' => '',
207
			'isSpreedAvailable' => $this->appManager->isEnabledForUser('spreed', null),
208
			'activelanguage' => $userLang,
209 8
			'commonlanguages' => $commonLanguages,
210 8
			'languages' => $languages
211 8
		]));
212 8
	}
213
214 8
	/**
215 8
	 * @PublicPage
216
	 * @NoCSRFRequired
217 8
	 *
218 8
	 * @param string $token
219
	 *
220 8
	 * @return TemplateResponse
221
	 */
222 8
	public function publicIndexWithBranding($token) {
223 8
		$templateParameters = $this->getTemplateParams();
224
		$publicTemplateParameters = $this->getPublicTemplateParameters($token);
225
		$params = array_merge($templateParameters, $publicTemplateParameters);
226 8
		$params['isEmbedded'] = false;
227 8
228 8
		return new TemplateResponse('calendar', 'public', $params, 'base');
229 8
	}
230 8
231
	/**
232 8
	 * @PublicPage
233 8
	 * @NoCSRFRequired
234 8
	 *
235 8
	 * @param string $token
236 8
	 *
237
	 * @return TemplateResponse
238
	 */
239
	public function publicIndexWithBrandingAndFancyName($token) {
240
		return $this->publicIndexWithBranding($token);
241
	}
242
243
	/**
244
	 * @PublicPage
245
	 * @NoCSRFRequired
246
	 *
247
	 * @param string $token
248
	 *
249
	 * @return TemplateResponse
250
	 */
251
	public function publicIndexForEmbedding($token) {
252
		$templateParameters = $this->getTemplateParams();
253
		$publicTemplateParameters = $this->getPublicTemplateParameters($token);
254
		$params = array_merge($templateParameters, $publicTemplateParameters);
255
		$params['isEmbedded'] = true;
256
257
		$response = new TemplateResponse('calendar', 'main', $params, 'public');
258
259
		$response->addHeader('X-Frame-Options', 'ALLOW');
260
		$csp = new ContentSecurityPolicy();
261
		$csp->addAllowedScriptDomain('*');
262
		$response->setContentSecurityPolicy($csp);
263
264
		return $response;
265
	}
266
267
	/**
268
	 * @PublicPage
269
	 * @NoCSRFRequired
270
	 *
271
	 * @param string $token
272
	 *
273
	 * @return TemplateResponse
274
	 */
275
	public function publicIndexForEmbeddingLegacy($token) {
276
		return $this->publicIndexForEmbedding($token);
277
	}
278
279
	/**
280
	 * get common parameters used for all three routes
281
	 * @return array
282
	 */
283
	private function getTemplateParams() {
284
		$runningOn = $this->config->getSystemValue('version');
285
		$runningOnNextcloud12OrLater = version_compare($runningOn, '12', '>=');
286
287
		$shareeCanEditShares = !$runningOnNextcloud12OrLater;
288
		$shareeCanEditCalendarProperties = $runningOnNextcloud12OrLater;
289
290
		$appVersion = $this->config->getAppValue($this->appName, 'installed_version');
291
		$isIE = $this->request->isUserAgent([Request::USER_AGENT_IE]);
292
		$defaultColor = $this->config->getAppValue('theming', 'color', '#0082C9');
293
		$canSharePublicLink = $this->config->getAppValue('core', 'shareapi_allow_links', 'yes');
294
295
		return [
296
			'appVersion' => $appVersion,
297
			'isIE' => $isIE,
298
			'defaultColor' => $defaultColor,
299
			'shareeCanEditShares' => $shareeCanEditShares ? 'yes' : 'no',
300
			'shareeCanEditCalendarProperties' => $shareeCanEditCalendarProperties ? 'yes' : 'no',
301
			'canSharePublicLink' => $canSharePublicLink,
302
		];
303
	}
304
305
	/**
306
	 * get common parameters for public sites
307
	 * @param string $token
308
	 * @return array
309
	 */
310
	private function getPublicTemplateParameters($token) {
311
		$shareURL = $this->request->getServerProtocol() . '://';
312
		$shareURL .= $this->request->getServerHost();
313
		$shareURL .= $this->request->getRequestUri();
314
315
		$relativeImagePath = $this->urlGenerator->imagePath('core', 'favicon-touch.png');
316
		$previewImage = $this->urlGenerator->getAbsoluteURL($relativeImagePath);
317
318
		$remoteBase = $this->urlGenerator->linkTo('', 'remote.php');
319
		$remoteBase .= '/dav/public-calendars/' . $token . '?export';
320
321
		$downloadUrl = $this->urlGenerator->getAbsoluteURL($remoteBase);
322
323
		$protocolLength = strlen($this->request->getServerProtocol()) + 3;
324
		$webcalUrl = 'webcal://' . substr($downloadUrl, $protocolLength);
325
326
		return [
327
			'initialView' => 'month',
328
			'emailAddress' => '',
329
			'skipPopover' => 'no',
330
			'weekNumbers' => 'no',
331
			'firstRun' => 'no',
332
			'isPublic' => true,
333
			'shareURL' => $shareURL,
334
			'previewImage' => $previewImage,
335
			'webcalURL' => $webcalUrl,
336
			'downloadURL' => $downloadUrl,
337
			'token' => $token,
338
		];
339
	}
340
}
341