|
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 []; |
|
|
|
|
|
|
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']) { |
|
|
|
|
|
|
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']) { |
|
|
|
|
|
|
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
|
|
|
|
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:
Our function
my_functionexpects aPostobject, and outputs the author of the post. The base classPostreturns a simple string and outputting a simple string will work just fine. However, the child classBlogPostwhich is a sub-type ofPostinstead decided to return anobject, and is therefore violating the SOLID principles. If aBlogPostwere passed tomy_function, PHP would not complain, but ultimately fail when executing thestrtouppercall in its body.