Completed
Pull Request — master (#5623)
by Georg
218:40 queued 190:46
created
lib/public/L10N/IFactory.php 1 patch
Indentation   +57 added lines, -57 removed lines patch added patch discarded remove patch
@@ -25,68 +25,68 @@
 block discarded – undo
25 25
  * @since 8.2.0
26 26
  */
27 27
 interface IFactory {
28
-	/**
29
-	 * Get a language instance
30
-	 *
31
-	 * @param string $app
32
-	 * @param string|null $lang
33
-	 * @return \OCP\IL10N
34
-	 * @since 8.2.0
35
-	 */
36
-	public function get($app, $lang = null);
28
+    /**
29
+     * Get a language instance
30
+     *
31
+     * @param string $app
32
+     * @param string|null $lang
33
+     * @return \OCP\IL10N
34
+     * @since 8.2.0
35
+     */
36
+    public function get($app, $lang = null);
37 37
 
38
-	/**
39
-	 * Find the best language
40
-	 *
41
-	 * @param string|null $app App id or null for core
42
-	 * @return string language If nothing works it returns 'en'
43
-	 * @since 9.0.0
44
-	 */
45
-	public function findLanguage($app = null);
38
+    /**
39
+     * Find the best language
40
+     *
41
+     * @param string|null $app App id or null for core
42
+     * @return string language If nothing works it returns 'en'
43
+     * @since 9.0.0
44
+     */
45
+    public function findLanguage($app = null);
46 46
 
47
-	/**
48
-	 * @param string|null $lang user language as default locale
49
-	 * @return string locale If nothing works it returns 'en_US'
50
-	 * @since 13.0.0
51
-	 */
52
-	public function findLocale($lang = null);
47
+    /**
48
+     * @param string|null $lang user language as default locale
49
+     * @return string locale If nothing works it returns 'en_US'
50
+     * @since 13.0.0
51
+     */
52
+    public function findLocale($lang = null);
53 53
 
54
-	/**
55
-	 * Find all available languages for an app
56
-	 *
57
-	 * @param string|null $app App id or null for core
58
-	 * @return string[] an array of available languages
59
-	 * @since 9.0.0
60
-	 */
61
-	public function findAvailableLanguages($app = null);
54
+    /**
55
+     * Find all available languages for an app
56
+     *
57
+     * @param string|null $app App id or null for core
58
+     * @return string[] an array of available languages
59
+     * @since 9.0.0
60
+     */
61
+    public function findAvailableLanguages($app = null);
62 62
 
63
-	/**
64
-	 * @return array an array of available
65
-	 * @since 13.0.0
66
-	 */
67
-	public function findAvailableLocales();
63
+    /**
64
+     * @return array an array of available
65
+     * @since 13.0.0
66
+     */
67
+    public function findAvailableLocales();
68 68
 
69
-	/**
70
-	 * @param string|null $app App id or null for core
71
-	 * @param string $lang
72
-	 * @return bool
73
-	 * @since 9.0.0
74
-	 */
75
-	public function languageExists($app, $lang);
69
+    /**
70
+     * @param string|null $app App id or null for core
71
+     * @param string $lang
72
+     * @return bool
73
+     * @since 9.0.0
74
+     */
75
+    public function languageExists($app, $lang);
76 76
 
77
-	/**
78
-	 * @param string $locale
79
-	 * @return bool
80
-	 * @since 13.0.0
81
-	 */
82
-	public function localeExists($locale);
77
+    /**
78
+     * @param string $locale
79
+     * @return bool
80
+     * @since 13.0.0
81
+     */
82
+    public function localeExists($locale);
83 83
 
84
-	/**
85
-	 * Creates a function from the plural string
86
-	 *
87
-	 * @param string $string
88
-	 * @return string Unique function name
89
-	 * @since 9.0.0
90
-	 */
91
-	public function createPluralFunction($string);
84
+    /**
85
+     * Creates a function from the plural string
86
+     *
87
+     * @param string $string
88
+     * @return string Unique function name
89
+     * @since 9.0.0
90
+     */
91
+    public function createPluralFunction($string);
92 92
 }
Please login to merge, or discard this patch.
settings/templates/settings/personal/personal.info.php 1 patch
Spacing   +64 added lines, -64 removed lines patch added patch discarded remove patch
@@ -71,7 +71,7 @@  discard block
 block discarded – undo
71 71
 					</div>
72 72
 				</div>
73 73
 				<span class="icon-checkmark hidden"></span>
74
-				<?php if($_['lookupServerUploadEnabled']) { ?>
74
+				<?php if ($_['lookupServerUploadEnabled']) { ?>
75 75
 				<input type="hidden" id="avatarscope" value="<?php p($_['avatarScope']) ?>">
76 76
 				<?php } ?>
77 77
 			</form>
@@ -89,14 +89,14 @@  discard block
 block discarded – undo
89 89
 					<p class="quotatext">
90 90
 						<?php if ($_['quota'] === \OCP\Files\FileInfo::SPACE_UNLIMITED): ?>
91 91
 							<?php print_unescaped($l->t('You are using <strong>%s</strong>',
92
-								[$_['usage']]));?>
92
+								[$_['usage']])); ?>
93 93
 						<?php else: ?>
94 94
 							<?php print_unescaped($l->t('You are using <strong>%s</strong> of <strong>%s</strong> (<strong>%s %%</strong>)',
95
-								[$_['usage'], $_['total_space'],  $_['usage_relative']]));?>
95
+								[$_['usage'], $_['total_space'], $_['usage_relative']])); ?>
96 96
 						<?php endif ?>
97 97
 					</p>
98 98
 				</div>
99
-				<progress value="<?php p($_['usage_relative']); ?>" max="100"<?php if($_['usage_relative'] > 80): ?> class="warn" <?php endif; ?>></progress>
99
+				<progress value="<?php p($_['usage_relative']); ?>" max="100"<?php if ($_['usage_relative'] > 80): ?> class="warn" <?php endif; ?>></progress>
100 100
 			</div>
101 101
 		</div>
102 102
 	</div>
@@ -113,15 +113,15 @@  discard block
 block discarded – undo
113 113
 					</div>
114 114
 				</h2>
115 115
 				<input type="text" id="displayname" name="displayname"
116
-					<?php if(!$_['displayNameChangeSupported']) { print_unescaped('class="hidden"'); } ?>
116
+					<?php if (!$_['displayNameChangeSupported']) { print_unescaped('class="hidden"'); } ?>
117 117
 					   value="<?php p($_['displayName']) ?>"
118 118
 					   autocomplete="on" autocapitalize="none" autocorrect="off" />
119
-				<?php if(!$_['displayNameChangeSupported']) { ?>
120
-					<span><?php if(isset($_['displayName']) && !empty($_['displayName'])) { p($_['displayName']); } else { p($l->t('No display name set')); } ?></span>
119
+				<?php if (!$_['displayNameChangeSupported']) { ?>
120
+					<span><?php if (isset($_['displayName']) && !empty($_['displayName'])) { p($_['displayName']); } else { p($l->t('No display name set')); } ?></span>
121 121
 				<?php } ?>
122 122
 				<span class="icon-checkmark hidden"></span>
123 123
 				<span class="icon-error hidden" ></span>
124
-				<?php if($_['lookupServerUploadEnabled']) { ?>
124
+				<?php if ($_['lookupServerUploadEnabled']) { ?>
125 125
 					<input type="hidden" id="displaynamescope" value="<?php p($_['displayNameScope']) ?>">
126 126
 				<?php } ?>
127 127
 			</form>
@@ -136,10 +136,10 @@  discard block
 block discarded – undo
136 136
 						</span>
137 137
 					</div>
138 138
 				</h2>
139
-				<div class="verify <?php if ($_['email'] === ''  || $_['emailScope'] !== 'public') p('hidden'); ?>">
139
+				<div class="verify <?php if ($_['email'] === '' || $_['emailScope'] !== 'public') p('hidden'); ?>">
140 140
 					<img id="verify-email" title="<?php p($_['emailMessage']); ?>" data-status="<?php p($_['emailVerification']) ?>" src="
141 141
 				<?php
142
-					switch($_['emailVerification']) {
142
+					switch ($_['emailVerification']) {
143 143
 						case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
144 144
 							p(image_path('core', 'actions/verifying.svg'));
145 145
 							break;
@@ -152,18 +152,18 @@  discard block
 block discarded – undo
152 152
 					?>">
153 153
 				</div>
154 154
 				<input type="email" name="email" id="email" value="<?php p($_['email']); ?>"
155
-					<?php if(!$_['displayNameChangeSupported']) { print_unescaped('class="hidden"'); } ?>
155
+					<?php if (!$_['displayNameChangeSupported']) { print_unescaped('class="hidden"'); } ?>
156 156
 					   placeholder="<?php p($l->t('Your email address')); ?>"
157 157
 					   autocomplete="on" autocapitalize="none" autocorrect="off" />
158 158
 			   	<span class="icon-checkmark hidden"></span>
159 159
 				<span class="icon-error hidden" ></span>
160
-				<?php if(!$_['displayNameChangeSupported']) { ?>
161
-					<span><?php if(isset($_['email']) && !empty($_['email'])) { p($_['email']); } else { p($l->t('No email address set')); }?></span>
160
+				<?php if (!$_['displayNameChangeSupported']) { ?>
161
+					<span><?php if (isset($_['email']) && !empty($_['email'])) { p($_['email']); } else { p($l->t('No email address set')); }?></span>
162 162
 				<?php } ?>
163
-				<?php if($_['displayNameChangeSupported']) { ?>
163
+				<?php if ($_['displayNameChangeSupported']) { ?>
164 164
 					<em><?php p($l->t('For password reset and notifications')); ?></em>
165 165
 				<?php } ?>
166
-				<?php if($_['lookupServerUploadEnabled']) { ?>
166
+				<?php if ($_['lookupServerUploadEnabled']) { ?>
167 167
 					<input type="hidden" id="emailscope" value="<?php p($_['emailScope']) ?>">
168 168
 				<?php } ?>
169 169
 			</form>
@@ -179,12 +179,12 @@  discard block
 block discarded – undo
179 179
 						</span>
180 180
 					</div>
181 181
 				</h2>
182
-				<input type="tel" id="phone" name="phone" <?php if(!$_['lookupServerUploadEnabled']) print_unescaped('disabled="1"'); ?>
182
+				<input type="tel" id="phone" name="phone" <?php if (!$_['lookupServerUploadEnabled']) print_unescaped('disabled="1"'); ?>
183 183
 					   value="<?php p($_['phone']) ?>"
184 184
 					   placeholder="<?php p($l->t('Your phone number')); ?>"
185 185
 				       autocomplete="on" autocapitalize="none" autocorrect="off" />
186 186
 				<span class="icon-checkmark hidden"></span>
187
-				<?php if($_['lookupServerUploadEnabled']) { ?>
187
+				<?php if ($_['lookupServerUploadEnabled']) { ?>
188 188
 				<input type="hidden" id="phonescope" value="<?php p($_['phoneScope']) ?>">
189 189
 				<?php } ?>
190 190
 			</form>
@@ -201,12 +201,12 @@  discard block
 block discarded – undo
201 201
 						</span>
202 202
 					</div>
203 203
 				</h2>
204
-				<input type="text" id="address" name="address" <?php if(!$_['lookupServerUploadEnabled']) print_unescaped('disabled="1"');  ?>
204
+				<input type="text" id="address" name="address" <?php if (!$_['lookupServerUploadEnabled']) print_unescaped('disabled="1"'); ?>
205 205
 					   placeholder="<?php p($l->t('Your postal address')); ?>"
206 206
 					   value="<?php p($_['address']) ?>"
207 207
 					   autocomplete="on" autocapitalize="none" autocorrect="off" />
208 208
 				<span class="icon-checkmark hidden"></span>
209
-				<?php if($_['lookupServerUploadEnabled']) { ?>
209
+				<?php if ($_['lookupServerUploadEnabled']) { ?>
210 210
 				<input type="hidden" id="addressscope" value="<?php p($_['addressScope']) ?>">
211 211
 				<?php } ?>
212 212
 			</form>
@@ -223,11 +223,11 @@  discard block
 block discarded – undo
223 223
 						</span>
224 224
 					</div>
225 225
 				</h2>
226
-				<?php if($_['lookupServerUploadEnabled']) { ?>
227
-				<div class="verify <?php if ($_['website'] === ''  || $_['websiteScope'] !== 'public') p('hidden'); ?>">
226
+				<?php if ($_['lookupServerUploadEnabled']) { ?>
227
+				<div class="verify <?php if ($_['website'] === '' || $_['websiteScope'] !== 'public') p('hidden'); ?>">
228 228
 					<img id="verify-website" title="<?php p($_['websiteMessage']); ?>" data-status="<?php p($_['websiteVerification']) ?>" src="
229 229
 					<?php
230
-					switch($_['websiteVerification']) {
230
+					switch ($_['websiteVerification']) {
231 231
 						case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
232 232
 							p(image_path('core', 'actions/verifying.svg'));
233 233
 							break;
@@ -238,13 +238,13 @@  discard block
 block discarded – undo
238 238
 							p(image_path('core', 'actions/verify.svg'));
239 239
 					}
240 240
 					?>"
241
-					<?php if($_['websiteVerification'] === \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS || $_['websiteVerification'] === \OC\Accounts\AccountManager::NOT_VERIFIED) print_unescaped(' class="verify-action"') ?>
241
+					<?php if ($_['websiteVerification'] === \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS || $_['websiteVerification'] === \OC\Accounts\AccountManager::NOT_VERIFIED) print_unescaped(' class="verify-action"') ?>
242 242
 					>
243 243
 					<div class="verification-dialog popovermenu bubble menu">
244 244
 						<div class="verification-dialog-content">
245 245
 							<p class="explainVerification"></p>
246 246
 							<p class="verificationCode"></p>
247
-							<p><?php p($l->t('It can take up to 24 hours before the account is displayed as verified.'));?></p>
247
+							<p><?php p($l->t('It can take up to 24 hours before the account is displayed as verified.')); ?></p>
248 248
 						</div>
249 249
 					</div>
250 250
 				</div>
@@ -252,10 +252,10 @@  discard block
 block discarded – undo
252 252
 				<input type="url" name="website" id="website" value="<?php p($_['website']); ?>"
253 253
 				       placeholder="<?php p($l->t('Link https://…')); ?>"
254 254
 				       autocomplete="on" autocapitalize="none" autocorrect="off"
255
-					   <?php if(!$_['lookupServerUploadEnabled']) print_unescaped('disabled="1"');  ?>
255
+					   <?php if (!$_['lookupServerUploadEnabled']) print_unescaped('disabled="1"'); ?>
256 256
 				/>
257 257
 				<span class="icon-checkmark hidden"></span>
258
-				<?php if($_['lookupServerUploadEnabled']) { ?>
258
+				<?php if ($_['lookupServerUploadEnabled']) { ?>
259 259
 				<input type="hidden" id="websitescope" value="<?php p($_['websiteScope']) ?>">
260 260
 				<?php } ?>
261 261
 			</form>
@@ -272,11 +272,11 @@  discard block
 block discarded – undo
272 272
 						</span>
273 273
 					</div>
274 274
 				</h2>
275
-				<?php if($_['lookupServerUploadEnabled']) { ?>
276
-				<div class="verify <?php if ($_['twitter'] === ''  || $_['twitterScope'] !== 'public') p('hidden'); ?>">
275
+				<?php if ($_['lookupServerUploadEnabled']) { ?>
276
+				<div class="verify <?php if ($_['twitter'] === '' || $_['twitterScope'] !== 'public') p('hidden'); ?>">
277 277
 					<img id="verify-twitter" title="<?php p($_['twitterMessage']); ?>" data-status="<?php p($_['twitterVerification']) ?>" src="
278 278
 					<?php
279
-					switch($_['twitterVerification']) {
279
+					switch ($_['twitterVerification']) {
280 280
 						case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
281 281
 							p(image_path('core', 'actions/verifying.svg'));
282 282
 							break;
@@ -287,13 +287,13 @@  discard block
 block discarded – undo
287 287
 							p(image_path('core', 'actions/verify.svg'));
288 288
 					}
289 289
 					?>"
290
-					<?php if($_['twitterVerification'] === \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS || $_['twitterVerification'] === \OC\Accounts\AccountManager::NOT_VERIFIED) print_unescaped(' class="verify-action"') ?>
290
+					<?php if ($_['twitterVerification'] === \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS || $_['twitterVerification'] === \OC\Accounts\AccountManager::NOT_VERIFIED) print_unescaped(' class="verify-action"') ?>
291 291
 					>
292 292
 					<div class="verification-dialog popovermenu bubble menu">
293 293
 						<div class="verification-dialog-content">
294 294
 							<p class="explainVerification"></p>
295 295
 							<p class="verificationCode"></p>
296
-							<p><?php p($l->t('It can take up to 24 hours before the account is displayed as verified.'));?></p>
296
+							<p><?php p($l->t('It can take up to 24 hours before the account is displayed as verified.')); ?></p>
297 297
 						</div>
298 298
 					</div>
299 299
 				</div>
@@ -301,10 +301,10 @@  discard block
 block discarded – undo
301 301
 				<input type="text" name="twitter" id="twitter" value="<?php p($_['twitter']); ?>"
302 302
 					   placeholder="<?php p($l->t('Twitter handle @…')); ?>"
303 303
 					   autocomplete="on" autocapitalize="none" autocorrect="off"
304
-					   <?php if(!$_['lookupServerUploadEnabled']) print_unescaped('disabled="1"');  ?>
304
+					   <?php if (!$_['lookupServerUploadEnabled']) print_unescaped('disabled="1"'); ?>
305 305
 				/>
306 306
 				<span class="icon-checkmark hidden"></span>
307
-				<?php if($_['lookupServerUploadEnabled']) { ?>
307
+				<?php if ($_['lookupServerUploadEnabled']) { ?>
308 308
 				<input type="hidden" id="twitterscope" value="<?php p($_['twitterScope']) ?>">
309 309
 				<?php } ?>
310 310
 			</form>
@@ -317,54 +317,54 @@  discard block
 block discarded – undo
317 317
 			<?php if (isset($_['activelanguage'])) { ?>
318 318
 				<form id="language" class="section">
319 319
 					<h2>
320
-						<label for="languageinput"><?php p($l->t('Language'));?></label>
320
+						<label for="languageinput"><?php p($l->t('Language')); ?></label>
321 321
 					</h2>
322
-					<select id="languageinput" name="lang" data-placeholder="<?php p($l->t('Language'));?>">
323
-						<option value="<?php p($_['activelanguage']['code']);?>">
324
-							<?php p($_['activelanguage']['name']);?>
322
+					<select id="languageinput" name="lang" data-placeholder="<?php p($l->t('Language')); ?>">
323
+						<option value="<?php p($_['activelanguage']['code']); ?>">
324
+							<?php p($_['activelanguage']['name']); ?>
325 325
 						</option>
326
-						<?php foreach($_['commonlanguages'] as $language):?>
327
-							<option value="<?php p($language['code']);?>">
328
-								<?php p($language['name']);?>
326
+						<?php foreach ($_['commonlanguages'] as $language):?>
327
+							<option value="<?php p($language['code']); ?>">
328
+								<?php p($language['name']); ?>
329 329
 							</option>
330
-						<?php endforeach;?>
330
+						<?php endforeach; ?>
331 331
 						<optgroup label="––––––––––"></optgroup>
332
-						<?php foreach($_['languages'] as $language):?>
333
-							<option value="<?php p($language['code']);?>">
334
-								<?php p($language['name']);?>
332
+						<?php foreach ($_['languages'] as $language):?>
333
+							<option value="<?php p($language['code']); ?>">
334
+								<?php p($language['name']); ?>
335 335
 							</option>
336
-						<?php endforeach;?>
336
+						<?php endforeach; ?>
337 337
 					</select>
338 338
 					<a href="https://www.transifex.com/nextcloud/nextcloud/"
339 339
 					   target="_blank" rel="noreferrer noopener">
340
-						<em><?php p($l->t('Help translate'));?></em>
340
+						<em><?php p($l->t('Help translate')); ?></em>
341 341
 					</a>
342 342
 				</form>
343 343
 			<?php } ?>
344 344
 			<?php if (isset($_['activelocale'])) { ?>
345 345
 				<form id="locale" class="section">
346 346
 					<h2>
347
-						<label for="localeinput"><?php p($l->t('Locale'));?></label>
347
+						<label for="localeinput"><?php p($l->t('Locale')); ?></label>
348 348
 					</h2>
349
-					<select id="localeinput" name="lang" data-placeholder="<?php p($l->t('Locale'));?>">
350
-						<option value="<?php p($_['activelocale']['code']);?>">
351
-							<?php p($_['activelocale']['name']);?>
349
+					<select id="localeinput" name="lang" data-placeholder="<?php p($l->t('Locale')); ?>">
350
+						<option value="<?php p($_['activelocale']['code']); ?>">
351
+							<?php p($_['activelocale']['name']); ?>
352 352
 						</option>
353 353
 						<optgroup label="––––––––––"></optgroup>
354
-						<?php foreach($_['localesforlanguage'] as $locale):?>
355
-							<option value="<?php p($locale['code']);?>">
356
-								<?php p($locale['name']);?>
354
+						<?php foreach ($_['localesforlanguage'] as $locale):?>
355
+							<option value="<?php p($locale['code']); ?>">
356
+								<?php p($locale['name']); ?>
357 357
 							</option>
358
-						<?php endforeach;?>
358
+						<?php endforeach; ?>
359 359
 						<optgroup label="––––––––––"></optgroup>
360
-						<option value="<?php p($_['activelocale']['code']);?>">
361
-							<?php p($_['activelocale']['name']);?>
360
+						<option value="<?php p($_['activelocale']['code']); ?>">
361
+							<?php p($_['activelocale']['name']); ?>
362 362
 						</option>
363
-						<?php foreach($_['locales'] as $locale):?>
364
-							<option value="<?php p($locale['code']);?>">
365
-								<?php p($locale['name']);?>
363
+						<?php foreach ($_['locales'] as $locale):?>
364
+							<option value="<?php p($locale['code']); ?>">
365
+								<?php p($locale['name']); ?>
366 366
 							</option>
367
-						<?php endforeach;?>
367
+						<?php endforeach; ?>
368 368
 					</select>
369 369
 					<div id="localeexample">
370 370
 						<p id="localeexample-time"></p>
@@ -376,20 +376,20 @@  discard block
 block discarded – undo
376 376
 		</div>
377 377
 		<div class="personal-settings-setting-box personal-settings-password-box">
378 378
 			<?php
379
-			if($_['passwordChangeSupported']) {
379
+			if ($_['passwordChangeSupported']) {
380 380
 				script('jquery-showpassword');
381 381
 				?>
382 382
 				<form id="passwordform" class="section">
383
-					<h2 class="inlineblock"><?php p($l->t('Password'));?></h2>
383
+					<h2 class="inlineblock"><?php p($l->t('Password')); ?></h2>
384 384
 					<div id="password-error-msg" class="msg success inlineblock" style="display: none;">Saved</div>
385 385
 
386 386
 					<label for="pass1" class="hidden-visually"><?php p($l->t('Current password')); ?>: </label>
387 387
 					<input type="password" id="pass1" name="oldpassword"
388
-						   placeholder="<?php p($l->t('Current password'));?>"
388
+						   placeholder="<?php p($l->t('Current password')); ?>"
389 389
 						   autocomplete="off" autocapitalize="none" autocorrect="off" />
390 390
 
391 391
 					<div class="personal-show-container">
392
-						<label for="pass2" class="hidden-visually"><?php p($l->t('New password'));?>: </label>
392
+						<label for="pass2" class="hidden-visually"><?php p($l->t('New password')); ?>: </label>
393 393
 						<input type="password" id="pass2" name="newpassword"
394 394
 							   placeholder="<?php p($l->t('New password')); ?>"
395 395
 							   data-typetoggle="#personal-show"
Please login to merge, or discard this patch.
lib/public/IL10N.php 2 patches
Indentation   +68 added lines, -68 removed lines patch added patch discarded remove patch
@@ -43,77 +43,77 @@
 block discarded – undo
43 43
  * @since 6.0.0
44 44
  */
45 45
 interface IL10N {
46
-	/**
47
-	 * Translating
48
-	 * @param string $text The text we need a translation for
49
-	 * @param array|string $parameters default:array() Parameters for sprintf
50
-	 * @return string Translation or the same text
51
-	 *
52
-	 * Returns the translation. If no translation is found, $text will be
53
-	 * returned.
54
-	 * @since 6.0.0
55
-	 */
56
-	public function t(string $text, $parameters = []): string;
46
+    /**
47
+     * Translating
48
+     * @param string $text The text we need a translation for
49
+     * @param array|string $parameters default:array() Parameters for sprintf
50
+     * @return string Translation or the same text
51
+     *
52
+     * Returns the translation. If no translation is found, $text will be
53
+     * returned.
54
+     * @since 6.0.0
55
+     */
56
+    public function t(string $text, $parameters = []): string;
57 57
 
58
-	/**
59
-	 * Translating
60
-	 * @param string $text_singular the string to translate for exactly one object
61
-	 * @param string $text_plural the string to translate for n objects
62
-	 * @param integer $count Number of objects
63
-	 * @param array $parameters default:array() Parameters for sprintf
64
-	 * @return string Translation or the same text
65
-	 *
66
-	 * Returns the translation. If no translation is found, $text will be
67
-	 * returned. %n will be replaced with the number of objects.
68
-	 *
69
-	 * The correct plural is determined by the plural_forms-function
70
-	 * provided by the po file.
71
-	 * @since 6.0.0
72
-	 *
73
-	 */
74
-	public function n(string $text_singular, string $text_plural, int $count, array $parameters = []): string;
58
+    /**
59
+     * Translating
60
+     * @param string $text_singular the string to translate for exactly one object
61
+     * @param string $text_plural the string to translate for n objects
62
+     * @param integer $count Number of objects
63
+     * @param array $parameters default:array() Parameters for sprintf
64
+     * @return string Translation or the same text
65
+     *
66
+     * Returns the translation. If no translation is found, $text will be
67
+     * returned. %n will be replaced with the number of objects.
68
+     *
69
+     * The correct plural is determined by the plural_forms-function
70
+     * provided by the po file.
71
+     * @since 6.0.0
72
+     *
73
+     */
74
+    public function n(string $text_singular, string $text_plural, int $count, array $parameters = []): string;
75 75
 
76
-	/**
77
-	 * Localization
78
-	 * @param string $type Type of localization
79
-	 * @param \DateTime|int|string $data parameters for this localization
80
-	 * @param array $options currently supports following options:
81
-	 * 			- 'width': handed into \Punic\Calendar::formatDate as second parameter
82
-	 * @return string|int|false
83
-	 *
84
-	 * Returns the localized data.
85
-	 *
86
-	 * Implemented types:
87
-	 *  - date
88
-	 *    - Creates a date
89
-	 *    - l10n-field: date
90
-	 *    - params: timestamp (int/string)
91
-	 *  - datetime
92
-	 *    - Creates date and time
93
-	 *    - l10n-field: datetime
94
-	 *    - params: timestamp (int/string)
95
-	 *  - time
96
-	 *    - Creates a time
97
-	 *    - l10n-field: time
98
-	 *    - params: timestamp (int/string)
99
-	 * @since 6.0.0 - parameter $options was added in 8.0.0
100
-	 */
101
-	public function l(string $type, $data, array $options = []);
76
+    /**
77
+     * Localization
78
+     * @param string $type Type of localization
79
+     * @param \DateTime|int|string $data parameters for this localization
80
+     * @param array $options currently supports following options:
81
+     * 			- 'width': handed into \Punic\Calendar::formatDate as second parameter
82
+     * @return string|int|false
83
+     *
84
+     * Returns the localized data.
85
+     *
86
+     * Implemented types:
87
+     *  - date
88
+     *    - Creates a date
89
+     *    - l10n-field: date
90
+     *    - params: timestamp (int/string)
91
+     *  - datetime
92
+     *    - Creates date and time
93
+     *    - l10n-field: datetime
94
+     *    - params: timestamp (int/string)
95
+     *  - time
96
+     *    - Creates a time
97
+     *    - l10n-field: time
98
+     *    - params: timestamp (int/string)
99
+     * @since 6.0.0 - parameter $options was added in 8.0.0
100
+     */
101
+    public function l(string $type, $data, array $options = []);
102 102
 
103 103
 
104
-	/**
105
-	 * The code (en, de, ...) of the language that is used for this IL10N object
106
-	 *
107
-	 * @return string language
108
-	 * @since 7.0.0
109
-	 */
110
-	public function getLanguageCode(): string ;
104
+    /**
105
+     * The code (en, de, ...) of the language that is used for this IL10N object
106
+     *
107
+     * @return string language
108
+     * @since 7.0.0
109
+     */
110
+    public function getLanguageCode(): string ;
111 111
 
112
-	/**
113
-	 * * The code (en_US, fr_CA, ...) of the locale that is used for this IL10N object
114
-	 *
115
-	 * @return string locale
116
-	 * @since 13.0.0
117
-	 */
118
-	public function getLocaleCode();
112
+    /**
113
+     * * The code (en_US, fr_CA, ...) of the locale that is used for this IL10N object
114
+     *
115
+     * @return string locale
116
+     * @since 13.0.0
117
+     */
118
+    public function getLocaleCode();
119 119
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -107,7 +107,7 @@
 block discarded – undo
107 107
 	 * @return string language
108 108
 	 * @since 7.0.0
109 109
 	 */
110
-	public function getLanguageCode(): string ;
110
+	public function getLanguageCode(): string;
111 111
 
112 112
 	/**
113 113
 	 * * The code (en_US, fr_CA, ...) of the locale that is used for this IL10N object
Please login to merge, or discard this patch.
lib/private/TemplateLayout.php 2 patches
Indentation   +282 added lines, -282 removed lines patch added patch discarded remove patch
@@ -45,286 +45,286 @@
 block discarded – undo
45 45
 
46 46
 class TemplateLayout extends \OC_Template {
47 47
 
48
-	private static $versionHash = '';
49
-
50
-	/**
51
-	 * @var \OCP\IConfig
52
-	 */
53
-	private $config;
54
-
55
-	/**
56
-	 * @param string $renderAs
57
-	 * @param string $appId application id
58
-	 */
59
-	public function __construct( $renderAs, $appId = '' ) {
60
-
61
-		// yes - should be injected ....
62
-		$this->config = \OC::$server->getConfig();
63
-
64
-
65
-		// Decide which page we show
66
-		if($renderAs == 'user') {
67
-			parent::__construct( 'core', 'layout.user' );
68
-			if(in_array(\OC_App::getCurrentApp(), ['settings','admin', 'help']) !== false) {
69
-				$this->assign('bodyid', 'body-settings');
70
-			}else{
71
-				$this->assign('bodyid', 'body-user');
72
-			}
73
-
74
-			// Code integrity notification
75
-			$integrityChecker = \OC::$server->getIntegrityCodeChecker();
76
-			if(\OC_User::isAdminUser(\OC_User::getUser()) && $integrityChecker->isCodeCheckEnforced() && !$integrityChecker->hasPassedCheck()) {
77
-				\OCP\Util::addScript('core', 'integritycheck-failed-notification');
78
-			}
79
-
80
-			// Add navigation entry
81
-			$this->assign( 'application', '');
82
-			$this->assign( 'appid', $appId );
83
-			$navigation = \OC::$server->getNavigationManager()->getAll();
84
-			$this->assign( 'navigation', $navigation);
85
-			$settingsNavigation = \OC::$server->getNavigationManager()->getAll('settings');
86
-			$this->assign( 'settingsnavigation', $settingsNavigation);
87
-			foreach($navigation as $entry) {
88
-				if ($entry['active']) {
89
-					$this->assign( 'application', $entry['name'] );
90
-					break;
91
-				}
92
-			}
93
-
94
-			foreach($settingsNavigation as $entry) {
95
-				if ($entry['active']) {
96
-					$this->assign( 'application', $entry['name'] );
97
-					break;
98
-				}
99
-			}
100
-			$userDisplayName = \OC_User::getDisplayName();
101
-			$this->assign('user_displayname', $userDisplayName);
102
-			$this->assign('user_uid', \OC_User::getUser());
103
-
104
-			if (\OC_User::getUser() === false) {
105
-				$this->assign('userAvatarSet', false);
106
-			} else {
107
-				$this->assign('userAvatarSet', \OC::$server->getAvatarManager()->getAvatar(\OC_User::getUser())->exists());
108
-				$this->assign('userAvatarVersion', $this->config->getUserValue(\OC_User::getUser(), 'avatar', 'version', 0));
109
-			}
110
-
111
-			// check if app menu icons should be inverted
112
-			try {
113
-				/** @var \OCA\Theming\Util $util */
114
-				$util = \OC::$server->query(\OCA\Theming\Util::class);
115
-				$this->assign('themingInvertMenu', $util->invertTextColor(\OC::$server->getThemingDefaults()->getColorPrimary()));
116
-			} catch (\OCP\AppFramework\QueryException $e) {
117
-				$this->assign('themingInvertMenu', false);
118
-			}
119
-
120
-		} else if ($renderAs == 'error') {
121
-			parent::__construct('core', 'layout.guest', '', false);
122
-			$this->assign('bodyid', 'body-login');
123
-		} else if ($renderAs == 'guest') {
124
-			parent::__construct('core', 'layout.guest');
125
-			$this->assign('bodyid', 'body-login');
126
-		} else if ($renderAs == 'public') {
127
-			parent::__construct('core', 'layout.public');
128
-			$this->assign( 'appid', $appId );
129
-			$this->assign('bodyid', 'body-public');
130
-		} else {
131
-			parent::__construct('core', 'layout.base');
132
-
133
-		}
134
-		// Send the language and the locale to our layouts
135
-		$lang = \OC::$server->getL10NFactory()->findLanguage();
136
-		$lang = str_replace('_', '-', $lang);
137
-		$this->assign('language', $lang);
138
-		$this->assign('locale', \OC::$server->getL10NFactory()->findLocale());
139
-
140
-		if(\OC::$server->getSystemConfig()->getValue('installed', false)) {
141
-			if (empty(self::$versionHash)) {
142
-				$v = \OC_App::getAppVersions();
143
-				$v['core'] = implode('.', \OCP\Util::getVersion());
144
-				self::$versionHash = substr(md5(implode(',', $v)), 0, 8);
145
-			}
146
-		} else {
147
-			self::$versionHash = md5('not installed');
148
-		}
149
-
150
-		// Add the js files
151
-		$jsFiles = self::findJavascriptFiles(\OC_Util::$scripts);
152
-		$this->assign('jsfiles', array());
153
-		if ($this->config->getSystemValue('installed', false) && $renderAs != 'error') {
154
-			if (\OC::$server->getContentSecurityPolicyNonceManager()->browserSupportsCspV3()) {
155
-				$jsConfigHelper = new JSConfigHelper(
156
-					\OC::$server->getL10N('lib'),
157
-					\OC::$server->query(Defaults::class),
158
-					\OC::$server->getAppManager(),
159
-					\OC::$server->getSession(),
160
-					\OC::$server->getUserSession()->getUser(),
161
-					$this->config,
162
-					\OC::$server->getGroupManager(),
163
-					\OC::$server->getIniWrapper(),
164
-					\OC::$server->getURLGenerator(),
165
-					\OC::$server->getCapabilitiesManager()
166
-				);
167
-				$this->assign('inline_ocjs', $jsConfigHelper->getConfig());
168
-			} else {
169
-				$this->append('jsfiles', \OC::$server->getURLGenerator()->linkToRoute('core.OCJS.getConfig', ['v' => self::$versionHash]));
170
-			}
171
-		}
172
-		foreach($jsFiles as $info) {
173
-			$web = $info[1];
174
-			$file = $info[2];
175
-			$this->append( 'jsfiles', $web.'/'.$file . $this->getVersionHashSuffix() );
176
-		}
177
-
178
-		try {
179
-			$pathInfo = \OC::$server->getRequest()->getPathInfo();
180
-		} catch (\Exception $e) {
181
-			$pathInfo = '';
182
-		}
183
-
184
-		// Do not initialise scss appdata until we have a fully installed instance
185
-		// Do not load scss for update, errors, installation or login page
186
-		if(\OC::$server->getSystemConfig()->getValue('installed', false)
187
-			&& !\OCP\Util::needUpgrade()
188
-			&& $pathInfo !== ''
189
-			&& !preg_match('/^\/login/', $pathInfo)
190
-			&& $renderAs !== 'error' && $renderAs !== 'guest'
191
-		) {
192
-			$cssFiles = self::findStylesheetFiles(\OC_Util::$styles);
193
-		} else {
194
-			// If we ignore the scss compiler,
195
-			// we need to load the guest css fallback
196
-			\OC_Util::addStyle('guest');
197
-			$cssFiles = self::findStylesheetFiles(\OC_Util::$styles, false);
198
-		}
199
-
200
-		$this->assign('cssfiles', array());
201
-		$this->assign('printcssfiles', []);
202
-		$this->assign('versionHash', self::$versionHash);
203
-		foreach($cssFiles as $info) {
204
-			$web = $info[1];
205
-			$file = $info[2];
206
-
207
-			if (substr($file, -strlen('print.css')) === 'print.css') {
208
-				$this->append( 'printcssfiles', $web.'/'.$file . $this->getVersionHashSuffix() );
209
-			} else {
210
-				$this->append( 'cssfiles', $web.'/'.$file . $this->getVersionHashSuffix($web, $file)  );
211
-			}
212
-		}
213
-	}
214
-
215
-	/**
216
-	 * @param string $path
217
- 	 * @param string $file
218
-	 * @return string
219
-	 */
220
-	protected function getVersionHashSuffix($path = false, $file = false) {
221
-		if ($this->config->getSystemValue('debug', false)) {
222
-			// allows chrome workspace mapping in debug mode
223
-			return "";
224
-		}
225
-		$themingSuffix = '';
226
-		$v = [];
227
-
228
-		if ($this->config->getSystemValue('installed', false)) {
229
-			if (\OC::$server->getAppManager()->isInstalled('theming')) {
230
-				$themingSuffix = '-' . $this->config->getAppValue('theming', 'cachebuster', '0');
231
-			}
232
-			$v = \OC_App::getAppVersions();
233
-		}
234
-
235
-		// Try the webroot path for a match
236
-		if ($path !== false && $path !== '') {
237
-			$appName = $this->getAppNamefromPath($path);
238
-			if(array_key_exists($appName, $v)) {
239
-				$appVersion = $v[$appName];
240
-				return '?v=' . substr(md5($appVersion), 0, 8) . $themingSuffix;
241
-			}
242
-		}
243
-		// fallback to the file path instead
244
-		if ($file !== false && $file !== '') {
245
-			$appName = $this->getAppNamefromPath($file);
246
-			if(array_key_exists($appName, $v)) {
247
-				$appVersion = $v[$appName];
248
-				return '?v=' . substr(md5($appVersion), 0, 8) . $themingSuffix;
249
-			}
250
-		}
251
-
252
-		return '?v=' . self::$versionHash . $themingSuffix;
253
-	}
254
-
255
-	/**
256
-	 * @param array $styles
257
-	 * @return array
258
-	 */
259
-	static public function findStylesheetFiles($styles, $compileScss = true) {
260
-		// Read the selected theme from the config file
261
-		$theme = \OC_Util::getTheme();
262
-
263
-		if($compileScss) {
264
-			$SCSSCacher = \OC::$server->query(SCSSCacher::class);
265
-		} else {
266
-			$SCSSCacher = null;
267
-		}
268
-
269
-		$locator = new \OC\Template\CSSResourceLocator(
270
-			\OC::$server->getLogger(),
271
-			$theme,
272
-			array( \OC::$SERVERROOT => \OC::$WEBROOT ),
273
-			array( \OC::$SERVERROOT => \OC::$WEBROOT ),
274
-			$SCSSCacher
275
-		);
276
-		$locator->find($styles);
277
-		return $locator->getResources();
278
-	}
279
-
280
-	/**
281
-	 * @param string $path
282
-	 * @return string|boolean
283
-	 */
284
-	public function getAppNamefromPath($path) {
285
-		if ($path !== '' && is_string($path)) {
286
-			$pathParts = explode('/', $path);
287
-			if ($pathParts[0] === 'css') {
288
-				// This is a scss request
289
-				return $pathParts[1];
290
-			}
291
-			return end($pathParts);
292
-		}
293
-		return false;
294
-
295
-	}
296
-
297
-	/**
298
-	 * @param array $scripts
299
-	 * @return array
300
-	 */
301
-	static public function findJavascriptFiles($scripts) {
302
-		// Read the selected theme from the config file
303
-		$theme = \OC_Util::getTheme();
304
-
305
-		$locator = new \OC\Template\JSResourceLocator(
306
-			\OC::$server->getLogger(),
307
-			$theme,
308
-			array( \OC::$SERVERROOT => \OC::$WEBROOT ),
309
-			array( \OC::$SERVERROOT => \OC::$WEBROOT ),
310
-			\OC::$server->query(JSCombiner::class)
311
-			);
312
-		$locator->find($scripts);
313
-		return $locator->getResources();
314
-	}
315
-
316
-	/**
317
-	 * Converts the absolute file path to a relative path from \OC::$SERVERROOT
318
-	 * @param string $filePath Absolute path
319
-	 * @return string Relative path
320
-	 * @throws \Exception If $filePath is not under \OC::$SERVERROOT
321
-	 */
322
-	public static function convertToRelativePath($filePath) {
323
-		$relativePath = explode(\OC::$SERVERROOT, $filePath);
324
-		if(count($relativePath) !== 2) {
325
-			throw new \Exception('$filePath is not under the \OC::$SERVERROOT');
326
-		}
327
-
328
-		return $relativePath[1];
329
-	}
48
+    private static $versionHash = '';
49
+
50
+    /**
51
+     * @var \OCP\IConfig
52
+     */
53
+    private $config;
54
+
55
+    /**
56
+     * @param string $renderAs
57
+     * @param string $appId application id
58
+     */
59
+    public function __construct( $renderAs, $appId = '' ) {
60
+
61
+        // yes - should be injected ....
62
+        $this->config = \OC::$server->getConfig();
63
+
64
+
65
+        // Decide which page we show
66
+        if($renderAs == 'user') {
67
+            parent::__construct( 'core', 'layout.user' );
68
+            if(in_array(\OC_App::getCurrentApp(), ['settings','admin', 'help']) !== false) {
69
+                $this->assign('bodyid', 'body-settings');
70
+            }else{
71
+                $this->assign('bodyid', 'body-user');
72
+            }
73
+
74
+            // Code integrity notification
75
+            $integrityChecker = \OC::$server->getIntegrityCodeChecker();
76
+            if(\OC_User::isAdminUser(\OC_User::getUser()) && $integrityChecker->isCodeCheckEnforced() && !$integrityChecker->hasPassedCheck()) {
77
+                \OCP\Util::addScript('core', 'integritycheck-failed-notification');
78
+            }
79
+
80
+            // Add navigation entry
81
+            $this->assign( 'application', '');
82
+            $this->assign( 'appid', $appId );
83
+            $navigation = \OC::$server->getNavigationManager()->getAll();
84
+            $this->assign( 'navigation', $navigation);
85
+            $settingsNavigation = \OC::$server->getNavigationManager()->getAll('settings');
86
+            $this->assign( 'settingsnavigation', $settingsNavigation);
87
+            foreach($navigation as $entry) {
88
+                if ($entry['active']) {
89
+                    $this->assign( 'application', $entry['name'] );
90
+                    break;
91
+                }
92
+            }
93
+
94
+            foreach($settingsNavigation as $entry) {
95
+                if ($entry['active']) {
96
+                    $this->assign( 'application', $entry['name'] );
97
+                    break;
98
+                }
99
+            }
100
+            $userDisplayName = \OC_User::getDisplayName();
101
+            $this->assign('user_displayname', $userDisplayName);
102
+            $this->assign('user_uid', \OC_User::getUser());
103
+
104
+            if (\OC_User::getUser() === false) {
105
+                $this->assign('userAvatarSet', false);
106
+            } else {
107
+                $this->assign('userAvatarSet', \OC::$server->getAvatarManager()->getAvatar(\OC_User::getUser())->exists());
108
+                $this->assign('userAvatarVersion', $this->config->getUserValue(\OC_User::getUser(), 'avatar', 'version', 0));
109
+            }
110
+
111
+            // check if app menu icons should be inverted
112
+            try {
113
+                /** @var \OCA\Theming\Util $util */
114
+                $util = \OC::$server->query(\OCA\Theming\Util::class);
115
+                $this->assign('themingInvertMenu', $util->invertTextColor(\OC::$server->getThemingDefaults()->getColorPrimary()));
116
+            } catch (\OCP\AppFramework\QueryException $e) {
117
+                $this->assign('themingInvertMenu', false);
118
+            }
119
+
120
+        } else if ($renderAs == 'error') {
121
+            parent::__construct('core', 'layout.guest', '', false);
122
+            $this->assign('bodyid', 'body-login');
123
+        } else if ($renderAs == 'guest') {
124
+            parent::__construct('core', 'layout.guest');
125
+            $this->assign('bodyid', 'body-login');
126
+        } else if ($renderAs == 'public') {
127
+            parent::__construct('core', 'layout.public');
128
+            $this->assign( 'appid', $appId );
129
+            $this->assign('bodyid', 'body-public');
130
+        } else {
131
+            parent::__construct('core', 'layout.base');
132
+
133
+        }
134
+        // Send the language and the locale to our layouts
135
+        $lang = \OC::$server->getL10NFactory()->findLanguage();
136
+        $lang = str_replace('_', '-', $lang);
137
+        $this->assign('language', $lang);
138
+        $this->assign('locale', \OC::$server->getL10NFactory()->findLocale());
139
+
140
+        if(\OC::$server->getSystemConfig()->getValue('installed', false)) {
141
+            if (empty(self::$versionHash)) {
142
+                $v = \OC_App::getAppVersions();
143
+                $v['core'] = implode('.', \OCP\Util::getVersion());
144
+                self::$versionHash = substr(md5(implode(',', $v)), 0, 8);
145
+            }
146
+        } else {
147
+            self::$versionHash = md5('not installed');
148
+        }
149
+
150
+        // Add the js files
151
+        $jsFiles = self::findJavascriptFiles(\OC_Util::$scripts);
152
+        $this->assign('jsfiles', array());
153
+        if ($this->config->getSystemValue('installed', false) && $renderAs != 'error') {
154
+            if (\OC::$server->getContentSecurityPolicyNonceManager()->browserSupportsCspV3()) {
155
+                $jsConfigHelper = new JSConfigHelper(
156
+                    \OC::$server->getL10N('lib'),
157
+                    \OC::$server->query(Defaults::class),
158
+                    \OC::$server->getAppManager(),
159
+                    \OC::$server->getSession(),
160
+                    \OC::$server->getUserSession()->getUser(),
161
+                    $this->config,
162
+                    \OC::$server->getGroupManager(),
163
+                    \OC::$server->getIniWrapper(),
164
+                    \OC::$server->getURLGenerator(),
165
+                    \OC::$server->getCapabilitiesManager()
166
+                );
167
+                $this->assign('inline_ocjs', $jsConfigHelper->getConfig());
168
+            } else {
169
+                $this->append('jsfiles', \OC::$server->getURLGenerator()->linkToRoute('core.OCJS.getConfig', ['v' => self::$versionHash]));
170
+            }
171
+        }
172
+        foreach($jsFiles as $info) {
173
+            $web = $info[1];
174
+            $file = $info[2];
175
+            $this->append( 'jsfiles', $web.'/'.$file . $this->getVersionHashSuffix() );
176
+        }
177
+
178
+        try {
179
+            $pathInfo = \OC::$server->getRequest()->getPathInfo();
180
+        } catch (\Exception $e) {
181
+            $pathInfo = '';
182
+        }
183
+
184
+        // Do not initialise scss appdata until we have a fully installed instance
185
+        // Do not load scss for update, errors, installation or login page
186
+        if(\OC::$server->getSystemConfig()->getValue('installed', false)
187
+            && !\OCP\Util::needUpgrade()
188
+            && $pathInfo !== ''
189
+            && !preg_match('/^\/login/', $pathInfo)
190
+            && $renderAs !== 'error' && $renderAs !== 'guest'
191
+        ) {
192
+            $cssFiles = self::findStylesheetFiles(\OC_Util::$styles);
193
+        } else {
194
+            // If we ignore the scss compiler,
195
+            // we need to load the guest css fallback
196
+            \OC_Util::addStyle('guest');
197
+            $cssFiles = self::findStylesheetFiles(\OC_Util::$styles, false);
198
+        }
199
+
200
+        $this->assign('cssfiles', array());
201
+        $this->assign('printcssfiles', []);
202
+        $this->assign('versionHash', self::$versionHash);
203
+        foreach($cssFiles as $info) {
204
+            $web = $info[1];
205
+            $file = $info[2];
206
+
207
+            if (substr($file, -strlen('print.css')) === 'print.css') {
208
+                $this->append( 'printcssfiles', $web.'/'.$file . $this->getVersionHashSuffix() );
209
+            } else {
210
+                $this->append( 'cssfiles', $web.'/'.$file . $this->getVersionHashSuffix($web, $file)  );
211
+            }
212
+        }
213
+    }
214
+
215
+    /**
216
+     * @param string $path
217
+     * @param string $file
218
+     * @return string
219
+     */
220
+    protected function getVersionHashSuffix($path = false, $file = false) {
221
+        if ($this->config->getSystemValue('debug', false)) {
222
+            // allows chrome workspace mapping in debug mode
223
+            return "";
224
+        }
225
+        $themingSuffix = '';
226
+        $v = [];
227
+
228
+        if ($this->config->getSystemValue('installed', false)) {
229
+            if (\OC::$server->getAppManager()->isInstalled('theming')) {
230
+                $themingSuffix = '-' . $this->config->getAppValue('theming', 'cachebuster', '0');
231
+            }
232
+            $v = \OC_App::getAppVersions();
233
+        }
234
+
235
+        // Try the webroot path for a match
236
+        if ($path !== false && $path !== '') {
237
+            $appName = $this->getAppNamefromPath($path);
238
+            if(array_key_exists($appName, $v)) {
239
+                $appVersion = $v[$appName];
240
+                return '?v=' . substr(md5($appVersion), 0, 8) . $themingSuffix;
241
+            }
242
+        }
243
+        // fallback to the file path instead
244
+        if ($file !== false && $file !== '') {
245
+            $appName = $this->getAppNamefromPath($file);
246
+            if(array_key_exists($appName, $v)) {
247
+                $appVersion = $v[$appName];
248
+                return '?v=' . substr(md5($appVersion), 0, 8) . $themingSuffix;
249
+            }
250
+        }
251
+
252
+        return '?v=' . self::$versionHash . $themingSuffix;
253
+    }
254
+
255
+    /**
256
+     * @param array $styles
257
+     * @return array
258
+     */
259
+    static public function findStylesheetFiles($styles, $compileScss = true) {
260
+        // Read the selected theme from the config file
261
+        $theme = \OC_Util::getTheme();
262
+
263
+        if($compileScss) {
264
+            $SCSSCacher = \OC::$server->query(SCSSCacher::class);
265
+        } else {
266
+            $SCSSCacher = null;
267
+        }
268
+
269
+        $locator = new \OC\Template\CSSResourceLocator(
270
+            \OC::$server->getLogger(),
271
+            $theme,
272
+            array( \OC::$SERVERROOT => \OC::$WEBROOT ),
273
+            array( \OC::$SERVERROOT => \OC::$WEBROOT ),
274
+            $SCSSCacher
275
+        );
276
+        $locator->find($styles);
277
+        return $locator->getResources();
278
+    }
279
+
280
+    /**
281
+     * @param string $path
282
+     * @return string|boolean
283
+     */
284
+    public function getAppNamefromPath($path) {
285
+        if ($path !== '' && is_string($path)) {
286
+            $pathParts = explode('/', $path);
287
+            if ($pathParts[0] === 'css') {
288
+                // This is a scss request
289
+                return $pathParts[1];
290
+            }
291
+            return end($pathParts);
292
+        }
293
+        return false;
294
+
295
+    }
296
+
297
+    /**
298
+     * @param array $scripts
299
+     * @return array
300
+     */
301
+    static public function findJavascriptFiles($scripts) {
302
+        // Read the selected theme from the config file
303
+        $theme = \OC_Util::getTheme();
304
+
305
+        $locator = new \OC\Template\JSResourceLocator(
306
+            \OC::$server->getLogger(),
307
+            $theme,
308
+            array( \OC::$SERVERROOT => \OC::$WEBROOT ),
309
+            array( \OC::$SERVERROOT => \OC::$WEBROOT ),
310
+            \OC::$server->query(JSCombiner::class)
311
+            );
312
+        $locator->find($scripts);
313
+        return $locator->getResources();
314
+    }
315
+
316
+    /**
317
+     * Converts the absolute file path to a relative path from \OC::$SERVERROOT
318
+     * @param string $filePath Absolute path
319
+     * @return string Relative path
320
+     * @throws \Exception If $filePath is not under \OC::$SERVERROOT
321
+     */
322
+    public static function convertToRelativePath($filePath) {
323
+        $relativePath = explode(\OC::$SERVERROOT, $filePath);
324
+        if(count($relativePath) !== 2) {
325
+            throw new \Exception('$filePath is not under the \OC::$SERVERROOT');
326
+        }
327
+
328
+        return $relativePath[1];
329
+    }
330 330
 }
Please login to merge, or discard this patch.
Spacing   +34 added lines, -34 removed lines patch added patch discarded remove patch
@@ -56,44 +56,44 @@  discard block
 block discarded – undo
56 56
 	 * @param string $renderAs
57 57
 	 * @param string $appId application id
58 58
 	 */
59
-	public function __construct( $renderAs, $appId = '' ) {
59
+	public function __construct($renderAs, $appId = '') {
60 60
 
61 61
 		// yes - should be injected ....
62 62
 		$this->config = \OC::$server->getConfig();
63 63
 
64 64
 
65 65
 		// Decide which page we show
66
-		if($renderAs == 'user') {
67
-			parent::__construct( 'core', 'layout.user' );
68
-			if(in_array(\OC_App::getCurrentApp(), ['settings','admin', 'help']) !== false) {
66
+		if ($renderAs == 'user') {
67
+			parent::__construct('core', 'layout.user');
68
+			if (in_array(\OC_App::getCurrentApp(), ['settings', 'admin', 'help']) !== false) {
69 69
 				$this->assign('bodyid', 'body-settings');
70
-			}else{
70
+			} else {
71 71
 				$this->assign('bodyid', 'body-user');
72 72
 			}
73 73
 
74 74
 			// Code integrity notification
75 75
 			$integrityChecker = \OC::$server->getIntegrityCodeChecker();
76
-			if(\OC_User::isAdminUser(\OC_User::getUser()) && $integrityChecker->isCodeCheckEnforced() && !$integrityChecker->hasPassedCheck()) {
76
+			if (\OC_User::isAdminUser(\OC_User::getUser()) && $integrityChecker->isCodeCheckEnforced() && !$integrityChecker->hasPassedCheck()) {
77 77
 				\OCP\Util::addScript('core', 'integritycheck-failed-notification');
78 78
 			}
79 79
 
80 80
 			// Add navigation entry
81
-			$this->assign( 'application', '');
82
-			$this->assign( 'appid', $appId );
81
+			$this->assign('application', '');
82
+			$this->assign('appid', $appId);
83 83
 			$navigation = \OC::$server->getNavigationManager()->getAll();
84
-			$this->assign( 'navigation', $navigation);
84
+			$this->assign('navigation', $navigation);
85 85
 			$settingsNavigation = \OC::$server->getNavigationManager()->getAll('settings');
86
-			$this->assign( 'settingsnavigation', $settingsNavigation);
87
-			foreach($navigation as $entry) {
86
+			$this->assign('settingsnavigation', $settingsNavigation);
87
+			foreach ($navigation as $entry) {
88 88
 				if ($entry['active']) {
89
-					$this->assign( 'application', $entry['name'] );
89
+					$this->assign('application', $entry['name']);
90 90
 					break;
91 91
 				}
92 92
 			}
93 93
 
94
-			foreach($settingsNavigation as $entry) {
94
+			foreach ($settingsNavigation as $entry) {
95 95
 				if ($entry['active']) {
96
-					$this->assign( 'application', $entry['name'] );
96
+					$this->assign('application', $entry['name']);
97 97
 					break;
98 98
 				}
99 99
 			}
@@ -125,7 +125,7 @@  discard block
 block discarded – undo
125 125
 			$this->assign('bodyid', 'body-login');
126 126
 		} else if ($renderAs == 'public') {
127 127
 			parent::__construct('core', 'layout.public');
128
-			$this->assign( 'appid', $appId );
128
+			$this->assign('appid', $appId);
129 129
 			$this->assign('bodyid', 'body-public');
130 130
 		} else {
131 131
 			parent::__construct('core', 'layout.base');
@@ -137,7 +137,7 @@  discard block
 block discarded – undo
137 137
 		$this->assign('language', $lang);
138 138
 		$this->assign('locale', \OC::$server->getL10NFactory()->findLocale());
139 139
 
140
-		if(\OC::$server->getSystemConfig()->getValue('installed', false)) {
140
+		if (\OC::$server->getSystemConfig()->getValue('installed', false)) {
141 141
 			if (empty(self::$versionHash)) {
142 142
 				$v = \OC_App::getAppVersions();
143 143
 				$v['core'] = implode('.', \OCP\Util::getVersion());
@@ -169,10 +169,10 @@  discard block
 block discarded – undo
169 169
 				$this->append('jsfiles', \OC::$server->getURLGenerator()->linkToRoute('core.OCJS.getConfig', ['v' => self::$versionHash]));
170 170
 			}
171 171
 		}
172
-		foreach($jsFiles as $info) {
172
+		foreach ($jsFiles as $info) {
173 173
 			$web = $info[1];
174 174
 			$file = $info[2];
175
-			$this->append( 'jsfiles', $web.'/'.$file . $this->getVersionHashSuffix() );
175
+			$this->append('jsfiles', $web.'/'.$file.$this->getVersionHashSuffix());
176 176
 		}
177 177
 
178 178
 		try {
@@ -183,7 +183,7 @@  discard block
 block discarded – undo
183 183
 
184 184
 		// Do not initialise scss appdata until we have a fully installed instance
185 185
 		// Do not load scss for update, errors, installation or login page
186
-		if(\OC::$server->getSystemConfig()->getValue('installed', false)
186
+		if (\OC::$server->getSystemConfig()->getValue('installed', false)
187 187
 			&& !\OCP\Util::needUpgrade()
188 188
 			&& $pathInfo !== ''
189 189
 			&& !preg_match('/^\/login/', $pathInfo)
@@ -200,14 +200,14 @@  discard block
 block discarded – undo
200 200
 		$this->assign('cssfiles', array());
201 201
 		$this->assign('printcssfiles', []);
202 202
 		$this->assign('versionHash', self::$versionHash);
203
-		foreach($cssFiles as $info) {
203
+		foreach ($cssFiles as $info) {
204 204
 			$web = $info[1];
205 205
 			$file = $info[2];
206 206
 
207 207
 			if (substr($file, -strlen('print.css')) === 'print.css') {
208
-				$this->append( 'printcssfiles', $web.'/'.$file . $this->getVersionHashSuffix() );
208
+				$this->append('printcssfiles', $web.'/'.$file.$this->getVersionHashSuffix());
209 209
 			} else {
210
-				$this->append( 'cssfiles', $web.'/'.$file . $this->getVersionHashSuffix($web, $file)  );
210
+				$this->append('cssfiles', $web.'/'.$file.$this->getVersionHashSuffix($web, $file));
211 211
 			}
212 212
 		}
213 213
 	}
@@ -227,7 +227,7 @@  discard block
 block discarded – undo
227 227
 
228 228
 		if ($this->config->getSystemValue('installed', false)) {
229 229
 			if (\OC::$server->getAppManager()->isInstalled('theming')) {
230
-				$themingSuffix = '-' . $this->config->getAppValue('theming', 'cachebuster', '0');
230
+				$themingSuffix = '-'.$this->config->getAppValue('theming', 'cachebuster', '0');
231 231
 			}
232 232
 			$v = \OC_App::getAppVersions();
233 233
 		}
@@ -235,21 +235,21 @@  discard block
 block discarded – undo
235 235
 		// Try the webroot path for a match
236 236
 		if ($path !== false && $path !== '') {
237 237
 			$appName = $this->getAppNamefromPath($path);
238
-			if(array_key_exists($appName, $v)) {
238
+			if (array_key_exists($appName, $v)) {
239 239
 				$appVersion = $v[$appName];
240
-				return '?v=' . substr(md5($appVersion), 0, 8) . $themingSuffix;
240
+				return '?v='.substr(md5($appVersion), 0, 8).$themingSuffix;
241 241
 			}
242 242
 		}
243 243
 		// fallback to the file path instead
244 244
 		if ($file !== false && $file !== '') {
245 245
 			$appName = $this->getAppNamefromPath($file);
246
-			if(array_key_exists($appName, $v)) {
246
+			if (array_key_exists($appName, $v)) {
247 247
 				$appVersion = $v[$appName];
248
-				return '?v=' . substr(md5($appVersion), 0, 8) . $themingSuffix;
248
+				return '?v='.substr(md5($appVersion), 0, 8).$themingSuffix;
249 249
 			}
250 250
 		}
251 251
 
252
-		return '?v=' . self::$versionHash . $themingSuffix;
252
+		return '?v='.self::$versionHash.$themingSuffix;
253 253
 	}
254 254
 
255 255
 	/**
@@ -260,7 +260,7 @@  discard block
 block discarded – undo
260 260
 		// Read the selected theme from the config file
261 261
 		$theme = \OC_Util::getTheme();
262 262
 
263
-		if($compileScss) {
263
+		if ($compileScss) {
264 264
 			$SCSSCacher = \OC::$server->query(SCSSCacher::class);
265 265
 		} else {
266 266
 			$SCSSCacher = null;
@@ -269,8 +269,8 @@  discard block
 block discarded – undo
269 269
 		$locator = new \OC\Template\CSSResourceLocator(
270 270
 			\OC::$server->getLogger(),
271 271
 			$theme,
272
-			array( \OC::$SERVERROOT => \OC::$WEBROOT ),
273
-			array( \OC::$SERVERROOT => \OC::$WEBROOT ),
272
+			array(\OC::$SERVERROOT => \OC::$WEBROOT),
273
+			array(\OC::$SERVERROOT => \OC::$WEBROOT),
274 274
 			$SCSSCacher
275 275
 		);
276 276
 		$locator->find($styles);
@@ -305,8 +305,8 @@  discard block
 block discarded – undo
305 305
 		$locator = new \OC\Template\JSResourceLocator(
306 306
 			\OC::$server->getLogger(),
307 307
 			$theme,
308
-			array( \OC::$SERVERROOT => \OC::$WEBROOT ),
309
-			array( \OC::$SERVERROOT => \OC::$WEBROOT ),
308
+			array(\OC::$SERVERROOT => \OC::$WEBROOT),
309
+			array(\OC::$SERVERROOT => \OC::$WEBROOT),
310 310
 			\OC::$server->query(JSCombiner::class)
311 311
 			);
312 312
 		$locator->find($scripts);
@@ -321,7 +321,7 @@  discard block
 block discarded – undo
321 321
 	 */
322 322
 	public static function convertToRelativePath($filePath) {
323 323
 		$relativePath = explode(\OC::$SERVERROOT, $filePath);
324
-		if(count($relativePath) !== 2) {
324
+		if (count($relativePath) !== 2) {
325 325
 			throw new \Exception('$filePath is not under the \OC::$SERVERROOT');
326 326
 		}
327 327
 
Please login to merge, or discard this patch.
lib/private/Settings/Personal/PersonalInfo.php 2 patches
Indentation   +236 added lines, -236 removed lines patch added patch discarded remove patch
@@ -41,241 +41,241 @@
 block discarded – undo
41 41
 
42 42
 class PersonalInfo implements ISettings {
43 43
 
44
-	/** @var IConfig */
45
-	private $config;
46
-	/** @var IUserManager */
47
-	private $userManager;
48
-	/** @var AccountManager */
49
-	private $accountManager;
50
-	/** @var IGroupManager */
51
-	private $groupManager;
52
-	/** @var IAppManager */
53
-	private $appManager;
54
-	/** @var IFactory */
55
-	private $l10nFactory;
56
-	/** @var IL10N */
57
-	private $l;
58
-
59
-	/**
60
-	 * @param IConfig $config
61
-	 * @param IUserManager $userManager
62
-	 * @param IGroupManager $groupManager
63
-	 * @param AccountManager $accountManager
64
-	 * @param IFactory $l10nFactory
65
-	 * @param IL10N $l
66
-	 */
67
-	public function __construct(
68
-		IConfig $config,
69
-		IUserManager $userManager,
70
-		IGroupManager $groupManager,
71
-		AccountManager $accountManager,
72
-		IAppManager $appManager,
73
-		IFactory $l10nFactory,
74
-		IL10N $l
75
-	) {
76
-		$this->config = $config;
77
-		$this->userManager = $userManager;
78
-		$this->accountManager = $accountManager;
79
-		$this->groupManager = $groupManager;
80
-		$this->appManager = $appManager;
81
-		$this->l10nFactory = $l10nFactory;
82
-		$this->l = $l;
83
-	}
84
-
85
-	/**
86
-	 * @return TemplateResponse returns the instance with all parameters set, ready to be rendered
87
-	 * @since 9.1
88
-	 */
89
-	public function getForm() {
90
-		$federatedFileSharingEnabled = $this->appManager->isEnabledForUser('federatedfilesharing');
91
-		$lookupServerUploadEnabled = false;
92
-		if($federatedFileSharingEnabled) {
93
-			$federatedFileSharing = new Application();
94
-			$shareProvider = $federatedFileSharing->getFederatedShareProvider();
95
-			$lookupServerUploadEnabled = $shareProvider->isLookupServerUploadEnabled();
96
-		}
97
-
98
-		$uid = \OC_User::getUser();
99
-		$user = $this->userManager->get($uid);
100
-		$userData = $this->accountManager->getUser($user);
101
-
102
-		$storageInfo = \OC_Helper::getStorageInfo('/');
103
-		if ($storageInfo['quota'] === FileInfo::SPACE_UNLIMITED) {
104
-			$totalSpace = $this->l->t('Unlimited');
105
-		} else {
106
-			$totalSpace = \OC_Helper::humanFileSize($storageInfo['total']);
107
-		}
108
-
109
-		$languageParameters = $this->getLanguages($user);
110
-		$localeParameters = $this->getLocales($user);
111
-		$messageParameters = $this->getMessageParameters($userData);
112
-
113
-		$parameters = [
114
-			'total_space' => $totalSpace,
115
-			'usage' => \OC_Helper::humanFileSize($storageInfo['used']),
116
-			'usage_relative' => round($storageInfo['relative']),
117
-			'quota' => $storageInfo['quota'],
118
-			'avatarChangeSupported' => $user->canChangeAvatar(),
119
-			'lookupServerUploadEnabled' => $lookupServerUploadEnabled,
120
-			'avatarScope' => $userData[AccountManager::PROPERTY_AVATAR]['scope'],
121
-			'displayNameChangeSupported' => $user->canChangeDisplayName(),
122
-			'displayName' => $userData[AccountManager::PROPERTY_DISPLAYNAME]['value'],
123
-			'displayNameScope' => $userData[AccountManager::PROPERTY_DISPLAYNAME]['scope'],
124
-			'email' => $userData[AccountManager::PROPERTY_EMAIL]['value'],
125
-			'emailScope' => $userData[AccountManager::PROPERTY_EMAIL]['scope'],
126
-			'emailVerification' => $userData[AccountManager::PROPERTY_EMAIL]['verified'],
127
-			'phone' => $userData[AccountManager::PROPERTY_PHONE]['value'],
128
-			'phoneScope' => $userData[AccountManager::PROPERTY_PHONE]['scope'],
129
-			'address' => $userData[AccountManager::PROPERTY_ADDRESS]['value'],
130
-			'addressScope' => $userData[AccountManager::PROPERTY_ADDRESS]['scope'],
131
-			'website' =>  $userData[AccountManager::PROPERTY_WEBSITE]['value'],
132
-			'websiteScope' =>  $userData[AccountManager::PROPERTY_WEBSITE]['scope'],
133
-			'websiteVerification' => $userData[AccountManager::PROPERTY_WEBSITE]['verified'],
134
-			'twitter' => $userData[AccountManager::PROPERTY_TWITTER]['value'],
135
-			'twitterScope' => $userData[AccountManager::PROPERTY_TWITTER]['scope'],
136
-			'twitterVerification' => $userData[AccountManager::PROPERTY_TWITTER]['verified'],
137
-			'groups' => $this->getGroups($user),
138
-			'passwordChangeSupported' => $user->canChangePassword(),
139
-		] + $messageParameters + $languageParameters + $localeParameters;
140
-
141
-
142
-		return new TemplateResponse('settings', 'settings/personal/personal.info', $parameters, '');
143
-	}
144
-
145
-	/**
146
-	 * @return string the section ID, e.g. 'sharing'
147
-	 * @since 9.1
148
-	 */
149
-	public function getSection() {
150
-		return 'personal-info';
151
-	}
152
-
153
-	/**
154
-	 * @return int whether the form should be rather on the top or bottom of
155
-	 * the admin section. The forms are arranged in ascending order of the
156
-	 * priority values. It is required to return a value between 0 and 100.
157
-	 *
158
-	 * E.g.: 70
159
-	 * @since 9.1
160
-	 */
161
-	public function getPriority() {
162
-		return 10;
163
-	}
164
-
165
-	/**
166
-	 * returns a sorted list of the user's group GIDs
167
-	 *
168
-	 * @param IUser $user
169
-	 * @return array
170
-	 */
171
-	private function getGroups(IUser $user) {
172
-		$groups = array_map(
173
-			function(IGroup $group) {
174
-				return $group->getDisplayName();
175
-			},
176
-			$this->groupManager->getUserGroups($user)
177
-		);
178
-		sort($groups);
179
-
180
-		return $groups;
181
-	}
182
-
183
-	/**
184
-	 * returns the user language, common language and other languages in an
185
-	 * associative array
186
-	 *
187
-	 * @param IUser $user
188
-	 * @return array
189
-	 */
190
-	private function getLanguages(IUser $user) {
191
-		$forceLanguage = $this->config->getSystemValue('force_language', false);
192
-		if($forceLanguage !== false) {
193
-			return [];
194
-		}
195
-
196
-		$uid = $user->getUID();
197
-
198
-		$userConfLang = $this->config->getUserValue($uid, 'core', 'lang', $this->l10nFactory->findLanguage());
199
-		$languages = $this->l10nFactory->getLanguages();
200
-
201
-		// associate the user language with the proper array
202
-		$userLangIndex = array_search($userConfLang, array_column($languages['commonlanguages'], 'code'));
203
-		$userLang = $languages['commonlanguages'][$userLangIndex];
204
-		// search in the other languages
205
-		if ($userLangIndex === false) {
206
-			$userLangIndex = array_search($userConfLang, array_column($languages['languages'], 'code'));		
207
-			$userLang = $languages['languages'][$userLangIndex];
208
-		}
209
-		// if user language is not available but set somehow: show the actual code as name
210
-		if (!is_array($userLang)) {
211
-			$userLang = [
212
-				'code' => $userConfLang,
213
-				'name' => $userConfLang,
214
-			];
215
-		}
216
-
217
-		return array_merge(
218
-			array('activelanguage' => $userLang),
219
-			$languages
220
-		);
221
-	}
222
-
223
-	private function getLocales(IUser $user) {
224
-		$forceLanguage = $this->config->getSystemValue('force_locale', false);
225
-		if($forceLanguage !== false) {
226
-			return [];
227
-		}
228
-
229
-		$uid = $user->getUID();
230
-
231
-		$userLocaleString = $this->config->getUserValue($uid, 'core', 'locale', 'en_US');
232
-
233
-		$userLang = $this->config->getUserValue($uid, 'core', 'lang', $this->l10nFactory->findLanguage());
234
-
235
-		$localeCodes = $this->l10nFactory->findAvailableLocales();
236
-
237
-		$userLocale = array_filter($localeCodes, function($value) use ($userLocaleString) {
238
-			return $userLocaleString === $value['code'];
239
-		});
240
-
241
-		if (!empty($userLocale))
242
-		{
243
-			$userLocale = reset($userLocale);
244
-		}
245
-
246
-		$localesForLanguage = array_filter($localeCodes, function($localeCode) use ($userLang) {
247
-			return 0 === strpos($localeCode['code'], $userLang);
248
-		});
249
-
250
-		return [
251
-			'activelocaleLang' => $userLocaleString,
252
-			'activelocale' => $userLocale,
253
-			'locales' => $localeCodes,
254
-			'localesforlanguage' => $localesForLanguage,
255
-		];
256
-	}
257
-
258
-	/**
259
-	 * @param array $userData
260
-	 * @return array
261
-	 */
262
-	private function getMessageParameters(array $userData) {
263
-		$needVerifyMessage = [AccountManager::PROPERTY_EMAIL, AccountManager::PROPERTY_WEBSITE, AccountManager::PROPERTY_TWITTER];
264
-		$messageParameters = [];
265
-		foreach ($needVerifyMessage as $property) {
266
-			switch ($userData[$property]['verified']) {
267
-				case AccountManager::VERIFIED:
268
-					$message = $this->l->t('Verifying');
269
-					break;
270
-				case AccountManager::VERIFICATION_IN_PROGRESS:
271
-					$message = $this->l->t('Verifying …');
272
-					break;
273
-				default:
274
-					$message = $this->l->t('Verify');
275
-			}
276
-			$messageParameters[$property . 'Message'] = $message;
277
-		}
278
-		return $messageParameters;
279
-	}
44
+    /** @var IConfig */
45
+    private $config;
46
+    /** @var IUserManager */
47
+    private $userManager;
48
+    /** @var AccountManager */
49
+    private $accountManager;
50
+    /** @var IGroupManager */
51
+    private $groupManager;
52
+    /** @var IAppManager */
53
+    private $appManager;
54
+    /** @var IFactory */
55
+    private $l10nFactory;
56
+    /** @var IL10N */
57
+    private $l;
58
+
59
+    /**
60
+     * @param IConfig $config
61
+     * @param IUserManager $userManager
62
+     * @param IGroupManager $groupManager
63
+     * @param AccountManager $accountManager
64
+     * @param IFactory $l10nFactory
65
+     * @param IL10N $l
66
+     */
67
+    public function __construct(
68
+        IConfig $config,
69
+        IUserManager $userManager,
70
+        IGroupManager $groupManager,
71
+        AccountManager $accountManager,
72
+        IAppManager $appManager,
73
+        IFactory $l10nFactory,
74
+        IL10N $l
75
+    ) {
76
+        $this->config = $config;
77
+        $this->userManager = $userManager;
78
+        $this->accountManager = $accountManager;
79
+        $this->groupManager = $groupManager;
80
+        $this->appManager = $appManager;
81
+        $this->l10nFactory = $l10nFactory;
82
+        $this->l = $l;
83
+    }
84
+
85
+    /**
86
+     * @return TemplateResponse returns the instance with all parameters set, ready to be rendered
87
+     * @since 9.1
88
+     */
89
+    public function getForm() {
90
+        $federatedFileSharingEnabled = $this->appManager->isEnabledForUser('federatedfilesharing');
91
+        $lookupServerUploadEnabled = false;
92
+        if($federatedFileSharingEnabled) {
93
+            $federatedFileSharing = new Application();
94
+            $shareProvider = $federatedFileSharing->getFederatedShareProvider();
95
+            $lookupServerUploadEnabled = $shareProvider->isLookupServerUploadEnabled();
96
+        }
97
+
98
+        $uid = \OC_User::getUser();
99
+        $user = $this->userManager->get($uid);
100
+        $userData = $this->accountManager->getUser($user);
101
+
102
+        $storageInfo = \OC_Helper::getStorageInfo('/');
103
+        if ($storageInfo['quota'] === FileInfo::SPACE_UNLIMITED) {
104
+            $totalSpace = $this->l->t('Unlimited');
105
+        } else {
106
+            $totalSpace = \OC_Helper::humanFileSize($storageInfo['total']);
107
+        }
108
+
109
+        $languageParameters = $this->getLanguages($user);
110
+        $localeParameters = $this->getLocales($user);
111
+        $messageParameters = $this->getMessageParameters($userData);
112
+
113
+        $parameters = [
114
+            'total_space' => $totalSpace,
115
+            'usage' => \OC_Helper::humanFileSize($storageInfo['used']),
116
+            'usage_relative' => round($storageInfo['relative']),
117
+            'quota' => $storageInfo['quota'],
118
+            'avatarChangeSupported' => $user->canChangeAvatar(),
119
+            'lookupServerUploadEnabled' => $lookupServerUploadEnabled,
120
+            'avatarScope' => $userData[AccountManager::PROPERTY_AVATAR]['scope'],
121
+            'displayNameChangeSupported' => $user->canChangeDisplayName(),
122
+            'displayName' => $userData[AccountManager::PROPERTY_DISPLAYNAME]['value'],
123
+            'displayNameScope' => $userData[AccountManager::PROPERTY_DISPLAYNAME]['scope'],
124
+            'email' => $userData[AccountManager::PROPERTY_EMAIL]['value'],
125
+            'emailScope' => $userData[AccountManager::PROPERTY_EMAIL]['scope'],
126
+            'emailVerification' => $userData[AccountManager::PROPERTY_EMAIL]['verified'],
127
+            'phone' => $userData[AccountManager::PROPERTY_PHONE]['value'],
128
+            'phoneScope' => $userData[AccountManager::PROPERTY_PHONE]['scope'],
129
+            'address' => $userData[AccountManager::PROPERTY_ADDRESS]['value'],
130
+            'addressScope' => $userData[AccountManager::PROPERTY_ADDRESS]['scope'],
131
+            'website' =>  $userData[AccountManager::PROPERTY_WEBSITE]['value'],
132
+            'websiteScope' =>  $userData[AccountManager::PROPERTY_WEBSITE]['scope'],
133
+            'websiteVerification' => $userData[AccountManager::PROPERTY_WEBSITE]['verified'],
134
+            'twitter' => $userData[AccountManager::PROPERTY_TWITTER]['value'],
135
+            'twitterScope' => $userData[AccountManager::PROPERTY_TWITTER]['scope'],
136
+            'twitterVerification' => $userData[AccountManager::PROPERTY_TWITTER]['verified'],
137
+            'groups' => $this->getGroups($user),
138
+            'passwordChangeSupported' => $user->canChangePassword(),
139
+        ] + $messageParameters + $languageParameters + $localeParameters;
140
+
141
+
142
+        return new TemplateResponse('settings', 'settings/personal/personal.info', $parameters, '');
143
+    }
144
+
145
+    /**
146
+     * @return string the section ID, e.g. 'sharing'
147
+     * @since 9.1
148
+     */
149
+    public function getSection() {
150
+        return 'personal-info';
151
+    }
152
+
153
+    /**
154
+     * @return int whether the form should be rather on the top or bottom of
155
+     * the admin section. The forms are arranged in ascending order of the
156
+     * priority values. It is required to return a value between 0 and 100.
157
+     *
158
+     * E.g.: 70
159
+     * @since 9.1
160
+     */
161
+    public function getPriority() {
162
+        return 10;
163
+    }
164
+
165
+    /**
166
+     * returns a sorted list of the user's group GIDs
167
+     *
168
+     * @param IUser $user
169
+     * @return array
170
+     */
171
+    private function getGroups(IUser $user) {
172
+        $groups = array_map(
173
+            function(IGroup $group) {
174
+                return $group->getDisplayName();
175
+            },
176
+            $this->groupManager->getUserGroups($user)
177
+        );
178
+        sort($groups);
179
+
180
+        return $groups;
181
+    }
182
+
183
+    /**
184
+     * returns the user language, common language and other languages in an
185
+     * associative array
186
+     *
187
+     * @param IUser $user
188
+     * @return array
189
+     */
190
+    private function getLanguages(IUser $user) {
191
+        $forceLanguage = $this->config->getSystemValue('force_language', false);
192
+        if($forceLanguage !== false) {
193
+            return [];
194
+        }
195
+
196
+        $uid = $user->getUID();
197
+
198
+        $userConfLang = $this->config->getUserValue($uid, 'core', 'lang', $this->l10nFactory->findLanguage());
199
+        $languages = $this->l10nFactory->getLanguages();
200
+
201
+        // associate the user language with the proper array
202
+        $userLangIndex = array_search($userConfLang, array_column($languages['commonlanguages'], 'code'));
203
+        $userLang = $languages['commonlanguages'][$userLangIndex];
204
+        // search in the other languages
205
+        if ($userLangIndex === false) {
206
+            $userLangIndex = array_search($userConfLang, array_column($languages['languages'], 'code'));		
207
+            $userLang = $languages['languages'][$userLangIndex];
208
+        }
209
+        // if user language is not available but set somehow: show the actual code as name
210
+        if (!is_array($userLang)) {
211
+            $userLang = [
212
+                'code' => $userConfLang,
213
+                'name' => $userConfLang,
214
+            ];
215
+        }
216
+
217
+        return array_merge(
218
+            array('activelanguage' => $userLang),
219
+            $languages
220
+        );
221
+    }
222
+
223
+    private function getLocales(IUser $user) {
224
+        $forceLanguage = $this->config->getSystemValue('force_locale', false);
225
+        if($forceLanguage !== false) {
226
+            return [];
227
+        }
228
+
229
+        $uid = $user->getUID();
230
+
231
+        $userLocaleString = $this->config->getUserValue($uid, 'core', 'locale', 'en_US');
232
+
233
+        $userLang = $this->config->getUserValue($uid, 'core', 'lang', $this->l10nFactory->findLanguage());
234
+
235
+        $localeCodes = $this->l10nFactory->findAvailableLocales();
236
+
237
+        $userLocale = array_filter($localeCodes, function($value) use ($userLocaleString) {
238
+            return $userLocaleString === $value['code'];
239
+        });
240
+
241
+        if (!empty($userLocale))
242
+        {
243
+            $userLocale = reset($userLocale);
244
+        }
245
+
246
+        $localesForLanguage = array_filter($localeCodes, function($localeCode) use ($userLang) {
247
+            return 0 === strpos($localeCode['code'], $userLang);
248
+        });
249
+
250
+        return [
251
+            'activelocaleLang' => $userLocaleString,
252
+            'activelocale' => $userLocale,
253
+            'locales' => $localeCodes,
254
+            'localesforlanguage' => $localesForLanguage,
255
+        ];
256
+    }
257
+
258
+    /**
259
+     * @param array $userData
260
+     * @return array
261
+     */
262
+    private function getMessageParameters(array $userData) {
263
+        $needVerifyMessage = [AccountManager::PROPERTY_EMAIL, AccountManager::PROPERTY_WEBSITE, AccountManager::PROPERTY_TWITTER];
264
+        $messageParameters = [];
265
+        foreach ($needVerifyMessage as $property) {
266
+            switch ($userData[$property]['verified']) {
267
+                case AccountManager::VERIFIED:
268
+                    $message = $this->l->t('Verifying');
269
+                    break;
270
+                case AccountManager::VERIFICATION_IN_PROGRESS:
271
+                    $message = $this->l->t('Verifying …');
272
+                    break;
273
+                default:
274
+                    $message = $this->l->t('Verify');
275
+            }
276
+            $messageParameters[$property . 'Message'] = $message;
277
+        }
278
+        return $messageParameters;
279
+    }
280 280
 
281 281
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -89,7 +89,7 @@  discard block
 block discarded – undo
89 89
 	public function getForm() {
90 90
 		$federatedFileSharingEnabled = $this->appManager->isEnabledForUser('federatedfilesharing');
91 91
 		$lookupServerUploadEnabled = false;
92
-		if($federatedFileSharingEnabled) {
92
+		if ($federatedFileSharingEnabled) {
93 93
 			$federatedFileSharing = new Application();
94 94
 			$shareProvider = $federatedFileSharing->getFederatedShareProvider();
95 95
 			$lookupServerUploadEnabled = $shareProvider->isLookupServerUploadEnabled();
@@ -189,7 +189,7 @@  discard block
 block discarded – undo
189 189
 	 */
190 190
 	private function getLanguages(IUser $user) {
191 191
 		$forceLanguage = $this->config->getSystemValue('force_language', false);
192
-		if($forceLanguage !== false) {
192
+		if ($forceLanguage !== false) {
193 193
 			return [];
194 194
 		}
195 195
 
@@ -222,7 +222,7 @@  discard block
 block discarded – undo
222 222
 
223 223
 	private function getLocales(IUser $user) {
224 224
 		$forceLanguage = $this->config->getSystemValue('force_locale', false);
225
-		if($forceLanguage !== false) {
225
+		if ($forceLanguage !== false) {
226 226
 			return [];
227 227
 		}
228 228
 
@@ -273,7 +273,7 @@  discard block
 block discarded – undo
273 273
 				default:
274 274
 					$message = $this->l->t('Verify');
275 275
 			}
276
-			$messageParameters[$property . 'Message'] = $message;
276
+			$messageParameters[$property.'Message'] = $message;
277 277
 		}
278 278
 		return $messageParameters;
279 279
 	}
Please login to merge, or discard this patch.
lib/private/L10N/L10N.php 1 patch
Indentation   +212 added lines, -212 removed lines patch added patch discarded remove patch
@@ -33,216 +33,216 @@
 block discarded – undo
33 33
 
34 34
 class L10N implements IL10N {
35 35
 
36
-	/** @var IFactory */
37
-	protected $factory;
38
-
39
-	/** @var string App of this object */
40
-	protected $app;
41
-
42
-	/** @var string Language of this object */
43
-	protected $lang;
44
-
45
-	/** @var string Locale of this object */
46
-	protected $locale;
47
-
48
-	/** @var string Plural forms (string) */
49
-	private $pluralFormString = 'nplurals=2; plural=(n != 1);';
50
-
51
-	/** @var string Plural forms (function) */
52
-	private $pluralFormFunction = null;
53
-
54
-	/** @var string[] */
55
-	private $translations = [];
56
-
57
-	/**
58
-	 * @param IFactory $factory
59
-	 * @param string $app
60
-	 * @param string $lang
61
-	 * @param string $locale
62
-	 * @param array $files
63
-	 */
64
-	public function __construct(IFactory $factory, $app, $lang, $locale, array $files) {
65
-		$this->factory = $factory;
66
-		$this->app = $app;
67
-		$this->lang = $lang;
68
-		$this->locale = $locale;
69
-
70
-		foreach ($files as $languageFile) {
71
-			$this->load($languageFile);
72
-		}
73
-	}
74
-
75
-	/**
76
-	 * The code (en, de, ...) of the language that is used for this instance
77
-	 *
78
-	 * @return string language
79
-	 */
80
-	public function getLanguageCode(): string {
81
-		return $this->lang;
82
-	}
83
-
84
-	/**
85
-	 * The code (en_US, fr_CA, ...) of the locale that is used for this instance
86
-	 *
87
-	 * @return string locale
88
-	 */
89
-	public function getLocaleCode() {
90
-		return $this->locale;
91
-	}
92
-
93
-	/**
94
-	 * Translating
95
-	 * @param string $text The text we need a translation for
96
-	 * @param array|string $parameters default:array() Parameters for sprintf
97
-	 * @return string Translation or the same text
98
-	 *
99
-	 * Returns the translation. If no translation is found, $text will be
100
-	 * returned.
101
-	 */
102
-	public function t(string $text, $parameters = []): string {
103
-		if (!\is_array($parameters)) {
104
-			$parameters = [$parameters];
105
-		}
106
-
107
-		return (string) new L10NString($this, $text, $parameters);
108
-	}
109
-
110
-	/**
111
-	 * Translating
112
-	 * @param string $text_singular the string to translate for exactly one object
113
-	 * @param string $text_plural the string to translate for n objects
114
-	 * @param integer $count Number of objects
115
-	 * @param array $parameters default:array() Parameters for sprintf
116
-	 * @return string Translation or the same text
117
-	 *
118
-	 * Returns the translation. If no translation is found, $text will be
119
-	 * returned. %n will be replaced with the number of objects.
120
-	 *
121
-	 * The correct plural is determined by the plural_forms-function
122
-	 * provided by the po file.
123
-	 *
124
-	 */
125
-	public function n(string $text_singular, string $text_plural, int $count, array $parameters = []): string {
126
-		$identifier = "_${text_singular}_::_${text_plural}_";
127
-		if (isset($this->translations[$identifier])) {
128
-			return (string) new L10NString($this, $identifier, $parameters, $count);
129
-		}
130
-
131
-		if ($count === 1) {
132
-			return (string) new L10NString($this, $text_singular, $parameters, $count);
133
-		}
134
-
135
-		return (string) new L10NString($this, $text_plural, $parameters, $count);
136
-	}
137
-
138
-	/**
139
-	 * Localization
140
-	 * @param string $type Type of localization
141
-	 * @param \DateTime|int|string $data parameters for this localization
142
-	 * @param array $options
143
-	 * @return string|int|false
144
-	 *
145
-	 * Returns the localized data.
146
-	 *
147
-	 * Implemented types:
148
-	 *  - date
149
-	 *    - Creates a date
150
-	 *    - params: timestamp (int/string)
151
-	 *  - datetime
152
-	 *    - Creates date and time
153
-	 *    - params: timestamp (int/string)
154
-	 *  - time
155
-	 *    - Creates a time
156
-	 *    - params: timestamp (int/string)
157
-	 *  - firstday: Returns the first day of the week (0 sunday - 6 saturday)
158
-	 *  - jsdate: Returns the short JS date format
159
-	 */
160
-	public function l(string $type, $data = null, array $options = []) {
161
-		if (null === $this->locale) {
162
-			// Use the language of the instance
163
-			$this->locale = $this->getLanguageCode();
164
-		}
165
-		if ($this->locale === 'sr@latin') {
166
-			$this->locale = 'sr_latn';
167
-		}
168
-
169
-		if ($type === 'firstday') {
170
-			return (int) Calendar::getFirstWeekday($this->locale);
171
-		}
172
-		if ($type === 'jsdate') {
173
-			return (string) Calendar::getDateFormat('short', $this->locale);
174
-		}
175
-
176
-		$value = new \DateTime();
177
-		if ($data instanceof \DateTime) {
178
-			$value = $data;
179
-		} else if (\is_string($data) && !is_numeric($data)) {
180
-			$data = strtotime($data);
181
-			$value->setTimestamp($data);
182
-		} else if ($data !== null) {
183
-			$data = (int)$data;
184
-			$value->setTimestamp($data);
185
-		}
186
-
187
-		$options = array_merge(['width' => 'long'], $options);
188
-		$width = $options['width'];
189
-		switch ($type) {
190
-			case 'date':
191
-				return (string) Calendar::formatDate($value, $width, $this->locale);
192
-			case 'datetime':
193
-				return (string) Calendar::formatDatetime($value, $width, $this->locale);
194
-			case 'time':
195
-				return (string) Calendar::formatTime($value, $width, $this->locale);
196
-			case 'weekdayName':
197
-				return (string) Calendar::getWeekdayName($value, $width, $this->locale);
198
-			default:
199
-				return false;
200
-		}
201
-	}
202
-
203
-	/**
204
-	 * Returns an associative array with all translations
205
-	 *
206
-	 * Called by \OC_L10N_String
207
-	 * @return array
208
-	 */
209
-	public function getTranslations(): array {
210
-		return $this->translations;
211
-	}
212
-
213
-	/**
214
-	 * Returnsed function accepts the argument $n
215
-	 *
216
-	 * Called by \OC_L10N_String
217
-	 * @return \Closure the plural form function
218
-	 */
219
-	public function getPluralFormFunction(): \Closure {
220
-		if (\is_null($this->pluralFormFunction)) {
221
-			$lang = $this->getLanguageCode();
222
-			$this->pluralFormFunction = function($n) use ($lang) {
223
-				return PluralizationRules::get($n, $lang);
224
-			};
225
-		}
226
-
227
-		return $this->pluralFormFunction;
228
-	}
229
-
230
-	/**
231
-	 * @param string $translationFile
232
-	 * @return bool
233
-	 */
234
-	protected function load(string $translationFile): bool {
235
-		$json = json_decode(file_get_contents($translationFile), true);
236
-		if (!\is_array($json)) {
237
-			$jsonError = json_last_error();
238
-			\OC::$server->getLogger()->warning("Failed to load $translationFile - json error code: $jsonError", ['app' => 'l10n']);
239
-			return false;
240
-		}
241
-
242
-		if (!empty($json['pluralForm'])) {
243
-			$this->pluralFormString = $json['pluralForm'];
244
-		}
245
-		$this->translations = array_merge($this->translations, $json['translations']);
246
-		return true;
247
-	}
36
+    /** @var IFactory */
37
+    protected $factory;
38
+
39
+    /** @var string App of this object */
40
+    protected $app;
41
+
42
+    /** @var string Language of this object */
43
+    protected $lang;
44
+
45
+    /** @var string Locale of this object */
46
+    protected $locale;
47
+
48
+    /** @var string Plural forms (string) */
49
+    private $pluralFormString = 'nplurals=2; plural=(n != 1);';
50
+
51
+    /** @var string Plural forms (function) */
52
+    private $pluralFormFunction = null;
53
+
54
+    /** @var string[] */
55
+    private $translations = [];
56
+
57
+    /**
58
+     * @param IFactory $factory
59
+     * @param string $app
60
+     * @param string $lang
61
+     * @param string $locale
62
+     * @param array $files
63
+     */
64
+    public function __construct(IFactory $factory, $app, $lang, $locale, array $files) {
65
+        $this->factory = $factory;
66
+        $this->app = $app;
67
+        $this->lang = $lang;
68
+        $this->locale = $locale;
69
+
70
+        foreach ($files as $languageFile) {
71
+            $this->load($languageFile);
72
+        }
73
+    }
74
+
75
+    /**
76
+     * The code (en, de, ...) of the language that is used for this instance
77
+     *
78
+     * @return string language
79
+     */
80
+    public function getLanguageCode(): string {
81
+        return $this->lang;
82
+    }
83
+
84
+    /**
85
+     * The code (en_US, fr_CA, ...) of the locale that is used for this instance
86
+     *
87
+     * @return string locale
88
+     */
89
+    public function getLocaleCode() {
90
+        return $this->locale;
91
+    }
92
+
93
+    /**
94
+     * Translating
95
+     * @param string $text The text we need a translation for
96
+     * @param array|string $parameters default:array() Parameters for sprintf
97
+     * @return string Translation or the same text
98
+     *
99
+     * Returns the translation. If no translation is found, $text will be
100
+     * returned.
101
+     */
102
+    public function t(string $text, $parameters = []): string {
103
+        if (!\is_array($parameters)) {
104
+            $parameters = [$parameters];
105
+        }
106
+
107
+        return (string) new L10NString($this, $text, $parameters);
108
+    }
109
+
110
+    /**
111
+     * Translating
112
+     * @param string $text_singular the string to translate for exactly one object
113
+     * @param string $text_plural the string to translate for n objects
114
+     * @param integer $count Number of objects
115
+     * @param array $parameters default:array() Parameters for sprintf
116
+     * @return string Translation or the same text
117
+     *
118
+     * Returns the translation. If no translation is found, $text will be
119
+     * returned. %n will be replaced with the number of objects.
120
+     *
121
+     * The correct plural is determined by the plural_forms-function
122
+     * provided by the po file.
123
+     *
124
+     */
125
+    public function n(string $text_singular, string $text_plural, int $count, array $parameters = []): string {
126
+        $identifier = "_${text_singular}_::_${text_plural}_";
127
+        if (isset($this->translations[$identifier])) {
128
+            return (string) new L10NString($this, $identifier, $parameters, $count);
129
+        }
130
+
131
+        if ($count === 1) {
132
+            return (string) new L10NString($this, $text_singular, $parameters, $count);
133
+        }
134
+
135
+        return (string) new L10NString($this, $text_plural, $parameters, $count);
136
+    }
137
+
138
+    /**
139
+     * Localization
140
+     * @param string $type Type of localization
141
+     * @param \DateTime|int|string $data parameters for this localization
142
+     * @param array $options
143
+     * @return string|int|false
144
+     *
145
+     * Returns the localized data.
146
+     *
147
+     * Implemented types:
148
+     *  - date
149
+     *    - Creates a date
150
+     *    - params: timestamp (int/string)
151
+     *  - datetime
152
+     *    - Creates date and time
153
+     *    - params: timestamp (int/string)
154
+     *  - time
155
+     *    - Creates a time
156
+     *    - params: timestamp (int/string)
157
+     *  - firstday: Returns the first day of the week (0 sunday - 6 saturday)
158
+     *  - jsdate: Returns the short JS date format
159
+     */
160
+    public function l(string $type, $data = null, array $options = []) {
161
+        if (null === $this->locale) {
162
+            // Use the language of the instance
163
+            $this->locale = $this->getLanguageCode();
164
+        }
165
+        if ($this->locale === 'sr@latin') {
166
+            $this->locale = 'sr_latn';
167
+        }
168
+
169
+        if ($type === 'firstday') {
170
+            return (int) Calendar::getFirstWeekday($this->locale);
171
+        }
172
+        if ($type === 'jsdate') {
173
+            return (string) Calendar::getDateFormat('short', $this->locale);
174
+        }
175
+
176
+        $value = new \DateTime();
177
+        if ($data instanceof \DateTime) {
178
+            $value = $data;
179
+        } else if (\is_string($data) && !is_numeric($data)) {
180
+            $data = strtotime($data);
181
+            $value->setTimestamp($data);
182
+        } else if ($data !== null) {
183
+            $data = (int)$data;
184
+            $value->setTimestamp($data);
185
+        }
186
+
187
+        $options = array_merge(['width' => 'long'], $options);
188
+        $width = $options['width'];
189
+        switch ($type) {
190
+            case 'date':
191
+                return (string) Calendar::formatDate($value, $width, $this->locale);
192
+            case 'datetime':
193
+                return (string) Calendar::formatDatetime($value, $width, $this->locale);
194
+            case 'time':
195
+                return (string) Calendar::formatTime($value, $width, $this->locale);
196
+            case 'weekdayName':
197
+                return (string) Calendar::getWeekdayName($value, $width, $this->locale);
198
+            default:
199
+                return false;
200
+        }
201
+    }
202
+
203
+    /**
204
+     * Returns an associative array with all translations
205
+     *
206
+     * Called by \OC_L10N_String
207
+     * @return array
208
+     */
209
+    public function getTranslations(): array {
210
+        return $this->translations;
211
+    }
212
+
213
+    /**
214
+     * Returnsed function accepts the argument $n
215
+     *
216
+     * Called by \OC_L10N_String
217
+     * @return \Closure the plural form function
218
+     */
219
+    public function getPluralFormFunction(): \Closure {
220
+        if (\is_null($this->pluralFormFunction)) {
221
+            $lang = $this->getLanguageCode();
222
+            $this->pluralFormFunction = function($n) use ($lang) {
223
+                return PluralizationRules::get($n, $lang);
224
+            };
225
+        }
226
+
227
+        return $this->pluralFormFunction;
228
+    }
229
+
230
+    /**
231
+     * @param string $translationFile
232
+     * @return bool
233
+     */
234
+    protected function load(string $translationFile): bool {
235
+        $json = json_decode(file_get_contents($translationFile), true);
236
+        if (!\is_array($json)) {
237
+            $jsonError = json_last_error();
238
+            \OC::$server->getLogger()->warning("Failed to load $translationFile - json error code: $jsonError", ['app' => 'l10n']);
239
+            return false;
240
+        }
241
+
242
+        if (!empty($json['pluralForm'])) {
243
+            $this->pluralFormString = $json['pluralForm'];
244
+        }
245
+        $this->translations = array_merge($this->translations, $json['translations']);
246
+        return true;
247
+    }
248 248
 }
Please login to merge, or discard this patch.
lib/private/L10N/Factory.php 2 patches
Indentation   +547 added lines, -547 removed lines patch added patch discarded remove patch
@@ -40,551 +40,551 @@
 block discarded – undo
40 40
  */
41 41
 class Factory implements IFactory {
42 42
 
43
-	/** @var string */
44
-	protected $requestLanguage = '';
45
-
46
-	/**
47
-	 * cached instances
48
-	 * @var array Structure: Lang => App => \OCP\IL10N
49
-	 */
50
-	protected $instances = [];
51
-
52
-	/**
53
-	 * @var array Structure: App => string[]
54
-	 */
55
-	protected $availableLanguages = [];
56
-
57
-	/**
58
-	 * @var array Structure: string => callable
59
-	 */
60
-	protected $pluralFunctions = [];
61
-
62
-	const COMMON_LANGUAGE_CODES = [
63
-		'en', 'es', 'fr', 'de', 'de_DE', 'ja', 'ar', 'ru', 'nl', 'it',
64
-		'pt_BR', 'pt_PT', 'da', 'fi_FI', 'nb_NO', 'sv', 'tr', 'zh_CN', 'ko'
65
-	];
66
-
67
-	/** @var IConfig */
68
-	protected $config;
69
-
70
-	/** @var IRequest */
71
-	protected $request;
72
-
73
-	/** @var IUserSession */
74
-	protected $userSession;
75
-
76
-	/** @var string */
77
-	protected $serverRoot;
78
-
79
-	/**
80
-	 * @param IConfig $config
81
-	 * @param IRequest $request
82
-	 * @param IUserSession $userSession
83
-	 * @param string $serverRoot
84
-	 */
85
-	public function __construct(IConfig $config,
86
-								IRequest $request,
87
-								IUserSession $userSession,
88
-								$serverRoot) {
89
-		$this->config = $config;
90
-		$this->request = $request;
91
-		$this->userSession = $userSession;
92
-		$this->serverRoot = $serverRoot;
93
-	}
94
-
95
-	/**
96
-	 * Get a language instance
97
-	 *
98
-	 * @param string $app
99
-	 * @param string|null $lang
100
-	 * @param string|null $locale
101
-	 * @return \OCP\IL10N
102
-	 */
103
-	public function get($app, $lang = null, $locale = null) {
104
-		$app = \OC_App::cleanAppId($app);
105
-		if ($lang !== null) {
106
-			$lang = str_replace(array('\0', '/', '\\', '..'), '', (string) $lang);
107
-		}
108
-
109
-		$forceLang = $this->config->getSystemValue('force_language', false);
110
-		if (is_string($forceLang)) {
111
-			$lang = $forceLang;
112
-		}
113
-
114
-		$forceLocale = $this->config->getSystemValue('force_locale', false);
115
-		if (is_string($forceLocale)) {
116
-			$locale = $forceLocale;
117
-		}
118
-
119
-		if ($lang === null || !$this->languageExists($app, $lang)) {
120
-			$lang = $this->findLanguage($app);
121
-		}
122
-
123
-		if ($locale === null || !$this->localeExists($locale)) {
124
-			$locale = $this->findLocale($app, $lang);
125
-		}
126
-
127
-		if (!isset($this->instances[$lang][$app])) {
128
-			$this->instances[$lang][$app] = new L10N(
129
-				$this, $app, $lang, $locale,
130
-				$this->getL10nFilesForApp($app, $lang)
131
-			);
132
-		}
133
-
134
-		return $this->instances[$lang][$app];
135
-	}
136
-
137
-	/**
138
-	 * Find the best language
139
-	 *
140
-	 * @param string|null $app App id or null for core
141
-	 * @return string language If nothing works it returns 'en'
142
-	 */
143
-	public function findLanguage($app = null) {
144
-		$forceLang = $this->config->getSystemValue('force_language', false);
145
-		if (is_string($forceLang)) {
146
-			$this->requestLanguage = $forceLang;
147
-		}
148
-
149
-		if ($this->requestLanguage !== '' && $this->languageExists($app, $this->requestLanguage)) {
150
-			return $this->requestLanguage;
151
-		}
152
-
153
-		/**
154
-		 * At this point Nextcloud might not yet be installed and thus the lookup
155
-		 * in the preferences table might fail. For this reason we need to check
156
-		 * whether the instance has already been installed
157
-		 *
158
-		 * @link https://github.com/owncloud/core/issues/21955
159
-		 */
160
-		if ($this->config->getSystemValue('installed', false)) {
161
-			$userId = !is_null($this->userSession->getUser()) ? $this->userSession->getUser()->getUID() :  null;
162
-			if (!is_null($userId)) {
163
-				$userLang = $this->config->getUserValue($userId, 'core', 'lang', null);
164
-			} else {
165
-				$userLang = null;
166
-			}
167
-		} else {
168
-			$userId = null;
169
-			$userLang = null;
170
-		}
171
-
172
-		if ($userLang) {
173
-			$this->requestLanguage = $userLang;
174
-			if ($this->languageExists($app, $userLang)) {
175
-				return $userLang;
176
-			}
177
-		}
178
-
179
-		try {
180
-			// Try to get the language from the Request
181
-			$lang = $this->getLanguageFromRequest($app);
182
-			if ($userId !== null && $app === null && !$userLang) {
183
-				$this->config->setUserValue($userId, 'core', 'lang', $lang);
184
-			}
185
-			return $lang;
186
-		} catch (LanguageNotFoundException $e) {
187
-			// Finding language from request failed fall back to default language
188
-			$defaultLanguage = $this->config->getSystemValue('default_language', false);
189
-			if ($defaultLanguage !== false && $this->languageExists($app, $defaultLanguage)) {
190
-				return $defaultLanguage;
191
-			}
192
-		}
193
-
194
-		// We could not find any language so fall back to english
195
-		return 'en';
196
-	}
197
-
198
-	public function findLocale($lang = null)
199
-	{
200
-		if ($this->config->getSystemValue('installed', false)) {
201
-			$userId = null !== $this->userSession->getUser() ? $this->userSession->getUser()->getUID() :  null;
202
-			$userLocale = null;
203
-			if (null !== $userId) {
204
-				$userLocale = $this->config->getUserValue($userId, 'core', 'locale', null);
205
-			}
206
-		} else {
207
-			$userId = null;
208
-			$userLocale = null;
209
-		}
210
-
211
-		if ($userLocale && $this->localeExists($userLocale)) {
212
-			return $userLocale;
213
-		}
214
-
215
-		// Default : use system default locale
216
-		$defaultLocale = $this->config->getSystemValue('default_locale', false);
217
-		if ($defaultLocale !== false && $this->localeExists($defaultLocale)) {
218
-			return $defaultLocale;
219
-		}
220
-
221
-		// If no user locale set, use lang as locale
222
-		if (null !== $lang && $this->localeExists($lang)) {
223
-			return $lang;
224
-		}
225
-
226
-		// At last, return USA
227
-		return 'en_US';
228
-	}
229
-
230
-	/**
231
-	 * Find all available languages for an app
232
-	 *
233
-	 * @param string|null $app App id or null for core
234
-	 * @return array an array of available languages
235
-	 */
236
-	public function findAvailableLanguages($app = null) {
237
-		$key = $app;
238
-		if ($key === null) {
239
-			$key = 'null';
240
-		}
241
-
242
-		// also works with null as key
243
-		if (!empty($this->availableLanguages[$key])) {
244
-			return $this->availableLanguages[$key];
245
-		}
246
-
247
-		$available = ['en']; //english is always available
248
-		$dir = $this->findL10nDir($app);
249
-		if (is_dir($dir)) {
250
-			$files = scandir($dir);
251
-			if ($files !== false) {
252
-				foreach ($files as $file) {
253
-					if (substr($file, -5) === '.json' && substr($file, 0, 4) !== 'l10n') {
254
-						$available[] = substr($file, 0, -5);
255
-					}
256
-				}
257
-			}
258
-		}
259
-
260
-		// merge with translations from theme
261
-		$theme = $this->config->getSystemValue('theme');
262
-		if (!empty($theme)) {
263
-			$themeDir = $this->serverRoot . '/themes/' . $theme . substr($dir, strlen($this->serverRoot));
264
-
265
-			if (is_dir($themeDir)) {
266
-				$files = scandir($themeDir);
267
-				if ($files !== false) {
268
-					foreach ($files as $file) {
269
-						if (substr($file, -5) === '.json' && substr($file, 0, 4) !== 'l10n') {
270
-							$available[] = substr($file, 0, -5);
271
-						}
272
-					}
273
-				}
274
-			}
275
-		}
276
-
277
-		$this->availableLanguages[$key] = $available;
278
-		return $available;
279
-	}
280
-
281
-	public function findAvailableLocales()
282
-	{
283
-		$localeData = file_get_contents(__DIR__ . '/locales.json');
284
-		return json_decode($localeData, true);
285
-	}
286
-
287
-	/**
288
-	 * @param string|null $app App id or null for core
289
-	 * @param string $lang
290
-	 * @return bool
291
-	 */
292
-	public function languageExists($app, $lang) {
293
-		if ($lang === 'en') {//english is always available
294
-			return true;
295
-		}
296
-
297
-		$languages = $this->findAvailableLanguages($app);
298
-		return array_search($lang, $languages) !== false;
299
-	}
300
-
301
-	/**
302
-	 * @param string $locale
303
-	 * @return bool
304
-	 */
305
-	public function localeExists($locale) {
306
-		if ($locale === 'en') { //english is always available
307
-			return true;
308
-		}
309
-
310
-		$locales = $this->findAvailableLocales();
311
-
312
-		$userLocale = array_filter($locales, function($value) use ($locale) {
313
-			return $locale === $value['code'];
314
-		});
315
-
316
-		return !empty($userLocale);
317
-	}
318
-
319
-	/**
320
-	 * @param string|null $app
321
-	 * @return string
322
-	 * @throws LanguageNotFoundException
323
-	 */
324
-	private function getLanguageFromRequest($app) {
325
-		$header = $this->request->getHeader('ACCEPT_LANGUAGE');
326
-		if ($header !== '') {
327
-			$available = $this->findAvailableLanguages($app);
328
-
329
-			// E.g. make sure that 'de' is before 'de_DE'.
330
-			sort($available);
331
-
332
-			$preferences = preg_split('/,\s*/', strtolower($header));
333
-			foreach ($preferences as $preference) {
334
-				list($preferred_language) = explode(';', $preference);
335
-				$preferred_language = str_replace('-', '_', $preferred_language);
336
-
337
-				foreach ($available as $available_language) {
338
-					if ($preferred_language === strtolower($available_language)) {
339
-						return $this->respectDefaultLanguage($app, $available_language);
340
-					}
341
-				}
342
-
343
-				// Fallback from de_De to de
344
-				foreach ($available as $available_language) {
345
-					if (substr($preferred_language, 0, 2) === $available_language) {
346
-						return $available_language;
347
-					}
348
-				}
349
-			}
350
-		}
351
-
352
-		throw new LanguageNotFoundException();
353
-	}
354
-
355
-	/**
356
-	 * if default language is set to de_DE (formal German) this should be
357
-	 * preferred to 'de' (non-formal German) if possible
358
-	 *
359
-	 * @param string|null $app
360
-	 * @param string $lang
361
-	 * @return string
362
-	 */
363
-	protected function respectDefaultLanguage($app, $lang) {
364
-		$result = $lang;
365
-		$defaultLanguage = $this->config->getSystemValue('default_language', false);
366
-
367
-		// use formal version of german ("Sie" instead of "Du") if the default
368
-		// language is set to 'de_DE' if possible
369
-		if (is_string($defaultLanguage) &&
370
-			strtolower($lang) === 'de' &&
371
-			strtolower($defaultLanguage) === 'de_de' &&
372
-			$this->languageExists($app, 'de_DE')
373
-		) {
374
-			$result = 'de_DE';
375
-		}
376
-
377
-		return $result;
378
-	}
379
-
380
-	/**
381
-	 * Checks if $sub is a subdirectory of $parent
382
-	 *
383
-	 * @param string $sub
384
-	 * @param string $parent
385
-	 * @return bool
386
-	 */
387
-	private function isSubDirectory($sub, $parent) {
388
-		// Check whether $sub contains no ".."
389
-		if (strpos($sub, '..') !== false) {
390
-			return false;
391
-		}
392
-
393
-		// Check whether $sub is a subdirectory of $parent
394
-		if (strpos($sub, $parent) === 0) {
395
-			return true;
396
-		}
397
-
398
-		return false;
399
-	}
400
-
401
-	/**
402
-	 * Get a list of language files that should be loaded
403
-	 *
404
-	 * @param string $app
405
-	 * @param string $lang
406
-	 * @return string[]
407
-	 */
408
-	// FIXME This method is only public, until OC_L10N does not need it anymore,
409
-	// FIXME This is also the reason, why it is not in the public interface
410
-	public function getL10nFilesForApp($app, $lang) {
411
-		$languageFiles = [];
412
-
413
-		$i18nDir = $this->findL10nDir($app);
414
-		$transFile = strip_tags($i18nDir) . strip_tags($lang) . '.json';
415
-
416
-		if (($this->isSubDirectory($transFile, $this->serverRoot . '/core/l10n/')
417
-				|| $this->isSubDirectory($transFile, $this->serverRoot . '/lib/l10n/')
418
-				|| $this->isSubDirectory($transFile, $this->serverRoot . '/settings/l10n/')
419
-				|| $this->isSubDirectory($transFile, \OC_App::getAppPath($app) . '/l10n/')
420
-			)
421
-			&& file_exists($transFile)) {
422
-			// load the translations file
423
-			$languageFiles[] = $transFile;
424
-		}
425
-
426
-		// merge with translations from theme
427
-		$theme = $this->config->getSystemValue('theme');
428
-		if (!empty($theme)) {
429
-			$transFile = $this->serverRoot . '/themes/' . $theme . substr($transFile, strlen($this->serverRoot));
430
-			if (file_exists($transFile)) {
431
-				$languageFiles[] = $transFile;
432
-			}
433
-		}
434
-
435
-		return $languageFiles;
436
-	}
437
-
438
-	/**
439
-	 * find the l10n directory
440
-	 *
441
-	 * @param string $app App id or empty string for core
442
-	 * @return string directory
443
-	 */
444
-	protected function findL10nDir($app = null) {
445
-		if (in_array($app, ['core', 'lib', 'settings'])) {
446
-			if (file_exists($this->serverRoot . '/' . $app . '/l10n/')) {
447
-				return $this->serverRoot . '/' . $app . '/l10n/';
448
-			}
449
-		} else if ($app && \OC_App::getAppPath($app) !== false) {
450
-			// Check if the app is in the app folder
451
-			return \OC_App::getAppPath($app) . '/l10n/';
452
-		}
453
-		return $this->serverRoot . '/core/l10n/';
454
-	}
455
-
456
-
457
-	/**
458
-	 * Creates a function from the plural string
459
-	 *
460
-	 * Parts of the code is copied from Habari:
461
-	 * https://github.com/habari/system/blob/master/classes/locale.php
462
-	 * @param string $string
463
-	 * @return string
464
-	 */
465
-	public function createPluralFunction($string) {
466
-		if (isset($this->pluralFunctions[$string])) {
467
-			return $this->pluralFunctions[$string];
468
-		}
469
-
470
-		if (preg_match( '/^\s*nplurals\s*=\s*(\d+)\s*;\s*plural=(.*)$/u', $string, $matches)) {
471
-			// sanitize
472
-			$nplurals = preg_replace( '/[^0-9]/', '', $matches[1] );
473
-			$plural = preg_replace( '#[^n0-9:\(\)\?\|\&=!<>+*/\%-]#', '', $matches[2] );
474
-
475
-			$body = str_replace(
476
-				array( 'plural', 'n', '$n$plurals', ),
477
-				array( '$plural', '$n', '$nplurals', ),
478
-				'nplurals='. $nplurals . '; plural=' . $plural
479
-			);
480
-
481
-			// add parents
482
-			// important since PHP's ternary evaluates from left to right
483
-			$body .= ';';
484
-			$res = '';
485
-			$p = 0;
486
-			$length = strlen($body);
487
-			for($i = 0; $i < $length; $i++) {
488
-				$ch = $body[$i];
489
-				switch ( $ch ) {
490
-					case '?':
491
-						$res .= ' ? (';
492
-						$p++;
493
-						break;
494
-					case ':':
495
-						$res .= ') : (';
496
-						break;
497
-					case ';':
498
-						$res .= str_repeat( ')', $p ) . ';';
499
-						$p = 0;
500
-						break;
501
-					default:
502
-						$res .= $ch;
503
-				}
504
-			}
505
-
506
-			$body = $res . 'return ($plural>=$nplurals?$nplurals-1:$plural);';
507
-			$function = create_function('$n', $body);
508
-			$this->pluralFunctions[$string] = $function;
509
-			return $function;
510
-		} else {
511
-			// default: one plural form for all cases but n==1 (english)
512
-			$function = create_function(
513
-				'$n',
514
-				'$nplurals=2;$plural=($n==1?0:1);return ($plural>=$nplurals?$nplurals-1:$plural);'
515
-			);
516
-			$this->pluralFunctions[$string] = $function;
517
-			return $function;
518
-		}
519
-	}
520
-
521
-	/**
522
-	 * returns the common language and other languages in an
523
-	 * associative array
524
-	 *
525
-	 * @return array
526
-	 */
527
-	public function getLanguages() {
528
-		$forceLanguage = $this->config->getSystemValue('force_language', false);
529
-		if ($forceLanguage !== false) {
530
-			return [];
531
-		}
532
-
533
-		$languageCodes = $this->findAvailableLanguages();
534
-
535
-		$commonLanguages = [];
536
-		$languages = [];
537
-
538
-		foreach($languageCodes as $lang) {
539
-			$l = $this->get('lib', $lang);
540
-			// TRANSLATORS this is the language name for the language switcher in the personal settings and should be the localized version
541
-			$potentialName = (string) $l->t('__language_name__');
542
-			if ($l->getLanguageCode() === $lang && $potentialName[0] !== '_') {//first check if the language name is in the translation file
543
-				$ln = array(
544
-					'code' => $lang,
545
-					'name' => $potentialName
546
-				);
547
-			} else if ($lang === 'en') {
548
-				$ln = array(
549
-					'code' => $lang,
550
-					'name' => 'English (US)'
551
-				);
552
-			} else {//fallback to language code
553
-				$ln = array(
554
-					'code' => $lang,
555
-					'name' => $lang
556
-				);
557
-			}
558
-
559
-			// put appropriate languages into appropriate arrays, to print them sorted
560
-			// common languages -> divider -> other languages
561
-			if (in_array($lang, self::COMMON_LANGUAGE_CODES)) {
562
-				$commonLanguages[array_search($lang, self::COMMON_LANGUAGE_CODES)] = $ln;
563
-			} else {
564
-				$languages[] = $ln;
565
-			}
566
-		}
567
-
568
-		ksort($commonLanguages);
569
-
570
-		// sort now by displayed language not the iso-code
571
-		usort( $languages, function ($a, $b) {
572
-			if ($a['code'] === $a['name'] && $b['code'] !== $b['name']) {
573
-				// If a doesn't have a name, but b does, list b before a
574
-				return 1;
575
-			}
576
-			if ($a['code'] !== $a['name'] && $b['code'] === $b['name']) {
577
-				// If a does have a name, but b doesn't, list a before b
578
-				return -1;
579
-			}
580
-			// Otherwise compare the names
581
-			return strcmp($a['name'], $b['name']);
582
-		});
583
-
584
-		return [
585
-			// reset indexes
586
-			'commonlanguages' => array_values($commonLanguages),
587
-			'languages' => $languages
588
-		];
589
-	}
43
+    /** @var string */
44
+    protected $requestLanguage = '';
45
+
46
+    /**
47
+     * cached instances
48
+     * @var array Structure: Lang => App => \OCP\IL10N
49
+     */
50
+    protected $instances = [];
51
+
52
+    /**
53
+     * @var array Structure: App => string[]
54
+     */
55
+    protected $availableLanguages = [];
56
+
57
+    /**
58
+     * @var array Structure: string => callable
59
+     */
60
+    protected $pluralFunctions = [];
61
+
62
+    const COMMON_LANGUAGE_CODES = [
63
+        'en', 'es', 'fr', 'de', 'de_DE', 'ja', 'ar', 'ru', 'nl', 'it',
64
+        'pt_BR', 'pt_PT', 'da', 'fi_FI', 'nb_NO', 'sv', 'tr', 'zh_CN', 'ko'
65
+    ];
66
+
67
+    /** @var IConfig */
68
+    protected $config;
69
+
70
+    /** @var IRequest */
71
+    protected $request;
72
+
73
+    /** @var IUserSession */
74
+    protected $userSession;
75
+
76
+    /** @var string */
77
+    protected $serverRoot;
78
+
79
+    /**
80
+     * @param IConfig $config
81
+     * @param IRequest $request
82
+     * @param IUserSession $userSession
83
+     * @param string $serverRoot
84
+     */
85
+    public function __construct(IConfig $config,
86
+                                IRequest $request,
87
+                                IUserSession $userSession,
88
+                                $serverRoot) {
89
+        $this->config = $config;
90
+        $this->request = $request;
91
+        $this->userSession = $userSession;
92
+        $this->serverRoot = $serverRoot;
93
+    }
94
+
95
+    /**
96
+     * Get a language instance
97
+     *
98
+     * @param string $app
99
+     * @param string|null $lang
100
+     * @param string|null $locale
101
+     * @return \OCP\IL10N
102
+     */
103
+    public function get($app, $lang = null, $locale = null) {
104
+        $app = \OC_App::cleanAppId($app);
105
+        if ($lang !== null) {
106
+            $lang = str_replace(array('\0', '/', '\\', '..'), '', (string) $lang);
107
+        }
108
+
109
+        $forceLang = $this->config->getSystemValue('force_language', false);
110
+        if (is_string($forceLang)) {
111
+            $lang = $forceLang;
112
+        }
113
+
114
+        $forceLocale = $this->config->getSystemValue('force_locale', false);
115
+        if (is_string($forceLocale)) {
116
+            $locale = $forceLocale;
117
+        }
118
+
119
+        if ($lang === null || !$this->languageExists($app, $lang)) {
120
+            $lang = $this->findLanguage($app);
121
+        }
122
+
123
+        if ($locale === null || !$this->localeExists($locale)) {
124
+            $locale = $this->findLocale($app, $lang);
125
+        }
126
+
127
+        if (!isset($this->instances[$lang][$app])) {
128
+            $this->instances[$lang][$app] = new L10N(
129
+                $this, $app, $lang, $locale,
130
+                $this->getL10nFilesForApp($app, $lang)
131
+            );
132
+        }
133
+
134
+        return $this->instances[$lang][$app];
135
+    }
136
+
137
+    /**
138
+     * Find the best language
139
+     *
140
+     * @param string|null $app App id or null for core
141
+     * @return string language If nothing works it returns 'en'
142
+     */
143
+    public function findLanguage($app = null) {
144
+        $forceLang = $this->config->getSystemValue('force_language', false);
145
+        if (is_string($forceLang)) {
146
+            $this->requestLanguage = $forceLang;
147
+        }
148
+
149
+        if ($this->requestLanguage !== '' && $this->languageExists($app, $this->requestLanguage)) {
150
+            return $this->requestLanguage;
151
+        }
152
+
153
+        /**
154
+         * At this point Nextcloud might not yet be installed and thus the lookup
155
+         * in the preferences table might fail. For this reason we need to check
156
+         * whether the instance has already been installed
157
+         *
158
+         * @link https://github.com/owncloud/core/issues/21955
159
+         */
160
+        if ($this->config->getSystemValue('installed', false)) {
161
+            $userId = !is_null($this->userSession->getUser()) ? $this->userSession->getUser()->getUID() :  null;
162
+            if (!is_null($userId)) {
163
+                $userLang = $this->config->getUserValue($userId, 'core', 'lang', null);
164
+            } else {
165
+                $userLang = null;
166
+            }
167
+        } else {
168
+            $userId = null;
169
+            $userLang = null;
170
+        }
171
+
172
+        if ($userLang) {
173
+            $this->requestLanguage = $userLang;
174
+            if ($this->languageExists($app, $userLang)) {
175
+                return $userLang;
176
+            }
177
+        }
178
+
179
+        try {
180
+            // Try to get the language from the Request
181
+            $lang = $this->getLanguageFromRequest($app);
182
+            if ($userId !== null && $app === null && !$userLang) {
183
+                $this->config->setUserValue($userId, 'core', 'lang', $lang);
184
+            }
185
+            return $lang;
186
+        } catch (LanguageNotFoundException $e) {
187
+            // Finding language from request failed fall back to default language
188
+            $defaultLanguage = $this->config->getSystemValue('default_language', false);
189
+            if ($defaultLanguage !== false && $this->languageExists($app, $defaultLanguage)) {
190
+                return $defaultLanguage;
191
+            }
192
+        }
193
+
194
+        // We could not find any language so fall back to english
195
+        return 'en';
196
+    }
197
+
198
+    public function findLocale($lang = null)
199
+    {
200
+        if ($this->config->getSystemValue('installed', false)) {
201
+            $userId = null !== $this->userSession->getUser() ? $this->userSession->getUser()->getUID() :  null;
202
+            $userLocale = null;
203
+            if (null !== $userId) {
204
+                $userLocale = $this->config->getUserValue($userId, 'core', 'locale', null);
205
+            }
206
+        } else {
207
+            $userId = null;
208
+            $userLocale = null;
209
+        }
210
+
211
+        if ($userLocale && $this->localeExists($userLocale)) {
212
+            return $userLocale;
213
+        }
214
+
215
+        // Default : use system default locale
216
+        $defaultLocale = $this->config->getSystemValue('default_locale', false);
217
+        if ($defaultLocale !== false && $this->localeExists($defaultLocale)) {
218
+            return $defaultLocale;
219
+        }
220
+
221
+        // If no user locale set, use lang as locale
222
+        if (null !== $lang && $this->localeExists($lang)) {
223
+            return $lang;
224
+        }
225
+
226
+        // At last, return USA
227
+        return 'en_US';
228
+    }
229
+
230
+    /**
231
+     * Find all available languages for an app
232
+     *
233
+     * @param string|null $app App id or null for core
234
+     * @return array an array of available languages
235
+     */
236
+    public function findAvailableLanguages($app = null) {
237
+        $key = $app;
238
+        if ($key === null) {
239
+            $key = 'null';
240
+        }
241
+
242
+        // also works with null as key
243
+        if (!empty($this->availableLanguages[$key])) {
244
+            return $this->availableLanguages[$key];
245
+        }
246
+
247
+        $available = ['en']; //english is always available
248
+        $dir = $this->findL10nDir($app);
249
+        if (is_dir($dir)) {
250
+            $files = scandir($dir);
251
+            if ($files !== false) {
252
+                foreach ($files as $file) {
253
+                    if (substr($file, -5) === '.json' && substr($file, 0, 4) !== 'l10n') {
254
+                        $available[] = substr($file, 0, -5);
255
+                    }
256
+                }
257
+            }
258
+        }
259
+
260
+        // merge with translations from theme
261
+        $theme = $this->config->getSystemValue('theme');
262
+        if (!empty($theme)) {
263
+            $themeDir = $this->serverRoot . '/themes/' . $theme . substr($dir, strlen($this->serverRoot));
264
+
265
+            if (is_dir($themeDir)) {
266
+                $files = scandir($themeDir);
267
+                if ($files !== false) {
268
+                    foreach ($files as $file) {
269
+                        if (substr($file, -5) === '.json' && substr($file, 0, 4) !== 'l10n') {
270
+                            $available[] = substr($file, 0, -5);
271
+                        }
272
+                    }
273
+                }
274
+            }
275
+        }
276
+
277
+        $this->availableLanguages[$key] = $available;
278
+        return $available;
279
+    }
280
+
281
+    public function findAvailableLocales()
282
+    {
283
+        $localeData = file_get_contents(__DIR__ . '/locales.json');
284
+        return json_decode($localeData, true);
285
+    }
286
+
287
+    /**
288
+     * @param string|null $app App id or null for core
289
+     * @param string $lang
290
+     * @return bool
291
+     */
292
+    public function languageExists($app, $lang) {
293
+        if ($lang === 'en') {//english is always available
294
+            return true;
295
+        }
296
+
297
+        $languages = $this->findAvailableLanguages($app);
298
+        return array_search($lang, $languages) !== false;
299
+    }
300
+
301
+    /**
302
+     * @param string $locale
303
+     * @return bool
304
+     */
305
+    public function localeExists($locale) {
306
+        if ($locale === 'en') { //english is always available
307
+            return true;
308
+        }
309
+
310
+        $locales = $this->findAvailableLocales();
311
+
312
+        $userLocale = array_filter($locales, function($value) use ($locale) {
313
+            return $locale === $value['code'];
314
+        });
315
+
316
+        return !empty($userLocale);
317
+    }
318
+
319
+    /**
320
+     * @param string|null $app
321
+     * @return string
322
+     * @throws LanguageNotFoundException
323
+     */
324
+    private function getLanguageFromRequest($app) {
325
+        $header = $this->request->getHeader('ACCEPT_LANGUAGE');
326
+        if ($header !== '') {
327
+            $available = $this->findAvailableLanguages($app);
328
+
329
+            // E.g. make sure that 'de' is before 'de_DE'.
330
+            sort($available);
331
+
332
+            $preferences = preg_split('/,\s*/', strtolower($header));
333
+            foreach ($preferences as $preference) {
334
+                list($preferred_language) = explode(';', $preference);
335
+                $preferred_language = str_replace('-', '_', $preferred_language);
336
+
337
+                foreach ($available as $available_language) {
338
+                    if ($preferred_language === strtolower($available_language)) {
339
+                        return $this->respectDefaultLanguage($app, $available_language);
340
+                    }
341
+                }
342
+
343
+                // Fallback from de_De to de
344
+                foreach ($available as $available_language) {
345
+                    if (substr($preferred_language, 0, 2) === $available_language) {
346
+                        return $available_language;
347
+                    }
348
+                }
349
+            }
350
+        }
351
+
352
+        throw new LanguageNotFoundException();
353
+    }
354
+
355
+    /**
356
+     * if default language is set to de_DE (formal German) this should be
357
+     * preferred to 'de' (non-formal German) if possible
358
+     *
359
+     * @param string|null $app
360
+     * @param string $lang
361
+     * @return string
362
+     */
363
+    protected function respectDefaultLanguage($app, $lang) {
364
+        $result = $lang;
365
+        $defaultLanguage = $this->config->getSystemValue('default_language', false);
366
+
367
+        // use formal version of german ("Sie" instead of "Du") if the default
368
+        // language is set to 'de_DE' if possible
369
+        if (is_string($defaultLanguage) &&
370
+            strtolower($lang) === 'de' &&
371
+            strtolower($defaultLanguage) === 'de_de' &&
372
+            $this->languageExists($app, 'de_DE')
373
+        ) {
374
+            $result = 'de_DE';
375
+        }
376
+
377
+        return $result;
378
+    }
379
+
380
+    /**
381
+     * Checks if $sub is a subdirectory of $parent
382
+     *
383
+     * @param string $sub
384
+     * @param string $parent
385
+     * @return bool
386
+     */
387
+    private function isSubDirectory($sub, $parent) {
388
+        // Check whether $sub contains no ".."
389
+        if (strpos($sub, '..') !== false) {
390
+            return false;
391
+        }
392
+
393
+        // Check whether $sub is a subdirectory of $parent
394
+        if (strpos($sub, $parent) === 0) {
395
+            return true;
396
+        }
397
+
398
+        return false;
399
+    }
400
+
401
+    /**
402
+     * Get a list of language files that should be loaded
403
+     *
404
+     * @param string $app
405
+     * @param string $lang
406
+     * @return string[]
407
+     */
408
+    // FIXME This method is only public, until OC_L10N does not need it anymore,
409
+    // FIXME This is also the reason, why it is not in the public interface
410
+    public function getL10nFilesForApp($app, $lang) {
411
+        $languageFiles = [];
412
+
413
+        $i18nDir = $this->findL10nDir($app);
414
+        $transFile = strip_tags($i18nDir) . strip_tags($lang) . '.json';
415
+
416
+        if (($this->isSubDirectory($transFile, $this->serverRoot . '/core/l10n/')
417
+                || $this->isSubDirectory($transFile, $this->serverRoot . '/lib/l10n/')
418
+                || $this->isSubDirectory($transFile, $this->serverRoot . '/settings/l10n/')
419
+                || $this->isSubDirectory($transFile, \OC_App::getAppPath($app) . '/l10n/')
420
+            )
421
+            && file_exists($transFile)) {
422
+            // load the translations file
423
+            $languageFiles[] = $transFile;
424
+        }
425
+
426
+        // merge with translations from theme
427
+        $theme = $this->config->getSystemValue('theme');
428
+        if (!empty($theme)) {
429
+            $transFile = $this->serverRoot . '/themes/' . $theme . substr($transFile, strlen($this->serverRoot));
430
+            if (file_exists($transFile)) {
431
+                $languageFiles[] = $transFile;
432
+            }
433
+        }
434
+
435
+        return $languageFiles;
436
+    }
437
+
438
+    /**
439
+     * find the l10n directory
440
+     *
441
+     * @param string $app App id or empty string for core
442
+     * @return string directory
443
+     */
444
+    protected function findL10nDir($app = null) {
445
+        if (in_array($app, ['core', 'lib', 'settings'])) {
446
+            if (file_exists($this->serverRoot . '/' . $app . '/l10n/')) {
447
+                return $this->serverRoot . '/' . $app . '/l10n/';
448
+            }
449
+        } else if ($app && \OC_App::getAppPath($app) !== false) {
450
+            // Check if the app is in the app folder
451
+            return \OC_App::getAppPath($app) . '/l10n/';
452
+        }
453
+        return $this->serverRoot . '/core/l10n/';
454
+    }
455
+
456
+
457
+    /**
458
+     * Creates a function from the plural string
459
+     *
460
+     * Parts of the code is copied from Habari:
461
+     * https://github.com/habari/system/blob/master/classes/locale.php
462
+     * @param string $string
463
+     * @return string
464
+     */
465
+    public function createPluralFunction($string) {
466
+        if (isset($this->pluralFunctions[$string])) {
467
+            return $this->pluralFunctions[$string];
468
+        }
469
+
470
+        if (preg_match( '/^\s*nplurals\s*=\s*(\d+)\s*;\s*plural=(.*)$/u', $string, $matches)) {
471
+            // sanitize
472
+            $nplurals = preg_replace( '/[^0-9]/', '', $matches[1] );
473
+            $plural = preg_replace( '#[^n0-9:\(\)\?\|\&=!<>+*/\%-]#', '', $matches[2] );
474
+
475
+            $body = str_replace(
476
+                array( 'plural', 'n', '$n$plurals', ),
477
+                array( '$plural', '$n', '$nplurals', ),
478
+                'nplurals='. $nplurals . '; plural=' . $plural
479
+            );
480
+
481
+            // add parents
482
+            // important since PHP's ternary evaluates from left to right
483
+            $body .= ';';
484
+            $res = '';
485
+            $p = 0;
486
+            $length = strlen($body);
487
+            for($i = 0; $i < $length; $i++) {
488
+                $ch = $body[$i];
489
+                switch ( $ch ) {
490
+                    case '?':
491
+                        $res .= ' ? (';
492
+                        $p++;
493
+                        break;
494
+                    case ':':
495
+                        $res .= ') : (';
496
+                        break;
497
+                    case ';':
498
+                        $res .= str_repeat( ')', $p ) . ';';
499
+                        $p = 0;
500
+                        break;
501
+                    default:
502
+                        $res .= $ch;
503
+                }
504
+            }
505
+
506
+            $body = $res . 'return ($plural>=$nplurals?$nplurals-1:$plural);';
507
+            $function = create_function('$n', $body);
508
+            $this->pluralFunctions[$string] = $function;
509
+            return $function;
510
+        } else {
511
+            // default: one plural form for all cases but n==1 (english)
512
+            $function = create_function(
513
+                '$n',
514
+                '$nplurals=2;$plural=($n==1?0:1);return ($plural>=$nplurals?$nplurals-1:$plural);'
515
+            );
516
+            $this->pluralFunctions[$string] = $function;
517
+            return $function;
518
+        }
519
+    }
520
+
521
+    /**
522
+     * returns the common language and other languages in an
523
+     * associative array
524
+     *
525
+     * @return array
526
+     */
527
+    public function getLanguages() {
528
+        $forceLanguage = $this->config->getSystemValue('force_language', false);
529
+        if ($forceLanguage !== false) {
530
+            return [];
531
+        }
532
+
533
+        $languageCodes = $this->findAvailableLanguages();
534
+
535
+        $commonLanguages = [];
536
+        $languages = [];
537
+
538
+        foreach($languageCodes as $lang) {
539
+            $l = $this->get('lib', $lang);
540
+            // TRANSLATORS this is the language name for the language switcher in the personal settings and should be the localized version
541
+            $potentialName = (string) $l->t('__language_name__');
542
+            if ($l->getLanguageCode() === $lang && $potentialName[0] !== '_') {//first check if the language name is in the translation file
543
+                $ln = array(
544
+                    'code' => $lang,
545
+                    'name' => $potentialName
546
+                );
547
+            } else if ($lang === 'en') {
548
+                $ln = array(
549
+                    'code' => $lang,
550
+                    'name' => 'English (US)'
551
+                );
552
+            } else {//fallback to language code
553
+                $ln = array(
554
+                    'code' => $lang,
555
+                    'name' => $lang
556
+                );
557
+            }
558
+
559
+            // put appropriate languages into appropriate arrays, to print them sorted
560
+            // common languages -> divider -> other languages
561
+            if (in_array($lang, self::COMMON_LANGUAGE_CODES)) {
562
+                $commonLanguages[array_search($lang, self::COMMON_LANGUAGE_CODES)] = $ln;
563
+            } else {
564
+                $languages[] = $ln;
565
+            }
566
+        }
567
+
568
+        ksort($commonLanguages);
569
+
570
+        // sort now by displayed language not the iso-code
571
+        usort( $languages, function ($a, $b) {
572
+            if ($a['code'] === $a['name'] && $b['code'] !== $b['name']) {
573
+                // If a doesn't have a name, but b does, list b before a
574
+                return 1;
575
+            }
576
+            if ($a['code'] !== $a['name'] && $b['code'] === $b['name']) {
577
+                // If a does have a name, but b doesn't, list a before b
578
+                return -1;
579
+            }
580
+            // Otherwise compare the names
581
+            return strcmp($a['name'], $b['name']);
582
+        });
583
+
584
+        return [
585
+            // reset indexes
586
+            'commonlanguages' => array_values($commonLanguages),
587
+            'languages' => $languages
588
+        ];
589
+    }
590 590
 }
Please login to merge, or discard this patch.
Spacing   +26 added lines, -26 removed lines patch added patch discarded remove patch
@@ -158,7 +158,7 @@  discard block
 block discarded – undo
158 158
 		 * @link https://github.com/owncloud/core/issues/21955
159 159
 		 */
160 160
 		if ($this->config->getSystemValue('installed', false)) {
161
-			$userId = !is_null($this->userSession->getUser()) ? $this->userSession->getUser()->getUID() :  null;
161
+			$userId = !is_null($this->userSession->getUser()) ? $this->userSession->getUser()->getUID() : null;
162 162
 			if (!is_null($userId)) {
163 163
 				$userLang = $this->config->getUserValue($userId, 'core', 'lang', null);
164 164
 			} else {
@@ -198,7 +198,7 @@  discard block
 block discarded – undo
198 198
 	public function findLocale($lang = null)
199 199
 	{
200 200
 		if ($this->config->getSystemValue('installed', false)) {
201
-			$userId = null !== $this->userSession->getUser() ? $this->userSession->getUser()->getUID() :  null;
201
+			$userId = null !== $this->userSession->getUser() ? $this->userSession->getUser()->getUID() : null;
202 202
 			$userLocale = null;
203 203
 			if (null !== $userId) {
204 204
 				$userLocale = $this->config->getUserValue($userId, 'core', 'locale', null);
@@ -260,7 +260,7 @@  discard block
 block discarded – undo
260 260
 		// merge with translations from theme
261 261
 		$theme = $this->config->getSystemValue('theme');
262 262
 		if (!empty($theme)) {
263
-			$themeDir = $this->serverRoot . '/themes/' . $theme . substr($dir, strlen($this->serverRoot));
263
+			$themeDir = $this->serverRoot.'/themes/'.$theme.substr($dir, strlen($this->serverRoot));
264 264
 
265 265
 			if (is_dir($themeDir)) {
266 266
 				$files = scandir($themeDir);
@@ -280,7 +280,7 @@  discard block
 block discarded – undo
280 280
 
281 281
 	public function findAvailableLocales()
282 282
 	{
283
-		$localeData = file_get_contents(__DIR__ . '/locales.json');
283
+		$localeData = file_get_contents(__DIR__.'/locales.json');
284 284
 		return json_decode($localeData, true);
285 285
 	}
286 286
 
@@ -411,12 +411,12 @@  discard block
 block discarded – undo
411 411
 		$languageFiles = [];
412 412
 
413 413
 		$i18nDir = $this->findL10nDir($app);
414
-		$transFile = strip_tags($i18nDir) . strip_tags($lang) . '.json';
414
+		$transFile = strip_tags($i18nDir).strip_tags($lang).'.json';
415 415
 
416
-		if (($this->isSubDirectory($transFile, $this->serverRoot . '/core/l10n/')
417
-				|| $this->isSubDirectory($transFile, $this->serverRoot . '/lib/l10n/')
418
-				|| $this->isSubDirectory($transFile, $this->serverRoot . '/settings/l10n/')
419
-				|| $this->isSubDirectory($transFile, \OC_App::getAppPath($app) . '/l10n/')
416
+		if (($this->isSubDirectory($transFile, $this->serverRoot.'/core/l10n/')
417
+				|| $this->isSubDirectory($transFile, $this->serverRoot.'/lib/l10n/')
418
+				|| $this->isSubDirectory($transFile, $this->serverRoot.'/settings/l10n/')
419
+				|| $this->isSubDirectory($transFile, \OC_App::getAppPath($app).'/l10n/')
420 420
 			)
421 421
 			&& file_exists($transFile)) {
422 422
 			// load the translations file
@@ -426,7 +426,7 @@  discard block
 block discarded – undo
426 426
 		// merge with translations from theme
427 427
 		$theme = $this->config->getSystemValue('theme');
428 428
 		if (!empty($theme)) {
429
-			$transFile = $this->serverRoot . '/themes/' . $theme . substr($transFile, strlen($this->serverRoot));
429
+			$transFile = $this->serverRoot.'/themes/'.$theme.substr($transFile, strlen($this->serverRoot));
430 430
 			if (file_exists($transFile)) {
431 431
 				$languageFiles[] = $transFile;
432 432
 			}
@@ -443,14 +443,14 @@  discard block
 block discarded – undo
443 443
 	 */
444 444
 	protected function findL10nDir($app = null) {
445 445
 		if (in_array($app, ['core', 'lib', 'settings'])) {
446
-			if (file_exists($this->serverRoot . '/' . $app . '/l10n/')) {
447
-				return $this->serverRoot . '/' . $app . '/l10n/';
446
+			if (file_exists($this->serverRoot.'/'.$app.'/l10n/')) {
447
+				return $this->serverRoot.'/'.$app.'/l10n/';
448 448
 			}
449 449
 		} else if ($app && \OC_App::getAppPath($app) !== false) {
450 450
 			// Check if the app is in the app folder
451
-			return \OC_App::getAppPath($app) . '/l10n/';
451
+			return \OC_App::getAppPath($app).'/l10n/';
452 452
 		}
453
-		return $this->serverRoot . '/core/l10n/';
453
+		return $this->serverRoot.'/core/l10n/';
454 454
 	}
455 455
 
456 456
 
@@ -467,15 +467,15 @@  discard block
 block discarded – undo
467 467
 			return $this->pluralFunctions[$string];
468 468
 		}
469 469
 
470
-		if (preg_match( '/^\s*nplurals\s*=\s*(\d+)\s*;\s*plural=(.*)$/u', $string, $matches)) {
470
+		if (preg_match('/^\s*nplurals\s*=\s*(\d+)\s*;\s*plural=(.*)$/u', $string, $matches)) {
471 471
 			// sanitize
472
-			$nplurals = preg_replace( '/[^0-9]/', '', $matches[1] );
473
-			$plural = preg_replace( '#[^n0-9:\(\)\?\|\&=!<>+*/\%-]#', '', $matches[2] );
472
+			$nplurals = preg_replace('/[^0-9]/', '', $matches[1]);
473
+			$plural = preg_replace('#[^n0-9:\(\)\?\|\&=!<>+*/\%-]#', '', $matches[2]);
474 474
 
475 475
 			$body = str_replace(
476
-				array( 'plural', 'n', '$n$plurals', ),
477
-				array( '$plural', '$n', '$nplurals', ),
478
-				'nplurals='. $nplurals . '; plural=' . $plural
476
+				array('plural', 'n', '$n$plurals',),
477
+				array('$plural', '$n', '$nplurals',),
478
+				'nplurals='.$nplurals.'; plural='.$plural
479 479
 			);
480 480
 
481 481
 			// add parents
@@ -484,9 +484,9 @@  discard block
 block discarded – undo
484 484
 			$res = '';
485 485
 			$p = 0;
486 486
 			$length = strlen($body);
487
-			for($i = 0; $i < $length; $i++) {
487
+			for ($i = 0; $i < $length; $i++) {
488 488
 				$ch = $body[$i];
489
-				switch ( $ch ) {
489
+				switch ($ch) {
490 490
 					case '?':
491 491
 						$res .= ' ? (';
492 492
 						$p++;
@@ -495,7 +495,7 @@  discard block
 block discarded – undo
495 495
 						$res .= ') : (';
496 496
 						break;
497 497
 					case ';':
498
-						$res .= str_repeat( ')', $p ) . ';';
498
+						$res .= str_repeat(')', $p).';';
499 499
 						$p = 0;
500 500
 						break;
501 501
 					default:
@@ -503,7 +503,7 @@  discard block
 block discarded – undo
503 503
 				}
504 504
 			}
505 505
 
506
-			$body = $res . 'return ($plural>=$nplurals?$nplurals-1:$plural);';
506
+			$body = $res.'return ($plural>=$nplurals?$nplurals-1:$plural);';
507 507
 			$function = create_function('$n', $body);
508 508
 			$this->pluralFunctions[$string] = $function;
509 509
 			return $function;
@@ -535,7 +535,7 @@  discard block
 block discarded – undo
535 535
 		$commonLanguages = [];
536 536
 		$languages = [];
537 537
 
538
-		foreach($languageCodes as $lang) {
538
+		foreach ($languageCodes as $lang) {
539 539
 			$l = $this->get('lib', $lang);
540 540
 			// TRANSLATORS this is the language name for the language switcher in the personal settings and should be the localized version
541 541
 			$potentialName = (string) $l->t('__language_name__');
@@ -568,7 +568,7 @@  discard block
 block discarded – undo
568 568
 		ksort($commonLanguages);
569 569
 
570 570
 		// sort now by displayed language not the iso-code
571
-		usort( $languages, function ($a, $b) {
571
+		usort($languages, function($a, $b) {
572 572
 			if ($a['code'] === $a['name'] && $b['code'] !== $b['name']) {
573 573
 				// If a doesn't have a name, but b does, list b before a
574 574
 				return 1;
Please login to merge, or discard this patch.
apps/provisioning_api/lib/Controller/UsersController.php 1 patch
Indentation   +868 added lines, -868 removed lines patch added patch discarded remove patch
@@ -53,872 +53,872 @@
 block discarded – undo
53 53
 
54 54
 class UsersController extends AUserData {
55 55
 
56
-	/** @var IAppManager */
57
-	private $appManager;
58
-	/** @var ILogger */
59
-	private $logger;
60
-	/** @var IFactory */
61
-	private $l10nFactory;
62
-	/** @var NewUserMailHelper */
63
-	private $newUserMailHelper;
64
-	/** @var FederatedFileSharingFactory */
65
-	private $federatedFileSharingFactory;
66
-	/** @var ISecureRandom */
67
-	private $secureRandom;
68
-
69
-	/**
70
-	 * @param string $appName
71
-	 * @param IRequest $request
72
-	 * @param IUserManager $userManager
73
-	 * @param IConfig $config
74
-	 * @param IAppManager $appManager
75
-	 * @param IGroupManager $groupManager
76
-	 * @param IUserSession $userSession
77
-	 * @param AccountManager $accountManager
78
-	 * @param ILogger $logger
79
-	 * @param IFactory $l10nFactory
80
-	 * @param NewUserMailHelper $newUserMailHelper
81
-	 * @param FederatedFileSharingFactory $federatedFileSharingFactory
82
-	 * @param ISecureRandom $secureRandom
83
-	 */
84
-	public function __construct(string $appName,
85
-								IRequest $request,
86
-								IUserManager $userManager,
87
-								IConfig $config,
88
-								IAppManager $appManager,
89
-								IGroupManager $groupManager,
90
-								IUserSession $userSession,
91
-								AccountManager $accountManager,
92
-								ILogger $logger,
93
-								IFactory $l10nFactory,
94
-								NewUserMailHelper $newUserMailHelper,
95
-								FederatedFileSharingFactory $federatedFileSharingFactory,
96
-								ISecureRandom $secureRandom) {
97
-		parent::__construct($appName,
98
-							$request,
99
-							$userManager,
100
-							$config,
101
-							$groupManager,
102
-							$userSession,
103
-							$accountManager);
104
-
105
-		$this->appManager = $appManager;
106
-		$this->logger = $logger;
107
-		$this->l10nFactory = $l10nFactory;
108
-		$this->newUserMailHelper = $newUserMailHelper;
109
-		$this->federatedFileSharingFactory = $federatedFileSharingFactory;
110
-		$this->secureRandom = $secureRandom;
111
-	}
112
-
113
-	/**
114
-	 * @NoAdminRequired
115
-	 *
116
-	 * returns a list of users
117
-	 *
118
-	 * @param string $search
119
-	 * @param int $limit
120
-	 * @param int $offset
121
-	 * @return DataResponse
122
-	 */
123
-	public function getUsers(string $search = '', $limit = null, $offset = 0): DataResponse {
124
-		$user = $this->userSession->getUser();
125
-		$users = [];
126
-
127
-		// Admin? Or SubAdmin?
128
-		$uid = $user->getUID();
129
-		$subAdminManager = $this->groupManager->getSubAdmin();
130
-		if ($this->groupManager->isAdmin($uid)){
131
-			$users = $this->userManager->search($search, $limit, $offset);
132
-		} else if ($subAdminManager->isSubAdmin($user)) {
133
-			$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
134
-			foreach ($subAdminOfGroups as $key => $group) {
135
-				$subAdminOfGroups[$key] = $group->getGID();
136
-			}
137
-
138
-			$users = [];
139
-			foreach ($subAdminOfGroups as $group) {
140
-				$users = array_merge($users, $this->groupManager->displayNamesInGroup($group, $search, $limit, $offset));
141
-			}
142
-		}
143
-
144
-		$users = array_keys($users);
145
-
146
-		return new DataResponse([
147
-			'users' => $users
148
-		]);
149
-	}
150
-
151
-	/**
152
-	 * @NoAdminRequired
153
-	 *
154
-	 * returns a list of users and their data
155
-	 */
156
-	public function getUsersDetails(string $search = '', $limit = null, $offset = 0): DataResponse {
157
-		$user = $this->userSession->getUser();
158
-		$users = [];
159
-
160
-		// Admin? Or SubAdmin?
161
-		$uid = $user->getUID();
162
-		$subAdminManager = $this->groupManager->getSubAdmin();
163
-		if ($this->groupManager->isAdmin($uid)){
164
-			$users = $this->userManager->search($search, $limit, $offset);
165
-		} else if ($subAdminManager->isSubAdmin($user)) {
166
-			$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
167
-			foreach ($subAdminOfGroups as $key => $group) {
168
-				$subAdminOfGroups[$key] = $group->getGID();
169
-			}
170
-
171
-			$users = [];
172
-			foreach ($subAdminOfGroups as $group) {
173
-				$users = array_merge($users, $this->groupManager->displayNamesInGroup($group, $search, $limit, $offset));
174
-			}
175
-		}
176
-
177
-		$users = array_keys($users);
178
-		$usersDetails = [];
179
-		foreach ($users as $key => $userId) {
180
-			$userData = $this->getUserData($userId);
181
-			// Do not insert empty entry
182
-			if (!empty($userData)) {
183
-				$usersDetails[$userId] = $userData;
184
-			} else {
185
-				// Logged user does not have permissions to see this user
186
-				// only showing its id
187
-				$usersDetails[$userId] = ['id' => $userId];
188
-			}
189
-		}
190
-
191
-		return new DataResponse([
192
-			'users' => $usersDetails
193
-		]);
194
-	}
195
-
196
-	/**
197
-	 * @PasswordConfirmationRequired
198
-	 * @NoAdminRequired
199
-	 *
200
-	 * @param string $userid
201
-	 * @param string $password
202
-	 * @param string $email
203
-	 * @param array $groups
204
-	 * @param array $subadmins
205
-	 * @param string $quota
206
-	 * @param string $language
207
-	 * @return DataResponse
208
-	 * @throws OCSException
209
-	 */
210
-	public function addUser(string $userid,
211
-							string $password = '',
212
-							string $email = '',
213
-							array $groups = [],
214
-							array $subadmin = [],
215
-							string $quota = '',
216
-							string $language = ''): DataResponse {
217
-		$user = $this->userSession->getUser();
218
-		$isAdmin = $this->groupManager->isAdmin($user->getUID());
219
-		$subAdminManager = $this->groupManager->getSubAdmin();
220
-
221
-		if ($this->userManager->userExists($userid)) {
222
-			$this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
223
-			throw new OCSException('User already exists', 102);
224
-		}
225
-
226
-		if ($groups !== []) {
227
-			foreach ($groups as $group) {
228
-				if (!$this->groupManager->groupExists($group)) {
229
-					throw new OCSException('group '.$group.' does not exist', 104);
230
-				}
231
-				if (!$isAdmin && !$subAdminManager->isSubAdminOfGroup($user, $this->groupManager->get($group))) {
232
-					throw new OCSException('insufficient privileges for group '. $group, 105);
233
-				}
234
-			}
235
-		} else {
236
-			if (!$isAdmin) {
237
-				throw new OCSException('no group specified (required for subadmins)', 106);
238
-			}
239
-		}
240
-
241
-		$subadminGroups = [];
242
-		if ($subadmin !== []) {
243
-			foreach ($subadmin as $groupid) {
244
-				$group = $this->groupManager->get($groupid);
245
-				// Check if group exists
246
-				if ($group === null) {
247
-					throw new OCSException('Subadmin group does not exist',  102);
248
-				}
249
-				// Check if trying to make subadmin of admin group
250
-				if ($group->getGID() === 'admin') {
251
-					throw new OCSException('Cannot create subadmins for admin group', 103);
252
-				}
253
-				// Check if has permission to promote subadmins
254
-				if (!$subAdminManager->isSubAdminOfGroup($user, $group) && !$isAdmin) {
255
-					throw new OCSForbiddenException('No permissions to promote subadmins');
256
-				}
257
-				$subadminGroups[] = $group;
258
-			}
259
-		}
260
-
261
-		$generatePasswordResetToken = false;
262
-		if ($password === '') {
263
-			if ($email === '') {
264
-				throw new OCSException('To send a password link to the user an email address is required.', 108);
265
-			}
266
-
267
-			$password = $this->secureRandom->generate(10);
268
-			// Make sure we pass the password_policy
269
-			$password .= $this->secureRandom->generate(2, '$!.,;:-~+*[]{}()');
270
-			$generatePasswordResetToken = true;
271
-		}
272
-
273
-		try {
274
-			$newUser = $this->userManager->createUser($userid, $password);
275
-			$this->logger->info('Successful addUser call with userid: ' . $userid, ['app' => 'ocs_api']);
276
-
277
-			foreach ($groups as $group) {
278
-				$this->groupManager->get($group)->addUser($newUser);
279
-				$this->logger->info('Added userid ' . $userid . ' to group ' . $group, ['app' => 'ocs_api']);
280
-			}
281
-			foreach ($subadminGroups as $group) {
282
-				$subAdminManager->createSubAdmin($newUser, $group);
283
-			}
284
-
285
-			if ($quota !== '') {
286
-				$this->editUser($userid, 'quota', $quota);
287
-			}
288
-
289
-			if ($language !== '') {
290
-				$this->editUser($userid, 'language', $language);
291
-			}
292
-
293
-			// Send new user mail only if a mail is set
294
-			if ($email !== '') {
295
-				$newUser->setEMailAddress($email);
296
-				try {
297
-					$emailTemplate = $this->newUserMailHelper->generateTemplate($newUser, $generatePasswordResetToken);
298
-					$this->newUserMailHelper->sendMail($newUser, $emailTemplate);
299
-				} catch (\Exception $e) {
300
-					$this->logger->logException($e, [
301
-						'message' => "Can't send new user mail to $email",
302
-						'level' => ILogger::ERROR,
303
-						'app' => 'ocs_api',
304
-					]);
305
-					throw new OCSException('Unable to send the invitation mail', 109);
306
-				}
307
-			}
308
-
309
-			return new DataResponse();
310
-
311
-		} catch (HintException $e ) {
312
-			$this->logger->logException($e, [
313
-				'message' => 'Failed addUser attempt with hint exception.',
314
-				'level' => ILogger::WARN,
315
-				'app' => 'ocs_api',
316
-			]);
317
-			throw new OCSException($e->getHint(), 107);
318
-		} catch (\Exception $e) {
319
-			$this->logger->logException($e, [
320
-				'message' => 'Failed addUser attempt with exception.',
321
-				'level' => ILogger::ERROR,
322
-				'app' => 'ocs_api',
323
-			]);
324
-			throw new OCSException('Bad request', 101);
325
-		}
326
-	}
327
-
328
-	/**
329
-	 * @NoAdminRequired
330
-	 * @NoSubAdminRequired
331
-	 *
332
-	 * gets user info
333
-	 *
334
-	 * @param string $userId
335
-	 * @return DataResponse
336
-	 * @throws OCSException
337
-	 */
338
-	public function getUser(string $userId): DataResponse {
339
-		$data = $this->getUserData($userId);
340
-		// getUserData returns empty array if not enough permissions
341
-		if (empty($data)) {
342
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
343
-		}
344
-		return new DataResponse($data);
345
-	}
346
-
347
-	/**
348
-	 * @NoAdminRequired
349
-	 * @NoSubAdminRequired
350
-	 *
351
-	 * gets user info from the currently logged in user
352
-	 *
353
-	 * @return DataResponse
354
-	 * @throws OCSException
355
-	 */
356
-	public function getCurrentUser(): DataResponse {
357
-		$user = $this->userSession->getUser();
358
-		if ($user) {
359
-			$data =  $this->getUserData($user->getUID());
360
-			// rename "displayname" to "display-name" only for this call to keep
361
-			// the API stable.
362
-			$data['display-name'] = $data['displayname'];
363
-			unset($data['displayname']);
364
-			return new DataResponse($data);
365
-
366
-		}
367
-
368
-		throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
369
-	}
370
-
371
-	/**
372
-	 * @NoAdminRequired
373
-	 * @NoSubAdminRequired
374
-	 */
375
-	public function getEditableFields(): DataResponse {
376
-		$permittedFields = [];
377
-
378
-		// Editing self (display, email)
379
-		if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
380
-			$permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
381
-			$permittedFields[] = AccountManager::PROPERTY_EMAIL;
382
-		}
383
-
384
-		if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
385
-			$federatedFileSharing = $this->federatedFileSharingFactory->get();
386
-			$shareProvider = $federatedFileSharing->getFederatedShareProvider();
387
-			if ($shareProvider->isLookupServerUploadEnabled()) {
388
-				$permittedFields[] = AccountManager::PROPERTY_PHONE;
389
-				$permittedFields[] = AccountManager::PROPERTY_ADDRESS;
390
-				$permittedFields[] = AccountManager::PROPERTY_WEBSITE;
391
-				$permittedFields[] = AccountManager::PROPERTY_TWITTER;
392
-			}
393
-		}
394
-
395
-		// Find the data
396
-		$data['id'] = $targetUserObject->getUID();
397
-		$data['quota'] = $this->fillStorageInfo($targetUserObject->getUID());
398
-		$data[AccountManager::PROPERTY_EMAIL] = $targetUserObject->getEMailAddress();
399
-		$data[AccountManager::PROPERTY_DISPLAYNAME] = $targetUserObject->getDisplayName();
400
-		$data[AccountManager::PROPERTY_PHONE] = $userAccount[AccountManager::PROPERTY_PHONE]['value'];
401
-		$data[AccountManager::PROPERTY_ADDRESS] = $userAccount[AccountManager::PROPERTY_ADDRESS]['value'];
402
-		$data[AccountManager::PROPERTY_WEBSITE] = $userAccount[AccountManager::PROPERTY_WEBSITE]['value'];
403
-		$data[AccountManager::PROPERTY_TWITTER] = $userAccount[AccountManager::PROPERTY_TWITTER]['value'];
404
-		$data['groups'] = $gids;
405
-		$data['language'] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'lang');
406
-		$data['locale'] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'locale');
407
-
408
-		return new DataResponse($permittedFields);
409
-	}
410
-
411
-	/**
412
-	 * @NoAdminRequired
413
-	 * @NoSubAdminRequired
414
-	 * @PasswordConfirmationRequired
415
-	 *
416
-	 * edit users
417
-	 *
418
-	 * @param string $userId
419
-	 * @param string $key
420
-	 * @param string $value
421
-	 * @return DataResponse
422
-	 * @throws OCSException
423
-	 */
424
-	public function editUser(string $userId, string $key, string $value): DataResponse {
425
-		$currentLoggedInUser = $this->userSession->getUser();
426
-
427
-		$targetUser = $this->userManager->get($userId);
428
-		if ($targetUser === null) {
429
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
430
-		}
431
-
432
-		$permittedFields = [];
433
-		if ($targetUser->getUID() === $currentLoggedInUser->getUID()) {
434
-			// Editing self (display, email)
435
-			if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
436
-				$permittedFields[] = 'display';
437
-				$permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
438
-				$permittedFields[] = AccountManager::PROPERTY_EMAIL;
439
-			}
440
-
441
-			$permittedFields[] = 'password';
442
-			if ($this->config->getSystemValue('force_language', false) === false ||
443
-				$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
444
-				$permittedFields[] = 'language';
445
-			}
446
-
447
-			if ($this->config->getSystemValue('force_locale', false) === false ||
448
-				$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
449
-				$permittedFields[] = 'locale';
450
-			}
451
-
452
-			if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
453
-				$federatedFileSharing = new \OCA\FederatedFileSharing\AppInfo\Application();
454
-				$shareProvider = $federatedFileSharing->getFederatedShareProvider();
455
-				if ($shareProvider->isLookupServerUploadEnabled()) {
456
-					$permittedFields[] = AccountManager::PROPERTY_PHONE;
457
-					$permittedFields[] = AccountManager::PROPERTY_ADDRESS;
458
-					$permittedFields[] = AccountManager::PROPERTY_WEBSITE;
459
-					$permittedFields[] = AccountManager::PROPERTY_TWITTER;
460
-				}
461
-			}
462
-
463
-			// If admin they can edit their own quota
464
-			if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
465
-				$permittedFields[] = 'quota';
466
-			}
467
-		} else {
468
-			// Check if admin / subadmin
469
-			$subAdminManager = $this->groupManager->getSubAdmin();
470
-			if ($subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
471
-			|| $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
472
-				// They have permissions over the user
473
-				$permittedFields[] = 'display';
474
-				$permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
475
-				$permittedFields[] = AccountManager::PROPERTY_EMAIL;
476
-				$permittedFields[] = 'password';
477
-				$permittedFields[] = 'language';
478
-				$permittedFields[] = 'locale';
479
-				$permittedFields[] = AccountManager::PROPERTY_PHONE;
480
-				$permittedFields[] = AccountManager::PROPERTY_ADDRESS;
481
-				$permittedFields[] = AccountManager::PROPERTY_WEBSITE;
482
-				$permittedFields[] = AccountManager::PROPERTY_TWITTER;
483
-				$permittedFields[] = 'quota';
484
-			} else {
485
-				// No rights
486
-				throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
487
-			}
488
-		}
489
-		// Check if permitted to edit this field
490
-		if (!in_array($key, $permittedFields)) {
491
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
492
-		}
493
-		// Process the edit
494
-		switch($key) {
495
-			case 'display':
496
-			case AccountManager::PROPERTY_DISPLAYNAME:
497
-				$targetUser->setDisplayName($value);
498
-				break;
499
-			case 'quota':
500
-				$quota = $value;
501
-				if ($quota !== 'none' && $quota !== 'default') {
502
-					if (is_numeric($quota)) {
503
-						$quota = (float) $quota;
504
-					} else {
505
-						$quota = \OCP\Util::computerFileSize($quota);
506
-					}
507
-					if ($quota === false) {
508
-						throw new OCSException('Invalid quota value '.$value, 103);
509
-					}
510
-					if ($quota === -1) {
511
-						$quota = 'none';
512
-					} else {
513
-						$quota = \OCP\Util::humanFileSize($quota);
514
-					}
515
-				}
516
-				$targetUser->setQuota($quota);
517
-				break;
518
-			case 'password':
519
-				$targetUser->setPassword($value);
520
-				break;
521
-			case 'language':
522
-				$languagesCodes = $this->l10nFactory->findAvailableLanguages();
523
-				if (!in_array($value, $languagesCodes, true) && $value !== 'en') {
524
-					throw new OCSException('Invalid language', 102);
525
-				}
526
-				$this->config->setUserValue($targetUser->getUID(), 'core', 'lang', $value);
527
-				break;
528
-			case 'locale':
529
-				if (!$this->l10nFactory->localeExists($value)) {
530
-					throw new OCSException('Invalid locale', 102);
531
-				}
532
-				$this->config->setUserValue($targetUser->getUID(), 'core', 'locale', $value);
533
-				break;
534
-			case AccountManager::PROPERTY_EMAIL:
535
-				if (filter_var($value, FILTER_VALIDATE_EMAIL) || $value === '') {
536
-					$targetUser->setEMailAddress($value);
537
-				} else {
538
-					throw new OCSException('', 102);
539
-				}
540
-				break;
541
-			case AccountManager::PROPERTY_PHONE:
542
-			case AccountManager::PROPERTY_ADDRESS:
543
-			case AccountManager::PROPERTY_WEBSITE:
544
-			case AccountManager::PROPERTY_TWITTER:
545
-				$userAccount = $this->accountManager->getUser($targetUser);
546
-				if ($userAccount[$key]['value'] !== $value) {
547
-					$userAccount[$key]['value'] = $value;
548
-					$this->accountManager->updateUser($targetUser, $userAccount);
549
-				}
550
-				break;
551
-			default:
552
-				throw new OCSException('', 103);
553
-		}
554
-		return new DataResponse();
555
-	}
556
-
557
-	/**
558
-	 * @PasswordConfirmationRequired
559
-	 * @NoAdminRequired
560
-	 *
561
-	 * @param string $userId
562
-	 * @return DataResponse
563
-	 * @throws OCSException
564
-	 */
565
-	public function deleteUser(string $userId): DataResponse {
566
-		$currentLoggedInUser = $this->userSession->getUser();
567
-
568
-		$targetUser = $this->userManager->get($userId);
569
-
570
-		if ($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
571
-			throw new OCSException('', 101);
572
-		}
573
-
574
-		// If not permitted
575
-		$subAdminManager = $this->groupManager->getSubAdmin();
576
-		if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
577
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
578
-		}
579
-
580
-		// Go ahead with the delete
581
-		if ($targetUser->delete()) {
582
-			return new DataResponse();
583
-		} else {
584
-			throw new OCSException('', 101);
585
-		}
586
-	}
587
-
588
-	/**
589
-	 * @PasswordConfirmationRequired
590
-	 * @NoAdminRequired
591
-	 *
592
-	 * @param string $userId
593
-	 * @return DataResponse
594
-	 * @throws OCSException
595
-	 * @throws OCSForbiddenException
596
-	 */
597
-	public function disableUser(string $userId): DataResponse {
598
-		return $this->setEnabled($userId, false);
599
-	}
600
-
601
-	/**
602
-	 * @PasswordConfirmationRequired
603
-	 * @NoAdminRequired
604
-	 *
605
-	 * @param string $userId
606
-	 * @return DataResponse
607
-	 * @throws OCSException
608
-	 * @throws OCSForbiddenException
609
-	 */
610
-	public function enableUser(string $userId): DataResponse {
611
-		return $this->setEnabled($userId, true);
612
-	}
613
-
614
-	/**
615
-	 * @param string $userId
616
-	 * @param bool $value
617
-	 * @return DataResponse
618
-	 * @throws OCSException
619
-	 */
620
-	private function setEnabled(string $userId, bool $value): DataResponse {
621
-		$currentLoggedInUser = $this->userSession->getUser();
622
-
623
-		$targetUser = $this->userManager->get($userId);
624
-		if ($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
625
-			throw new OCSException('', 101);
626
-		}
627
-
628
-		// If not permitted
629
-		$subAdminManager = $this->groupManager->getSubAdmin();
630
-		if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
631
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
632
-		}
633
-
634
-		// enable/disable the user now
635
-		$targetUser->setEnabled($value);
636
-		return new DataResponse();
637
-	}
638
-
639
-	/**
640
-	 * @NoAdminRequired
641
-	 * @NoSubAdminRequired
642
-	 *
643
-	 * @param string $userId
644
-	 * @return DataResponse
645
-	 * @throws OCSException
646
-	 */
647
-	public function getUsersGroups(string $userId): DataResponse {
648
-		$loggedInUser = $this->userSession->getUser();
649
-
650
-		$targetUser = $this->userManager->get($userId);
651
-		if ($targetUser === null) {
652
-			throw new OCSException('', \OCP\API::RESPOND_NOT_FOUND);
653
-		}
654
-
655
-		if ($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) {
656
-			// Self lookup or admin lookup
657
-			return new DataResponse([
658
-				'groups' => $this->groupManager->getUserGroupIds($targetUser)
659
-			]);
660
-		} else {
661
-			$subAdminManager = $this->groupManager->getSubAdmin();
662
-
663
-			// Looking up someone else
664
-			if ($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) {
665
-				// Return the group that the method caller is subadmin of for the user in question
666
-				/** @var IGroup[] $getSubAdminsGroups */
667
-				$getSubAdminsGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
668
-				foreach ($getSubAdminsGroups as $key => $group) {
669
-					$getSubAdminsGroups[$key] = $group->getGID();
670
-				}
671
-				$groups = array_intersect(
672
-					$getSubAdminsGroups,
673
-					$this->groupManager->getUserGroupIds($targetUser)
674
-				);
675
-				return new DataResponse(['groups' => $groups]);
676
-			} else {
677
-				// Not permitted
678
-				throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
679
-			}
680
-		}
681
-
682
-	}
683
-
684
-	/**
685
-	 * @PasswordConfirmationRequired
686
-	 * @NoAdminRequired
687
-	 *
688
-	 * @param string $userId
689
-	 * @param string $groupid
690
-	 * @return DataResponse
691
-	 * @throws OCSException
692
-	 */
693
-	public function addToGroup(string $userId, string $groupid = ''): DataResponse {
694
-		if ($groupid === '') {
695
-			throw new OCSException('', 101);
696
-		}
697
-
698
-		$group = $this->groupManager->get($groupid);
699
-		$targetUser = $this->userManager->get($userId);
700
-		if ($group === null) {
701
-			throw new OCSException('', 102);
702
-		}
703
-		if ($targetUser === null) {
704
-			throw new OCSException('', 103);
705
-		}
706
-
707
-		// If they're not an admin, check they are a subadmin of the group in question
708
-		$loggedInUser = $this->userSession->getUser();
709
-		$subAdminManager = $this->groupManager->getSubAdmin();
710
-		if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
711
-			throw new OCSException('', 104);
712
-		}
713
-
714
-		// Add user to group
715
-		$group->addUser($targetUser);
716
-		return new DataResponse();
717
-	}
718
-
719
-	/**
720
-	 * @PasswordConfirmationRequired
721
-	 * @NoAdminRequired
722
-	 *
723
-	 * @param string $userId
724
-	 * @param string $groupid
725
-	 * @return DataResponse
726
-	 * @throws OCSException
727
-	 */
728
-	public function removeFromGroup(string $userId, string $groupid): DataResponse {
729
-		$loggedInUser = $this->userSession->getUser();
730
-
731
-		if ($groupid === null || trim($groupid) === '') {
732
-			throw new OCSException('', 101);
733
-		}
734
-
735
-		$group = $this->groupManager->get($groupid);
736
-		if ($group === null) {
737
-			throw new OCSException('', 102);
738
-		}
739
-
740
-		$targetUser = $this->userManager->get($userId);
741
-		if ($targetUser === null) {
742
-			throw new OCSException('', 103);
743
-		}
744
-
745
-		// If they're not an admin, check they are a subadmin of the group in question
746
-		$subAdminManager = $this->groupManager->getSubAdmin();
747
-		if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
748
-			throw new OCSException('', 104);
749
-		}
750
-
751
-		// Check they aren't removing themselves from 'admin' or their 'subadmin; group
752
-		if ($targetUser->getUID() === $loggedInUser->getUID()) {
753
-			if ($this->groupManager->isAdmin($loggedInUser->getUID())) {
754
-				if ($group->getGID() === 'admin') {
755
-					throw new OCSException('Cannot remove yourself from the admin group', 105);
756
-				}
757
-			} else {
758
-				// Not an admin, so the user must be a subadmin of this group, but that is not allowed.
759
-				throw new OCSException('Cannot remove yourself from this group as you are a SubAdmin', 105);
760
-			}
761
-
762
-		} else if (!$this->groupManager->isAdmin($loggedInUser->getUID())) {
763
-			/** @var IGroup[] $subAdminGroups */
764
-			$subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
765
-			$subAdminGroups = array_map(function (IGroup $subAdminGroup) {
766
-				return $subAdminGroup->getGID();
767
-			}, $subAdminGroups);
768
-			$userGroups = $this->groupManager->getUserGroupIds($targetUser);
769
-			$userSubAdminGroups = array_intersect($subAdminGroups, $userGroups);
770
-
771
-			if (count($userSubAdminGroups) <= 1) {
772
-				// Subadmin must not be able to remove a user from all their subadmin groups.
773
-				throw new OCSException('Cannot remove user from this group as this is the only remaining group you are a SubAdmin of', 105);
774
-			}
775
-		}
776
-
777
-		// Remove user from group
778
-		$group->removeUser($targetUser);
779
-		return new DataResponse();
780
-	}
781
-
782
-	/**
783
-	 * Creates a subadmin
784
-	 *
785
-	 * @PasswordConfirmationRequired
786
-	 *
787
-	 * @param string $userId
788
-	 * @param string $groupid
789
-	 * @return DataResponse
790
-	 * @throws OCSException
791
-	 */
792
-	public function addSubAdmin(string $userId, string $groupid): DataResponse {
793
-		$group = $this->groupManager->get($groupid);
794
-		$user = $this->userManager->get($userId);
795
-
796
-		// Check if the user exists
797
-		if ($user === null) {
798
-			throw new OCSException('User does not exist', 101);
799
-		}
800
-		// Check if group exists
801
-		if ($group === null) {
802
-			throw new OCSException('Group does not exist',  102);
803
-		}
804
-		// Check if trying to make subadmin of admin group
805
-		if ($group->getGID() === 'admin') {
806
-			throw new OCSException('Cannot create subadmins for admin group', 103);
807
-		}
808
-
809
-		$subAdminManager = $this->groupManager->getSubAdmin();
810
-
811
-		// We cannot be subadmin twice
812
-		if ($subAdminManager->isSubAdminOfGroup($user, $group)) {
813
-			return new DataResponse();
814
-		}
815
-		// Go
816
-		if ($subAdminManager->createSubAdmin($user, $group)) {
817
-			return new DataResponse();
818
-		} else {
819
-			throw new OCSException('Unknown error occurred', 103);
820
-		}
821
-	}
822
-
823
-	/**
824
-	 * Removes a subadmin from a group
825
-	 *
826
-	 * @PasswordConfirmationRequired
827
-	 *
828
-	 * @param string $userId
829
-	 * @param string $groupid
830
-	 * @return DataResponse
831
-	 * @throws OCSException
832
-	 */
833
-	public function removeSubAdmin(string $userId, string $groupid): DataResponse {
834
-		$group = $this->groupManager->get($groupid);
835
-		$user = $this->userManager->get($userId);
836
-		$subAdminManager = $this->groupManager->getSubAdmin();
837
-
838
-		// Check if the user exists
839
-		if ($user === null) {
840
-			throw new OCSException('User does not exist', 101);
841
-		}
842
-		// Check if the group exists
843
-		if ($group === null) {
844
-			throw new OCSException('Group does not exist', 101);
845
-		}
846
-		// Check if they are a subadmin of this said group
847
-		if (!$subAdminManager->isSubAdminOfGroup($user, $group)) {
848
-			throw new OCSException('User is not a subadmin of this group', 102);
849
-		}
850
-
851
-		// Go
852
-		if ($subAdminManager->deleteSubAdmin($user, $group)) {
853
-			return new DataResponse();
854
-		} else {
855
-			throw new OCSException('Unknown error occurred', 103);
856
-		}
857
-	}
858
-
859
-	/**
860
-	 * Get the groups a user is a subadmin of
861
-	 *
862
-	 * @param string $userId
863
-	 * @return DataResponse
864
-	 * @throws OCSException
865
-	 */
866
-	public function getUserSubAdminGroups(string $userId): DataResponse {
867
-		$groups = $this->getUserSubAdminGroupsData($userId);
868
-		return new DataResponse($groups);
869
-	}
870
-
871
-	/**
872
-	 * @NoAdminRequired
873
-	 * @PasswordConfirmationRequired
874
-	 *
875
-	 * resend welcome message
876
-	 *
877
-	 * @param string $userId
878
-	 * @return DataResponse
879
-	 * @throws OCSException
880
-	 */
881
-	public function resendWelcomeMessage(string $userId): DataResponse {
882
-		$currentLoggedInUser = $this->userSession->getUser();
883
-
884
-		$targetUser = $this->userManager->get($userId);
885
-		if ($targetUser === null) {
886
-			throw new OCSException('', \OCP\API::RESPOND_NOT_FOUND);
887
-		}
888
-
889
-		// Check if admin / subadmin
890
-		$subAdminManager = $this->groupManager->getSubAdmin();
891
-		if (!$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
892
-			&& !$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
893
-			// No rights
894
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
895
-		}
896
-
897
-		$email = $targetUser->getEMailAddress();
898
-		if ($email === '' || $email === null) {
899
-			throw new OCSException('Email address not available', 101);
900
-		}
901
-		$username = $targetUser->getUID();
902
-		$lang = $this->config->getUserValue($username, 'core', 'lang', 'en');
903
-		if (!$this->l10nFactory->languageExists('settings', $lang)) {
904
-			$lang = 'en';
905
-		}
906
-
907
-		$l10n = $this->l10nFactory->get('settings', $lang);
908
-
909
-		try {
910
-			$this->newUserMailHelper->setL10N($l10n);
911
-			$emailTemplate = $this->newUserMailHelper->generateTemplate($targetUser, false);
912
-			$this->newUserMailHelper->sendMail($targetUser, $emailTemplate);
913
-		} catch(\Exception $e) {
914
-			$this->logger->logException($e, [
915
-				'message' => "Can't send new user mail to $email",
916
-				'level' => ILogger::ERROR,
917
-				'app' => 'settings',
918
-			]);
919
-			throw new OCSException('Sending email failed', 102);
920
-		}
921
-
922
-		return new DataResponse();
923
-	}
56
+    /** @var IAppManager */
57
+    private $appManager;
58
+    /** @var ILogger */
59
+    private $logger;
60
+    /** @var IFactory */
61
+    private $l10nFactory;
62
+    /** @var NewUserMailHelper */
63
+    private $newUserMailHelper;
64
+    /** @var FederatedFileSharingFactory */
65
+    private $federatedFileSharingFactory;
66
+    /** @var ISecureRandom */
67
+    private $secureRandom;
68
+
69
+    /**
70
+     * @param string $appName
71
+     * @param IRequest $request
72
+     * @param IUserManager $userManager
73
+     * @param IConfig $config
74
+     * @param IAppManager $appManager
75
+     * @param IGroupManager $groupManager
76
+     * @param IUserSession $userSession
77
+     * @param AccountManager $accountManager
78
+     * @param ILogger $logger
79
+     * @param IFactory $l10nFactory
80
+     * @param NewUserMailHelper $newUserMailHelper
81
+     * @param FederatedFileSharingFactory $federatedFileSharingFactory
82
+     * @param ISecureRandom $secureRandom
83
+     */
84
+    public function __construct(string $appName,
85
+                                IRequest $request,
86
+                                IUserManager $userManager,
87
+                                IConfig $config,
88
+                                IAppManager $appManager,
89
+                                IGroupManager $groupManager,
90
+                                IUserSession $userSession,
91
+                                AccountManager $accountManager,
92
+                                ILogger $logger,
93
+                                IFactory $l10nFactory,
94
+                                NewUserMailHelper $newUserMailHelper,
95
+                                FederatedFileSharingFactory $federatedFileSharingFactory,
96
+                                ISecureRandom $secureRandom) {
97
+        parent::__construct($appName,
98
+                            $request,
99
+                            $userManager,
100
+                            $config,
101
+                            $groupManager,
102
+                            $userSession,
103
+                            $accountManager);
104
+
105
+        $this->appManager = $appManager;
106
+        $this->logger = $logger;
107
+        $this->l10nFactory = $l10nFactory;
108
+        $this->newUserMailHelper = $newUserMailHelper;
109
+        $this->federatedFileSharingFactory = $federatedFileSharingFactory;
110
+        $this->secureRandom = $secureRandom;
111
+    }
112
+
113
+    /**
114
+     * @NoAdminRequired
115
+     *
116
+     * returns a list of users
117
+     *
118
+     * @param string $search
119
+     * @param int $limit
120
+     * @param int $offset
121
+     * @return DataResponse
122
+     */
123
+    public function getUsers(string $search = '', $limit = null, $offset = 0): DataResponse {
124
+        $user = $this->userSession->getUser();
125
+        $users = [];
126
+
127
+        // Admin? Or SubAdmin?
128
+        $uid = $user->getUID();
129
+        $subAdminManager = $this->groupManager->getSubAdmin();
130
+        if ($this->groupManager->isAdmin($uid)){
131
+            $users = $this->userManager->search($search, $limit, $offset);
132
+        } else if ($subAdminManager->isSubAdmin($user)) {
133
+            $subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
134
+            foreach ($subAdminOfGroups as $key => $group) {
135
+                $subAdminOfGroups[$key] = $group->getGID();
136
+            }
137
+
138
+            $users = [];
139
+            foreach ($subAdminOfGroups as $group) {
140
+                $users = array_merge($users, $this->groupManager->displayNamesInGroup($group, $search, $limit, $offset));
141
+            }
142
+        }
143
+
144
+        $users = array_keys($users);
145
+
146
+        return new DataResponse([
147
+            'users' => $users
148
+        ]);
149
+    }
150
+
151
+    /**
152
+     * @NoAdminRequired
153
+     *
154
+     * returns a list of users and their data
155
+     */
156
+    public function getUsersDetails(string $search = '', $limit = null, $offset = 0): DataResponse {
157
+        $user = $this->userSession->getUser();
158
+        $users = [];
159
+
160
+        // Admin? Or SubAdmin?
161
+        $uid = $user->getUID();
162
+        $subAdminManager = $this->groupManager->getSubAdmin();
163
+        if ($this->groupManager->isAdmin($uid)){
164
+            $users = $this->userManager->search($search, $limit, $offset);
165
+        } else if ($subAdminManager->isSubAdmin($user)) {
166
+            $subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
167
+            foreach ($subAdminOfGroups as $key => $group) {
168
+                $subAdminOfGroups[$key] = $group->getGID();
169
+            }
170
+
171
+            $users = [];
172
+            foreach ($subAdminOfGroups as $group) {
173
+                $users = array_merge($users, $this->groupManager->displayNamesInGroup($group, $search, $limit, $offset));
174
+            }
175
+        }
176
+
177
+        $users = array_keys($users);
178
+        $usersDetails = [];
179
+        foreach ($users as $key => $userId) {
180
+            $userData = $this->getUserData($userId);
181
+            // Do not insert empty entry
182
+            if (!empty($userData)) {
183
+                $usersDetails[$userId] = $userData;
184
+            } else {
185
+                // Logged user does not have permissions to see this user
186
+                // only showing its id
187
+                $usersDetails[$userId] = ['id' => $userId];
188
+            }
189
+        }
190
+
191
+        return new DataResponse([
192
+            'users' => $usersDetails
193
+        ]);
194
+    }
195
+
196
+    /**
197
+     * @PasswordConfirmationRequired
198
+     * @NoAdminRequired
199
+     *
200
+     * @param string $userid
201
+     * @param string $password
202
+     * @param string $email
203
+     * @param array $groups
204
+     * @param array $subadmins
205
+     * @param string $quota
206
+     * @param string $language
207
+     * @return DataResponse
208
+     * @throws OCSException
209
+     */
210
+    public function addUser(string $userid,
211
+                            string $password = '',
212
+                            string $email = '',
213
+                            array $groups = [],
214
+                            array $subadmin = [],
215
+                            string $quota = '',
216
+                            string $language = ''): DataResponse {
217
+        $user = $this->userSession->getUser();
218
+        $isAdmin = $this->groupManager->isAdmin($user->getUID());
219
+        $subAdminManager = $this->groupManager->getSubAdmin();
220
+
221
+        if ($this->userManager->userExists($userid)) {
222
+            $this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
223
+            throw new OCSException('User already exists', 102);
224
+        }
225
+
226
+        if ($groups !== []) {
227
+            foreach ($groups as $group) {
228
+                if (!$this->groupManager->groupExists($group)) {
229
+                    throw new OCSException('group '.$group.' does not exist', 104);
230
+                }
231
+                if (!$isAdmin && !$subAdminManager->isSubAdminOfGroup($user, $this->groupManager->get($group))) {
232
+                    throw new OCSException('insufficient privileges for group '. $group, 105);
233
+                }
234
+            }
235
+        } else {
236
+            if (!$isAdmin) {
237
+                throw new OCSException('no group specified (required for subadmins)', 106);
238
+            }
239
+        }
240
+
241
+        $subadminGroups = [];
242
+        if ($subadmin !== []) {
243
+            foreach ($subadmin as $groupid) {
244
+                $group = $this->groupManager->get($groupid);
245
+                // Check if group exists
246
+                if ($group === null) {
247
+                    throw new OCSException('Subadmin group does not exist',  102);
248
+                }
249
+                // Check if trying to make subadmin of admin group
250
+                if ($group->getGID() === 'admin') {
251
+                    throw new OCSException('Cannot create subadmins for admin group', 103);
252
+                }
253
+                // Check if has permission to promote subadmins
254
+                if (!$subAdminManager->isSubAdminOfGroup($user, $group) && !$isAdmin) {
255
+                    throw new OCSForbiddenException('No permissions to promote subadmins');
256
+                }
257
+                $subadminGroups[] = $group;
258
+            }
259
+        }
260
+
261
+        $generatePasswordResetToken = false;
262
+        if ($password === '') {
263
+            if ($email === '') {
264
+                throw new OCSException('To send a password link to the user an email address is required.', 108);
265
+            }
266
+
267
+            $password = $this->secureRandom->generate(10);
268
+            // Make sure we pass the password_policy
269
+            $password .= $this->secureRandom->generate(2, '$!.,;:-~+*[]{}()');
270
+            $generatePasswordResetToken = true;
271
+        }
272
+
273
+        try {
274
+            $newUser = $this->userManager->createUser($userid, $password);
275
+            $this->logger->info('Successful addUser call with userid: ' . $userid, ['app' => 'ocs_api']);
276
+
277
+            foreach ($groups as $group) {
278
+                $this->groupManager->get($group)->addUser($newUser);
279
+                $this->logger->info('Added userid ' . $userid . ' to group ' . $group, ['app' => 'ocs_api']);
280
+            }
281
+            foreach ($subadminGroups as $group) {
282
+                $subAdminManager->createSubAdmin($newUser, $group);
283
+            }
284
+
285
+            if ($quota !== '') {
286
+                $this->editUser($userid, 'quota', $quota);
287
+            }
288
+
289
+            if ($language !== '') {
290
+                $this->editUser($userid, 'language', $language);
291
+            }
292
+
293
+            // Send new user mail only if a mail is set
294
+            if ($email !== '') {
295
+                $newUser->setEMailAddress($email);
296
+                try {
297
+                    $emailTemplate = $this->newUserMailHelper->generateTemplate($newUser, $generatePasswordResetToken);
298
+                    $this->newUserMailHelper->sendMail($newUser, $emailTemplate);
299
+                } catch (\Exception $e) {
300
+                    $this->logger->logException($e, [
301
+                        'message' => "Can't send new user mail to $email",
302
+                        'level' => ILogger::ERROR,
303
+                        'app' => 'ocs_api',
304
+                    ]);
305
+                    throw new OCSException('Unable to send the invitation mail', 109);
306
+                }
307
+            }
308
+
309
+            return new DataResponse();
310
+
311
+        } catch (HintException $e ) {
312
+            $this->logger->logException($e, [
313
+                'message' => 'Failed addUser attempt with hint exception.',
314
+                'level' => ILogger::WARN,
315
+                'app' => 'ocs_api',
316
+            ]);
317
+            throw new OCSException($e->getHint(), 107);
318
+        } catch (\Exception $e) {
319
+            $this->logger->logException($e, [
320
+                'message' => 'Failed addUser attempt with exception.',
321
+                'level' => ILogger::ERROR,
322
+                'app' => 'ocs_api',
323
+            ]);
324
+            throw new OCSException('Bad request', 101);
325
+        }
326
+    }
327
+
328
+    /**
329
+     * @NoAdminRequired
330
+     * @NoSubAdminRequired
331
+     *
332
+     * gets user info
333
+     *
334
+     * @param string $userId
335
+     * @return DataResponse
336
+     * @throws OCSException
337
+     */
338
+    public function getUser(string $userId): DataResponse {
339
+        $data = $this->getUserData($userId);
340
+        // getUserData returns empty array if not enough permissions
341
+        if (empty($data)) {
342
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
343
+        }
344
+        return new DataResponse($data);
345
+    }
346
+
347
+    /**
348
+     * @NoAdminRequired
349
+     * @NoSubAdminRequired
350
+     *
351
+     * gets user info from the currently logged in user
352
+     *
353
+     * @return DataResponse
354
+     * @throws OCSException
355
+     */
356
+    public function getCurrentUser(): DataResponse {
357
+        $user = $this->userSession->getUser();
358
+        if ($user) {
359
+            $data =  $this->getUserData($user->getUID());
360
+            // rename "displayname" to "display-name" only for this call to keep
361
+            // the API stable.
362
+            $data['display-name'] = $data['displayname'];
363
+            unset($data['displayname']);
364
+            return new DataResponse($data);
365
+
366
+        }
367
+
368
+        throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
369
+    }
370
+
371
+    /**
372
+     * @NoAdminRequired
373
+     * @NoSubAdminRequired
374
+     */
375
+    public function getEditableFields(): DataResponse {
376
+        $permittedFields = [];
377
+
378
+        // Editing self (display, email)
379
+        if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
380
+            $permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
381
+            $permittedFields[] = AccountManager::PROPERTY_EMAIL;
382
+        }
383
+
384
+        if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
385
+            $federatedFileSharing = $this->federatedFileSharingFactory->get();
386
+            $shareProvider = $federatedFileSharing->getFederatedShareProvider();
387
+            if ($shareProvider->isLookupServerUploadEnabled()) {
388
+                $permittedFields[] = AccountManager::PROPERTY_PHONE;
389
+                $permittedFields[] = AccountManager::PROPERTY_ADDRESS;
390
+                $permittedFields[] = AccountManager::PROPERTY_WEBSITE;
391
+                $permittedFields[] = AccountManager::PROPERTY_TWITTER;
392
+            }
393
+        }
394
+
395
+        // Find the data
396
+        $data['id'] = $targetUserObject->getUID();
397
+        $data['quota'] = $this->fillStorageInfo($targetUserObject->getUID());
398
+        $data[AccountManager::PROPERTY_EMAIL] = $targetUserObject->getEMailAddress();
399
+        $data[AccountManager::PROPERTY_DISPLAYNAME] = $targetUserObject->getDisplayName();
400
+        $data[AccountManager::PROPERTY_PHONE] = $userAccount[AccountManager::PROPERTY_PHONE]['value'];
401
+        $data[AccountManager::PROPERTY_ADDRESS] = $userAccount[AccountManager::PROPERTY_ADDRESS]['value'];
402
+        $data[AccountManager::PROPERTY_WEBSITE] = $userAccount[AccountManager::PROPERTY_WEBSITE]['value'];
403
+        $data[AccountManager::PROPERTY_TWITTER] = $userAccount[AccountManager::PROPERTY_TWITTER]['value'];
404
+        $data['groups'] = $gids;
405
+        $data['language'] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'lang');
406
+        $data['locale'] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'locale');
407
+
408
+        return new DataResponse($permittedFields);
409
+    }
410
+
411
+    /**
412
+     * @NoAdminRequired
413
+     * @NoSubAdminRequired
414
+     * @PasswordConfirmationRequired
415
+     *
416
+     * edit users
417
+     *
418
+     * @param string $userId
419
+     * @param string $key
420
+     * @param string $value
421
+     * @return DataResponse
422
+     * @throws OCSException
423
+     */
424
+    public function editUser(string $userId, string $key, string $value): DataResponse {
425
+        $currentLoggedInUser = $this->userSession->getUser();
426
+
427
+        $targetUser = $this->userManager->get($userId);
428
+        if ($targetUser === null) {
429
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
430
+        }
431
+
432
+        $permittedFields = [];
433
+        if ($targetUser->getUID() === $currentLoggedInUser->getUID()) {
434
+            // Editing self (display, email)
435
+            if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
436
+                $permittedFields[] = 'display';
437
+                $permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
438
+                $permittedFields[] = AccountManager::PROPERTY_EMAIL;
439
+            }
440
+
441
+            $permittedFields[] = 'password';
442
+            if ($this->config->getSystemValue('force_language', false) === false ||
443
+                $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
444
+                $permittedFields[] = 'language';
445
+            }
446
+
447
+            if ($this->config->getSystemValue('force_locale', false) === false ||
448
+                $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
449
+                $permittedFields[] = 'locale';
450
+            }
451
+
452
+            if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
453
+                $federatedFileSharing = new \OCA\FederatedFileSharing\AppInfo\Application();
454
+                $shareProvider = $federatedFileSharing->getFederatedShareProvider();
455
+                if ($shareProvider->isLookupServerUploadEnabled()) {
456
+                    $permittedFields[] = AccountManager::PROPERTY_PHONE;
457
+                    $permittedFields[] = AccountManager::PROPERTY_ADDRESS;
458
+                    $permittedFields[] = AccountManager::PROPERTY_WEBSITE;
459
+                    $permittedFields[] = AccountManager::PROPERTY_TWITTER;
460
+                }
461
+            }
462
+
463
+            // If admin they can edit their own quota
464
+            if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
465
+                $permittedFields[] = 'quota';
466
+            }
467
+        } else {
468
+            // Check if admin / subadmin
469
+            $subAdminManager = $this->groupManager->getSubAdmin();
470
+            if ($subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
471
+            || $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
472
+                // They have permissions over the user
473
+                $permittedFields[] = 'display';
474
+                $permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
475
+                $permittedFields[] = AccountManager::PROPERTY_EMAIL;
476
+                $permittedFields[] = 'password';
477
+                $permittedFields[] = 'language';
478
+                $permittedFields[] = 'locale';
479
+                $permittedFields[] = AccountManager::PROPERTY_PHONE;
480
+                $permittedFields[] = AccountManager::PROPERTY_ADDRESS;
481
+                $permittedFields[] = AccountManager::PROPERTY_WEBSITE;
482
+                $permittedFields[] = AccountManager::PROPERTY_TWITTER;
483
+                $permittedFields[] = 'quota';
484
+            } else {
485
+                // No rights
486
+                throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
487
+            }
488
+        }
489
+        // Check if permitted to edit this field
490
+        if (!in_array($key, $permittedFields)) {
491
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
492
+        }
493
+        // Process the edit
494
+        switch($key) {
495
+            case 'display':
496
+            case AccountManager::PROPERTY_DISPLAYNAME:
497
+                $targetUser->setDisplayName($value);
498
+                break;
499
+            case 'quota':
500
+                $quota = $value;
501
+                if ($quota !== 'none' && $quota !== 'default') {
502
+                    if (is_numeric($quota)) {
503
+                        $quota = (float) $quota;
504
+                    } else {
505
+                        $quota = \OCP\Util::computerFileSize($quota);
506
+                    }
507
+                    if ($quota === false) {
508
+                        throw new OCSException('Invalid quota value '.$value, 103);
509
+                    }
510
+                    if ($quota === -1) {
511
+                        $quota = 'none';
512
+                    } else {
513
+                        $quota = \OCP\Util::humanFileSize($quota);
514
+                    }
515
+                }
516
+                $targetUser->setQuota($quota);
517
+                break;
518
+            case 'password':
519
+                $targetUser->setPassword($value);
520
+                break;
521
+            case 'language':
522
+                $languagesCodes = $this->l10nFactory->findAvailableLanguages();
523
+                if (!in_array($value, $languagesCodes, true) && $value !== 'en') {
524
+                    throw new OCSException('Invalid language', 102);
525
+                }
526
+                $this->config->setUserValue($targetUser->getUID(), 'core', 'lang', $value);
527
+                break;
528
+            case 'locale':
529
+                if (!$this->l10nFactory->localeExists($value)) {
530
+                    throw new OCSException('Invalid locale', 102);
531
+                }
532
+                $this->config->setUserValue($targetUser->getUID(), 'core', 'locale', $value);
533
+                break;
534
+            case AccountManager::PROPERTY_EMAIL:
535
+                if (filter_var($value, FILTER_VALIDATE_EMAIL) || $value === '') {
536
+                    $targetUser->setEMailAddress($value);
537
+                } else {
538
+                    throw new OCSException('', 102);
539
+                }
540
+                break;
541
+            case AccountManager::PROPERTY_PHONE:
542
+            case AccountManager::PROPERTY_ADDRESS:
543
+            case AccountManager::PROPERTY_WEBSITE:
544
+            case AccountManager::PROPERTY_TWITTER:
545
+                $userAccount = $this->accountManager->getUser($targetUser);
546
+                if ($userAccount[$key]['value'] !== $value) {
547
+                    $userAccount[$key]['value'] = $value;
548
+                    $this->accountManager->updateUser($targetUser, $userAccount);
549
+                }
550
+                break;
551
+            default:
552
+                throw new OCSException('', 103);
553
+        }
554
+        return new DataResponse();
555
+    }
556
+
557
+    /**
558
+     * @PasswordConfirmationRequired
559
+     * @NoAdminRequired
560
+     *
561
+     * @param string $userId
562
+     * @return DataResponse
563
+     * @throws OCSException
564
+     */
565
+    public function deleteUser(string $userId): DataResponse {
566
+        $currentLoggedInUser = $this->userSession->getUser();
567
+
568
+        $targetUser = $this->userManager->get($userId);
569
+
570
+        if ($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
571
+            throw new OCSException('', 101);
572
+        }
573
+
574
+        // If not permitted
575
+        $subAdminManager = $this->groupManager->getSubAdmin();
576
+        if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
577
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
578
+        }
579
+
580
+        // Go ahead with the delete
581
+        if ($targetUser->delete()) {
582
+            return new DataResponse();
583
+        } else {
584
+            throw new OCSException('', 101);
585
+        }
586
+    }
587
+
588
+    /**
589
+     * @PasswordConfirmationRequired
590
+     * @NoAdminRequired
591
+     *
592
+     * @param string $userId
593
+     * @return DataResponse
594
+     * @throws OCSException
595
+     * @throws OCSForbiddenException
596
+     */
597
+    public function disableUser(string $userId): DataResponse {
598
+        return $this->setEnabled($userId, false);
599
+    }
600
+
601
+    /**
602
+     * @PasswordConfirmationRequired
603
+     * @NoAdminRequired
604
+     *
605
+     * @param string $userId
606
+     * @return DataResponse
607
+     * @throws OCSException
608
+     * @throws OCSForbiddenException
609
+     */
610
+    public function enableUser(string $userId): DataResponse {
611
+        return $this->setEnabled($userId, true);
612
+    }
613
+
614
+    /**
615
+     * @param string $userId
616
+     * @param bool $value
617
+     * @return DataResponse
618
+     * @throws OCSException
619
+     */
620
+    private function setEnabled(string $userId, bool $value): DataResponse {
621
+        $currentLoggedInUser = $this->userSession->getUser();
622
+
623
+        $targetUser = $this->userManager->get($userId);
624
+        if ($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
625
+            throw new OCSException('', 101);
626
+        }
627
+
628
+        // If not permitted
629
+        $subAdminManager = $this->groupManager->getSubAdmin();
630
+        if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
631
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
632
+        }
633
+
634
+        // enable/disable the user now
635
+        $targetUser->setEnabled($value);
636
+        return new DataResponse();
637
+    }
638
+
639
+    /**
640
+     * @NoAdminRequired
641
+     * @NoSubAdminRequired
642
+     *
643
+     * @param string $userId
644
+     * @return DataResponse
645
+     * @throws OCSException
646
+     */
647
+    public function getUsersGroups(string $userId): DataResponse {
648
+        $loggedInUser = $this->userSession->getUser();
649
+
650
+        $targetUser = $this->userManager->get($userId);
651
+        if ($targetUser === null) {
652
+            throw new OCSException('', \OCP\API::RESPOND_NOT_FOUND);
653
+        }
654
+
655
+        if ($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) {
656
+            // Self lookup or admin lookup
657
+            return new DataResponse([
658
+                'groups' => $this->groupManager->getUserGroupIds($targetUser)
659
+            ]);
660
+        } else {
661
+            $subAdminManager = $this->groupManager->getSubAdmin();
662
+
663
+            // Looking up someone else
664
+            if ($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) {
665
+                // Return the group that the method caller is subadmin of for the user in question
666
+                /** @var IGroup[] $getSubAdminsGroups */
667
+                $getSubAdminsGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
668
+                foreach ($getSubAdminsGroups as $key => $group) {
669
+                    $getSubAdminsGroups[$key] = $group->getGID();
670
+                }
671
+                $groups = array_intersect(
672
+                    $getSubAdminsGroups,
673
+                    $this->groupManager->getUserGroupIds($targetUser)
674
+                );
675
+                return new DataResponse(['groups' => $groups]);
676
+            } else {
677
+                // Not permitted
678
+                throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
679
+            }
680
+        }
681
+
682
+    }
683
+
684
+    /**
685
+     * @PasswordConfirmationRequired
686
+     * @NoAdminRequired
687
+     *
688
+     * @param string $userId
689
+     * @param string $groupid
690
+     * @return DataResponse
691
+     * @throws OCSException
692
+     */
693
+    public function addToGroup(string $userId, string $groupid = ''): DataResponse {
694
+        if ($groupid === '') {
695
+            throw new OCSException('', 101);
696
+        }
697
+
698
+        $group = $this->groupManager->get($groupid);
699
+        $targetUser = $this->userManager->get($userId);
700
+        if ($group === null) {
701
+            throw new OCSException('', 102);
702
+        }
703
+        if ($targetUser === null) {
704
+            throw new OCSException('', 103);
705
+        }
706
+
707
+        // If they're not an admin, check they are a subadmin of the group in question
708
+        $loggedInUser = $this->userSession->getUser();
709
+        $subAdminManager = $this->groupManager->getSubAdmin();
710
+        if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
711
+            throw new OCSException('', 104);
712
+        }
713
+
714
+        // Add user to group
715
+        $group->addUser($targetUser);
716
+        return new DataResponse();
717
+    }
718
+
719
+    /**
720
+     * @PasswordConfirmationRequired
721
+     * @NoAdminRequired
722
+     *
723
+     * @param string $userId
724
+     * @param string $groupid
725
+     * @return DataResponse
726
+     * @throws OCSException
727
+     */
728
+    public function removeFromGroup(string $userId, string $groupid): DataResponse {
729
+        $loggedInUser = $this->userSession->getUser();
730
+
731
+        if ($groupid === null || trim($groupid) === '') {
732
+            throw new OCSException('', 101);
733
+        }
734
+
735
+        $group = $this->groupManager->get($groupid);
736
+        if ($group === null) {
737
+            throw new OCSException('', 102);
738
+        }
739
+
740
+        $targetUser = $this->userManager->get($userId);
741
+        if ($targetUser === null) {
742
+            throw new OCSException('', 103);
743
+        }
744
+
745
+        // If they're not an admin, check they are a subadmin of the group in question
746
+        $subAdminManager = $this->groupManager->getSubAdmin();
747
+        if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
748
+            throw new OCSException('', 104);
749
+        }
750
+
751
+        // Check they aren't removing themselves from 'admin' or their 'subadmin; group
752
+        if ($targetUser->getUID() === $loggedInUser->getUID()) {
753
+            if ($this->groupManager->isAdmin($loggedInUser->getUID())) {
754
+                if ($group->getGID() === 'admin') {
755
+                    throw new OCSException('Cannot remove yourself from the admin group', 105);
756
+                }
757
+            } else {
758
+                // Not an admin, so the user must be a subadmin of this group, but that is not allowed.
759
+                throw new OCSException('Cannot remove yourself from this group as you are a SubAdmin', 105);
760
+            }
761
+
762
+        } else if (!$this->groupManager->isAdmin($loggedInUser->getUID())) {
763
+            /** @var IGroup[] $subAdminGroups */
764
+            $subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
765
+            $subAdminGroups = array_map(function (IGroup $subAdminGroup) {
766
+                return $subAdminGroup->getGID();
767
+            }, $subAdminGroups);
768
+            $userGroups = $this->groupManager->getUserGroupIds($targetUser);
769
+            $userSubAdminGroups = array_intersect($subAdminGroups, $userGroups);
770
+
771
+            if (count($userSubAdminGroups) <= 1) {
772
+                // Subadmin must not be able to remove a user from all their subadmin groups.
773
+                throw new OCSException('Cannot remove user from this group as this is the only remaining group you are a SubAdmin of', 105);
774
+            }
775
+        }
776
+
777
+        // Remove user from group
778
+        $group->removeUser($targetUser);
779
+        return new DataResponse();
780
+    }
781
+
782
+    /**
783
+     * Creates a subadmin
784
+     *
785
+     * @PasswordConfirmationRequired
786
+     *
787
+     * @param string $userId
788
+     * @param string $groupid
789
+     * @return DataResponse
790
+     * @throws OCSException
791
+     */
792
+    public function addSubAdmin(string $userId, string $groupid): DataResponse {
793
+        $group = $this->groupManager->get($groupid);
794
+        $user = $this->userManager->get($userId);
795
+
796
+        // Check if the user exists
797
+        if ($user === null) {
798
+            throw new OCSException('User does not exist', 101);
799
+        }
800
+        // Check if group exists
801
+        if ($group === null) {
802
+            throw new OCSException('Group does not exist',  102);
803
+        }
804
+        // Check if trying to make subadmin of admin group
805
+        if ($group->getGID() === 'admin') {
806
+            throw new OCSException('Cannot create subadmins for admin group', 103);
807
+        }
808
+
809
+        $subAdminManager = $this->groupManager->getSubAdmin();
810
+
811
+        // We cannot be subadmin twice
812
+        if ($subAdminManager->isSubAdminOfGroup($user, $group)) {
813
+            return new DataResponse();
814
+        }
815
+        // Go
816
+        if ($subAdminManager->createSubAdmin($user, $group)) {
817
+            return new DataResponse();
818
+        } else {
819
+            throw new OCSException('Unknown error occurred', 103);
820
+        }
821
+    }
822
+
823
+    /**
824
+     * Removes a subadmin from a group
825
+     *
826
+     * @PasswordConfirmationRequired
827
+     *
828
+     * @param string $userId
829
+     * @param string $groupid
830
+     * @return DataResponse
831
+     * @throws OCSException
832
+     */
833
+    public function removeSubAdmin(string $userId, string $groupid): DataResponse {
834
+        $group = $this->groupManager->get($groupid);
835
+        $user = $this->userManager->get($userId);
836
+        $subAdminManager = $this->groupManager->getSubAdmin();
837
+
838
+        // Check if the user exists
839
+        if ($user === null) {
840
+            throw new OCSException('User does not exist', 101);
841
+        }
842
+        // Check if the group exists
843
+        if ($group === null) {
844
+            throw new OCSException('Group does not exist', 101);
845
+        }
846
+        // Check if they are a subadmin of this said group
847
+        if (!$subAdminManager->isSubAdminOfGroup($user, $group)) {
848
+            throw new OCSException('User is not a subadmin of this group', 102);
849
+        }
850
+
851
+        // Go
852
+        if ($subAdminManager->deleteSubAdmin($user, $group)) {
853
+            return new DataResponse();
854
+        } else {
855
+            throw new OCSException('Unknown error occurred', 103);
856
+        }
857
+    }
858
+
859
+    /**
860
+     * Get the groups a user is a subadmin of
861
+     *
862
+     * @param string $userId
863
+     * @return DataResponse
864
+     * @throws OCSException
865
+     */
866
+    public function getUserSubAdminGroups(string $userId): DataResponse {
867
+        $groups = $this->getUserSubAdminGroupsData($userId);
868
+        return new DataResponse($groups);
869
+    }
870
+
871
+    /**
872
+     * @NoAdminRequired
873
+     * @PasswordConfirmationRequired
874
+     *
875
+     * resend welcome message
876
+     *
877
+     * @param string $userId
878
+     * @return DataResponse
879
+     * @throws OCSException
880
+     */
881
+    public function resendWelcomeMessage(string $userId): DataResponse {
882
+        $currentLoggedInUser = $this->userSession->getUser();
883
+
884
+        $targetUser = $this->userManager->get($userId);
885
+        if ($targetUser === null) {
886
+            throw new OCSException('', \OCP\API::RESPOND_NOT_FOUND);
887
+        }
888
+
889
+        // Check if admin / subadmin
890
+        $subAdminManager = $this->groupManager->getSubAdmin();
891
+        if (!$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
892
+            && !$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
893
+            // No rights
894
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
895
+        }
896
+
897
+        $email = $targetUser->getEMailAddress();
898
+        if ($email === '' || $email === null) {
899
+            throw new OCSException('Email address not available', 101);
900
+        }
901
+        $username = $targetUser->getUID();
902
+        $lang = $this->config->getUserValue($username, 'core', 'lang', 'en');
903
+        if (!$this->l10nFactory->languageExists('settings', $lang)) {
904
+            $lang = 'en';
905
+        }
906
+
907
+        $l10n = $this->l10nFactory->get('settings', $lang);
908
+
909
+        try {
910
+            $this->newUserMailHelper->setL10N($l10n);
911
+            $emailTemplate = $this->newUserMailHelper->generateTemplate($targetUser, false);
912
+            $this->newUserMailHelper->sendMail($targetUser, $emailTemplate);
913
+        } catch(\Exception $e) {
914
+            $this->logger->logException($e, [
915
+                'message' => "Can't send new user mail to $email",
916
+                'level' => ILogger::ERROR,
917
+                'app' => 'settings',
918
+            ]);
919
+            throw new OCSException('Sending email failed', 102);
920
+        }
921
+
922
+        return new DataResponse();
923
+    }
924 924
 }
Please login to merge, or discard this patch.