Passed
Push — master ( ee183e...381eb0 )
by Maxence
25:19 queued 11:12
created
lib/private/User/User.php 2 patches
Indentation   +523 added lines, -523 removed lines patch added patch discarded remove patch
@@ -61,527 +61,527 @@
 block discarded – undo
61 61
 use Symfony\Component\EventDispatcher\GenericEvent;
62 62
 
63 63
 class User implements IUser {
64
-	/** @var IAccountManager */
65
-	protected $accountManager;
66
-	/** @var string */
67
-	private $uid;
68
-
69
-	/** @var string|null */
70
-	private $displayName;
71
-
72
-	/** @var UserInterface|null */
73
-	private $backend;
74
-	/** @var EventDispatcherInterface */
75
-	private $legacyDispatcher;
76
-
77
-	/** @var IEventDispatcher */
78
-	private $dispatcher;
79
-
80
-	/** @var bool|null */
81
-	private $enabled;
82
-
83
-	/** @var Emitter|Manager */
84
-	private $emitter;
85
-
86
-	/** @var string */
87
-	private $home;
88
-
89
-	/** @var int|null */
90
-	private $lastLogin;
91
-
92
-	/** @var \OCP\IConfig */
93
-	private $config;
94
-
95
-	/** @var IAvatarManager */
96
-	private $avatarManager;
97
-
98
-	/** @var IURLGenerator */
99
-	private $urlGenerator;
100
-
101
-	public function __construct(string $uid, ?UserInterface $backend, EventDispatcherInterface $dispatcher, $emitter = null, IConfig $config = null, $urlGenerator = null) {
102
-		$this->uid = $uid;
103
-		$this->backend = $backend;
104
-		$this->legacyDispatcher = $dispatcher;
105
-		$this->emitter = $emitter;
106
-		if (is_null($config)) {
107
-			$config = \OC::$server->getConfig();
108
-		}
109
-		$this->config = $config;
110
-		$this->urlGenerator = $urlGenerator;
111
-		if (is_null($this->urlGenerator)) {
112
-			$this->urlGenerator = \OC::$server->getURLGenerator();
113
-		}
114
-		// TODO: inject
115
-		$this->dispatcher = \OC::$server->query(IEventDispatcher::class);
116
-	}
117
-
118
-	/**
119
-	 * get the user id
120
-	 *
121
-	 * @return string
122
-	 */
123
-	public function getUID() {
124
-		return $this->uid;
125
-	}
126
-
127
-	/**
128
-	 * get the display name for the user, if no specific display name is set it will fallback to the user id
129
-	 *
130
-	 * @return string
131
-	 */
132
-	public function getDisplayName() {
133
-		if ($this->displayName === null) {
134
-			$displayName = '';
135
-			if ($this->backend && $this->backend->implementsActions(Backend::GET_DISPLAYNAME)) {
136
-				// get display name and strip whitespace from the beginning and end of it
137
-				$backendDisplayName = $this->backend->getDisplayName($this->uid);
138
-				if (is_string($backendDisplayName)) {
139
-					$displayName = trim($backendDisplayName);
140
-				}
141
-			}
142
-
143
-			if (!empty($displayName)) {
144
-				$this->displayName = $displayName;
145
-			} else {
146
-				$this->displayName = $this->uid;
147
-			}
148
-		}
149
-		return $this->displayName;
150
-	}
151
-
152
-	/**
153
-	 * set the displayname for the user
154
-	 *
155
-	 * @param string $displayName
156
-	 * @return bool
157
-	 *
158
-	 * @since 25.0.0 Throw InvalidArgumentException
159
-	 * @throws \InvalidArgumentException
160
-	 */
161
-	public function setDisplayName($displayName) {
162
-		$displayName = trim($displayName);
163
-		$oldDisplayName = $this->getDisplayName();
164
-		if ($this->backend->implementsActions(Backend::SET_DISPLAYNAME) && !empty($displayName) && $displayName !== $oldDisplayName) {
165
-			/** @var ISetDisplayNameBackend $backend */
166
-			$backend = $this->backend;
167
-			$result = $backend->setDisplayName($this->uid, $displayName);
168
-			if ($result) {
169
-				$this->displayName = $displayName;
170
-				$this->triggerChange('displayName', $displayName, $oldDisplayName);
171
-			}
172
-			return $result !== false;
173
-		}
174
-		return false;
175
-	}
176
-
177
-	/**
178
-	 * @inheritDoc
179
-	 */
180
-	public function setEMailAddress($mailAddress) {
181
-		$this->setSystemEMailAddress($mailAddress);
182
-	}
183
-
184
-	/**
185
-	 * @inheritDoc
186
-	 */
187
-	public function setSystemEMailAddress(string $mailAddress): void {
188
-		$oldMailAddress = $this->getSystemEMailAddress();
189
-
190
-		if ($mailAddress === '') {
191
-			$this->config->deleteUserValue($this->uid, 'settings', 'email');
192
-		} else {
193
-			$this->config->setUserValue($this->uid, 'settings', 'email', $mailAddress);
194
-		}
195
-
196
-		$primaryAddress = $this->getPrimaryEMailAddress();
197
-		if ($primaryAddress === $mailAddress) {
198
-			// on match no dedicated primary settings is necessary
199
-			$this->setPrimaryEMailAddress('');
200
-		}
201
-
202
-		if ($oldMailAddress !== strtolower($mailAddress)) {
203
-			$this->triggerChange('eMailAddress', $mailAddress, $oldMailAddress);
204
-		}
205
-	}
206
-
207
-	/**
208
-	 * @inheritDoc
209
-	 */
210
-	public function setPrimaryEMailAddress(string $mailAddress): void {
211
-		if ($mailAddress === '') {
212
-			$this->config->deleteUserValue($this->uid, 'settings', 'primary_email');
213
-			return;
214
-		}
215
-
216
-		$this->ensureAccountManager();
217
-		$account = $this->accountManager->getAccount($this);
218
-		$property = $account->getPropertyCollection(IAccountManager::COLLECTION_EMAIL)
219
-			->getPropertyByValue($mailAddress);
220
-
221
-		if ($property === null || $property->getLocallyVerified() !== IAccountManager::VERIFIED) {
222
-			throw new InvalidArgumentException('Only verified emails can be set as primary');
223
-		}
224
-		$this->config->setUserValue($this->uid, 'settings', 'primary_email', $mailAddress);
225
-	}
226
-
227
-	private function ensureAccountManager() {
228
-		if (!$this->accountManager instanceof IAccountManager) {
229
-			$this->accountManager = \OC::$server->get(IAccountManager::class);
230
-		}
231
-	}
232
-
233
-	/**
234
-	 * returns the timestamp of the user's last login or 0 if the user did never
235
-	 * login
236
-	 *
237
-	 * @return int
238
-	 */
239
-	public function getLastLogin() {
240
-		if ($this->lastLogin === null) {
241
-			$this->lastLogin = (int) $this->config->getUserValue($this->uid, 'login', 'lastLogin', 0);
242
-		}
243
-		return (int) $this->lastLogin;
244
-	}
245
-
246
-	/**
247
-	 * updates the timestamp of the most recent login of this user
248
-	 */
249
-	public function updateLastLoginTimestamp() {
250
-		$previousLogin = $this->getLastLogin();
251
-		$now = time();
252
-		$firstTimeLogin = $previousLogin === 0;
253
-
254
-		if ($now - $previousLogin > 60) {
255
-			$this->lastLogin = time();
256
-			$this->config->setUserValue(
257
-				$this->uid, 'login', 'lastLogin', (string)$this->lastLogin);
258
-		}
259
-
260
-		return $firstTimeLogin;
261
-	}
262
-
263
-	/**
264
-	 * Delete the user
265
-	 *
266
-	 * @return bool
267
-	 */
268
-	public function delete() {
269
-		/** @deprecated 21.0.0 use BeforeUserDeletedEvent event with the IEventDispatcher instead */
270
-		$this->legacyDispatcher->dispatch(IUser::class . '::preDelete', new GenericEvent($this));
271
-		if ($this->emitter) {
272
-			/** @deprecated 21.0.0 use BeforeUserDeletedEvent event with the IEventDispatcher instead */
273
-			$this->emitter->emit('\OC\User', 'preDelete', [$this]);
274
-		}
275
-		$this->dispatcher->dispatchTyped(new BeforeUserDeletedEvent($this));
276
-		$result = $this->backend->deleteUser($this->uid);
277
-		if ($result) {
278
-
279
-			// FIXME: Feels like an hack - suggestions?
280
-
281
-			$groupManager = \OC::$server->getGroupManager();
282
-			// We have to delete the user from all groups
283
-			foreach ($groupManager->getUserGroupIds($this) as $groupId) {
284
-				$group = $groupManager->get($groupId);
285
-				if ($group) {
286
-					$this->dispatcher->dispatchTyped(new BeforeUserRemovedEvent($group, $this));
287
-					$group->removeUser($this);
288
-					$this->dispatcher->dispatchTyped(new UserRemovedEvent($group, $this));
289
-				}
290
-			}
291
-			// Delete the user's keys in preferences
292
-			\OC::$server->getConfig()->deleteAllUserValues($this->uid);
293
-
294
-			\OC::$server->getCommentsManager()->deleteReferencesOfActor('users', $this->uid);
295
-			\OC::$server->getCommentsManager()->deleteReadMarksFromUser($this);
296
-
297
-			/** @var AvatarManager $avatarManager */
298
-			$avatarManager = \OC::$server->query(AvatarManager::class);
299
-			$avatarManager->deleteUserAvatar($this->uid);
300
-
301
-			$notification = \OC::$server->getNotificationManager()->createNotification();
302
-			$notification->setUser($this->uid);
303
-			\OC::$server->getNotificationManager()->markProcessed($notification);
304
-
305
-			/** @var AccountManager $accountManager */
306
-			$accountManager = \OC::$server->query(AccountManager::class);
307
-			$accountManager->deleteUser($this);
308
-
309
-			/** @deprecated 21.0.0 use UserDeletedEvent event with the IEventDispatcher instead */
310
-			$this->legacyDispatcher->dispatch(IUser::class . '::postDelete', new GenericEvent($this));
311
-			if ($this->emitter) {
312
-				/** @deprecated 21.0.0 use UserDeletedEvent event with the IEventDispatcher instead */
313
-				$this->emitter->emit('\OC\User', 'postDelete', [$this]);
314
-			}
315
-			$this->dispatcher->dispatchTyped(new UserDeletedEvent($this));
316
-		}
317
-		return !($result === false);
318
-	}
319
-
320
-	/**
321
-	 * Set the password of the user
322
-	 *
323
-	 * @param string $password
324
-	 * @param string $recoveryPassword for the encryption app to reset encryption keys
325
-	 * @return bool
326
-	 */
327
-	public function setPassword($password, $recoveryPassword = null) {
328
-		$this->legacyDispatcher->dispatch(IUser::class . '::preSetPassword', new GenericEvent($this, [
329
-			'password' => $password,
330
-			'recoveryPassword' => $recoveryPassword,
331
-		]));
332
-		if ($this->emitter) {
333
-			$this->emitter->emit('\OC\User', 'preSetPassword', [$this, $password, $recoveryPassword]);
334
-		}
335
-		if ($this->backend->implementsActions(Backend::SET_PASSWORD)) {
336
-			/** @var ISetPasswordBackend $backend */
337
-			$backend = $this->backend;
338
-			$result = $backend->setPassword($this->uid, $password);
339
-
340
-			if ($result !== false) {
341
-				$this->legacyDispatcher->dispatch(IUser::class . '::postSetPassword', new GenericEvent($this, [
342
-					'password' => $password,
343
-					'recoveryPassword' => $recoveryPassword,
344
-				]));
345
-				if ($this->emitter) {
346
-					$this->emitter->emit('\OC\User', 'postSetPassword', [$this, $password, $recoveryPassword]);
347
-				}
348
-			}
349
-
350
-			return !($result === false);
351
-		} else {
352
-			return false;
353
-		}
354
-	}
355
-
356
-	/**
357
-	 * get the users home folder to mount
358
-	 *
359
-	 * @return string
360
-	 */
361
-	public function getHome() {
362
-		if (!$this->home) {
363
-			/** @psalm-suppress UndefinedInterfaceMethod Once we get rid of the legacy implementsActions, psalm won't complain anymore */
364
-			if (($this->backend instanceof IGetHomeBackend || $this->backend->implementsActions(Backend::GET_HOME)) && $home = $this->backend->getHome($this->uid)) {
365
-				$this->home = $home;
366
-			} elseif ($this->config) {
367
-				$this->home = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/' . $this->uid;
368
-			} else {
369
-				$this->home = \OC::$SERVERROOT . '/data/' . $this->uid;
370
-			}
371
-		}
372
-		return $this->home;
373
-	}
374
-
375
-	/**
376
-	 * Get the name of the backend class the user is connected with
377
-	 *
378
-	 * @return string
379
-	 */
380
-	public function getBackendClassName() {
381
-		if ($this->backend instanceof IUserBackend) {
382
-			return $this->backend->getBackendName();
383
-		}
384
-		return get_class($this->backend);
385
-	}
386
-
387
-	public function getBackend(): ?UserInterface {
388
-		return $this->backend;
389
-	}
390
-
391
-	/**
392
-	 * Check if the backend allows the user to change his avatar on Personal page
393
-	 *
394
-	 * @return bool
395
-	 */
396
-	public function canChangeAvatar() {
397
-		if ($this->backend instanceof IProvideAvatarBackend || $this->backend->implementsActions(Backend::PROVIDE_AVATAR)) {
398
-			/** @var IProvideAvatarBackend $backend */
399
-			$backend = $this->backend;
400
-			return $backend->canChangeAvatar($this->uid);
401
-		}
402
-		return true;
403
-	}
404
-
405
-	/**
406
-	 * check if the backend supports changing passwords
407
-	 *
408
-	 * @return bool
409
-	 */
410
-	public function canChangePassword() {
411
-		return $this->backend->implementsActions(Backend::SET_PASSWORD);
412
-	}
413
-
414
-	/**
415
-	 * check if the backend supports changing display names
416
-	 *
417
-	 * @return bool
418
-	 */
419
-	public function canChangeDisplayName() {
420
-		if ($this->config->getSystemValue('allow_user_to_change_display_name') === false) {
421
-			return false;
422
-		}
423
-		return $this->backend->implementsActions(Backend::SET_DISPLAYNAME);
424
-	}
425
-
426
-	/**
427
-	 * check if the user is enabled
428
-	 *
429
-	 * @return bool
430
-	 */
431
-	public function isEnabled() {
432
-		if ($this->enabled === null) {
433
-			$enabled = $this->config->getUserValue($this->uid, 'core', 'enabled', 'true');
434
-			$this->enabled = $enabled === 'true';
435
-		}
436
-		return (bool) $this->enabled;
437
-	}
438
-
439
-	/**
440
-	 * set the enabled status for the user
441
-	 *
442
-	 * @param bool $enabled
443
-	 */
444
-	public function setEnabled(bool $enabled = true) {
445
-		$oldStatus = $this->isEnabled();
446
-		$this->enabled = $enabled;
447
-		if ($oldStatus !== $this->enabled) {
448
-			// TODO: First change the value, then trigger the event as done for all other properties.
449
-			$this->triggerChange('enabled', $enabled, $oldStatus);
450
-			$this->config->setUserValue($this->uid, 'core', 'enabled', $enabled ? 'true' : 'false');
451
-		}
452
-	}
453
-
454
-	/**
455
-	 * get the users email address
456
-	 *
457
-	 * @return string|null
458
-	 * @since 9.0.0
459
-	 */
460
-	public function getEMailAddress() {
461
-		return $this->getPrimaryEMailAddress() ?? $this->getSystemEMailAddress();
462
-	}
463
-
464
-	/**
465
-	 * @inheritDoc
466
-	 */
467
-	public function getSystemEMailAddress(): ?string {
468
-		return $this->config->getUserValue($this->uid, 'settings', 'email', null);
469
-	}
470
-
471
-	/**
472
-	 * @inheritDoc
473
-	 */
474
-	public function getPrimaryEMailAddress(): ?string {
475
-		return $this->config->getUserValue($this->uid, 'settings', 'primary_email', null);
476
-	}
477
-
478
-	/**
479
-	 * get the users' quota
480
-	 *
481
-	 * @return string
482
-	 * @since 9.0.0
483
-	 */
484
-	public function getQuota() {
485
-		// allow apps to modify the user quota by hooking into the event
486
-		$event = new GetQuotaEvent($this);
487
-		$this->dispatcher->dispatchTyped($event);
488
-		$overwriteQuota = $event->getQuota();
489
-		if ($overwriteQuota) {
490
-			$quota = $overwriteQuota;
491
-		} else {
492
-			$quota = $this->config->getUserValue($this->uid, 'files', 'quota', 'default');
493
-		}
494
-		if ($quota === 'default') {
495
-			$quota = $this->config->getAppValue('files', 'default_quota', 'none');
496
-
497
-			// if unlimited quota is not allowed => avoid getting 'unlimited' as default_quota fallback value
498
-			// use the first preset instead
499
-			$allowUnlimitedQuota = $this->config->getAppValue('files', 'allow_unlimited_quota', '1') === '1';
500
-			if (!$allowUnlimitedQuota) {
501
-				$presets = $this->config->getAppValue('files', 'quota_preset', '1 GB, 5 GB, 10 GB');
502
-				$presets = array_filter(array_map('trim', explode(',', $presets)));
503
-				$quotaPreset = array_values(array_diff($presets, ['default', 'none']));
504
-				if (count($quotaPreset) > 0) {
505
-					$quota = $this->config->getAppValue('files', 'default_quota', $quotaPreset[0]);
506
-				}
507
-			}
508
-		}
509
-		return $quota;
510
-	}
511
-
512
-	/**
513
-	 * set the users' quota
514
-	 *
515
-	 * @param string $quota
516
-	 * @return void
517
-	 * @since 9.0.0
518
-	 */
519
-	public function setQuota($quota) {
520
-		$oldQuota = $this->config->getUserValue($this->uid, 'files', 'quota', '');
521
-		if ($quota !== 'none' and $quota !== 'default') {
522
-			$quota = OC_Helper::computerFileSize($quota);
523
-			$quota = OC_Helper::humanFileSize((int)$quota);
524
-		}
525
-		if ($quota !== $oldQuota) {
526
-			$this->config->setUserValue($this->uid, 'files', 'quota', $quota);
527
-			$this->triggerChange('quota', $quota, $oldQuota);
528
-		}
529
-	}
530
-
531
-	/**
532
-	 * get the avatar image if it exists
533
-	 *
534
-	 * @param int $size
535
-	 * @return IImage|null
536
-	 * @since 9.0.0
537
-	 */
538
-	public function getAvatarImage($size) {
539
-		// delay the initialization
540
-		if (is_null($this->avatarManager)) {
541
-			$this->avatarManager = \OC::$server->getAvatarManager();
542
-		}
543
-
544
-		$avatar = $this->avatarManager->getAvatar($this->uid);
545
-		$image = $avatar->get(-1);
546
-		if ($image) {
547
-			return $image;
548
-		}
549
-
550
-		return null;
551
-	}
552
-
553
-	/**
554
-	 * get the federation cloud id
555
-	 *
556
-	 * @return string
557
-	 * @since 9.0.0
558
-	 */
559
-	public function getCloudId() {
560
-		$uid = $this->getUID();
561
-		$server = rtrim($this->urlGenerator->getAbsoluteURL('/'), '/');
562
-		if (substr($server, -10) === '/index.php') {
563
-			$server = substr($server, 0, -10);
564
-		}
565
-		$server = $this->removeProtocolFromUrl($server);
566
-		return $uid . '@' . $server;
567
-	}
568
-
569
-	private function removeProtocolFromUrl(string $url): string {
570
-		if (strpos($url, 'https://') === 0) {
571
-			return substr($url, strlen('https://'));
572
-		}
573
-
574
-		return $url;
575
-	}
576
-
577
-	public function triggerChange($feature, $value = null, $oldValue = null) {
578
-		$this->legacyDispatcher->dispatch(IUser::class . '::changeUser', new GenericEvent($this, [
579
-			'feature' => $feature,
580
-			'value' => $value,
581
-			'oldValue' => $oldValue,
582
-		]));
583
-		if ($this->emitter) {
584
-			$this->emitter->emit('\OC\User', 'changeUser', [$this, $feature, $value, $oldValue]);
585
-		}
586
-	}
64
+    /** @var IAccountManager */
65
+    protected $accountManager;
66
+    /** @var string */
67
+    private $uid;
68
+
69
+    /** @var string|null */
70
+    private $displayName;
71
+
72
+    /** @var UserInterface|null */
73
+    private $backend;
74
+    /** @var EventDispatcherInterface */
75
+    private $legacyDispatcher;
76
+
77
+    /** @var IEventDispatcher */
78
+    private $dispatcher;
79
+
80
+    /** @var bool|null */
81
+    private $enabled;
82
+
83
+    /** @var Emitter|Manager */
84
+    private $emitter;
85
+
86
+    /** @var string */
87
+    private $home;
88
+
89
+    /** @var int|null */
90
+    private $lastLogin;
91
+
92
+    /** @var \OCP\IConfig */
93
+    private $config;
94
+
95
+    /** @var IAvatarManager */
96
+    private $avatarManager;
97
+
98
+    /** @var IURLGenerator */
99
+    private $urlGenerator;
100
+
101
+    public function __construct(string $uid, ?UserInterface $backend, EventDispatcherInterface $dispatcher, $emitter = null, IConfig $config = null, $urlGenerator = null) {
102
+        $this->uid = $uid;
103
+        $this->backend = $backend;
104
+        $this->legacyDispatcher = $dispatcher;
105
+        $this->emitter = $emitter;
106
+        if (is_null($config)) {
107
+            $config = \OC::$server->getConfig();
108
+        }
109
+        $this->config = $config;
110
+        $this->urlGenerator = $urlGenerator;
111
+        if (is_null($this->urlGenerator)) {
112
+            $this->urlGenerator = \OC::$server->getURLGenerator();
113
+        }
114
+        // TODO: inject
115
+        $this->dispatcher = \OC::$server->query(IEventDispatcher::class);
116
+    }
117
+
118
+    /**
119
+     * get the user id
120
+     *
121
+     * @return string
122
+     */
123
+    public function getUID() {
124
+        return $this->uid;
125
+    }
126
+
127
+    /**
128
+     * get the display name for the user, if no specific display name is set it will fallback to the user id
129
+     *
130
+     * @return string
131
+     */
132
+    public function getDisplayName() {
133
+        if ($this->displayName === null) {
134
+            $displayName = '';
135
+            if ($this->backend && $this->backend->implementsActions(Backend::GET_DISPLAYNAME)) {
136
+                // get display name and strip whitespace from the beginning and end of it
137
+                $backendDisplayName = $this->backend->getDisplayName($this->uid);
138
+                if (is_string($backendDisplayName)) {
139
+                    $displayName = trim($backendDisplayName);
140
+                }
141
+            }
142
+
143
+            if (!empty($displayName)) {
144
+                $this->displayName = $displayName;
145
+            } else {
146
+                $this->displayName = $this->uid;
147
+            }
148
+        }
149
+        return $this->displayName;
150
+    }
151
+
152
+    /**
153
+     * set the displayname for the user
154
+     *
155
+     * @param string $displayName
156
+     * @return bool
157
+     *
158
+     * @since 25.0.0 Throw InvalidArgumentException
159
+     * @throws \InvalidArgumentException
160
+     */
161
+    public function setDisplayName($displayName) {
162
+        $displayName = trim($displayName);
163
+        $oldDisplayName = $this->getDisplayName();
164
+        if ($this->backend->implementsActions(Backend::SET_DISPLAYNAME) && !empty($displayName) && $displayName !== $oldDisplayName) {
165
+            /** @var ISetDisplayNameBackend $backend */
166
+            $backend = $this->backend;
167
+            $result = $backend->setDisplayName($this->uid, $displayName);
168
+            if ($result) {
169
+                $this->displayName = $displayName;
170
+                $this->triggerChange('displayName', $displayName, $oldDisplayName);
171
+            }
172
+            return $result !== false;
173
+        }
174
+        return false;
175
+    }
176
+
177
+    /**
178
+     * @inheritDoc
179
+     */
180
+    public function setEMailAddress($mailAddress) {
181
+        $this->setSystemEMailAddress($mailAddress);
182
+    }
183
+
184
+    /**
185
+     * @inheritDoc
186
+     */
187
+    public function setSystemEMailAddress(string $mailAddress): void {
188
+        $oldMailAddress = $this->getSystemEMailAddress();
189
+
190
+        if ($mailAddress === '') {
191
+            $this->config->deleteUserValue($this->uid, 'settings', 'email');
192
+        } else {
193
+            $this->config->setUserValue($this->uid, 'settings', 'email', $mailAddress);
194
+        }
195
+
196
+        $primaryAddress = $this->getPrimaryEMailAddress();
197
+        if ($primaryAddress === $mailAddress) {
198
+            // on match no dedicated primary settings is necessary
199
+            $this->setPrimaryEMailAddress('');
200
+        }
201
+
202
+        if ($oldMailAddress !== strtolower($mailAddress)) {
203
+            $this->triggerChange('eMailAddress', $mailAddress, $oldMailAddress);
204
+        }
205
+    }
206
+
207
+    /**
208
+     * @inheritDoc
209
+     */
210
+    public function setPrimaryEMailAddress(string $mailAddress): void {
211
+        if ($mailAddress === '') {
212
+            $this->config->deleteUserValue($this->uid, 'settings', 'primary_email');
213
+            return;
214
+        }
215
+
216
+        $this->ensureAccountManager();
217
+        $account = $this->accountManager->getAccount($this);
218
+        $property = $account->getPropertyCollection(IAccountManager::COLLECTION_EMAIL)
219
+            ->getPropertyByValue($mailAddress);
220
+
221
+        if ($property === null || $property->getLocallyVerified() !== IAccountManager::VERIFIED) {
222
+            throw new InvalidArgumentException('Only verified emails can be set as primary');
223
+        }
224
+        $this->config->setUserValue($this->uid, 'settings', 'primary_email', $mailAddress);
225
+    }
226
+
227
+    private function ensureAccountManager() {
228
+        if (!$this->accountManager instanceof IAccountManager) {
229
+            $this->accountManager = \OC::$server->get(IAccountManager::class);
230
+        }
231
+    }
232
+
233
+    /**
234
+     * returns the timestamp of the user's last login or 0 if the user did never
235
+     * login
236
+     *
237
+     * @return int
238
+     */
239
+    public function getLastLogin() {
240
+        if ($this->lastLogin === null) {
241
+            $this->lastLogin = (int) $this->config->getUserValue($this->uid, 'login', 'lastLogin', 0);
242
+        }
243
+        return (int) $this->lastLogin;
244
+    }
245
+
246
+    /**
247
+     * updates the timestamp of the most recent login of this user
248
+     */
249
+    public function updateLastLoginTimestamp() {
250
+        $previousLogin = $this->getLastLogin();
251
+        $now = time();
252
+        $firstTimeLogin = $previousLogin === 0;
253
+
254
+        if ($now - $previousLogin > 60) {
255
+            $this->lastLogin = time();
256
+            $this->config->setUserValue(
257
+                $this->uid, 'login', 'lastLogin', (string)$this->lastLogin);
258
+        }
259
+
260
+        return $firstTimeLogin;
261
+    }
262
+
263
+    /**
264
+     * Delete the user
265
+     *
266
+     * @return bool
267
+     */
268
+    public function delete() {
269
+        /** @deprecated 21.0.0 use BeforeUserDeletedEvent event with the IEventDispatcher instead */
270
+        $this->legacyDispatcher->dispatch(IUser::class . '::preDelete', new GenericEvent($this));
271
+        if ($this->emitter) {
272
+            /** @deprecated 21.0.0 use BeforeUserDeletedEvent event with the IEventDispatcher instead */
273
+            $this->emitter->emit('\OC\User', 'preDelete', [$this]);
274
+        }
275
+        $this->dispatcher->dispatchTyped(new BeforeUserDeletedEvent($this));
276
+        $result = $this->backend->deleteUser($this->uid);
277
+        if ($result) {
278
+
279
+            // FIXME: Feels like an hack - suggestions?
280
+
281
+            $groupManager = \OC::$server->getGroupManager();
282
+            // We have to delete the user from all groups
283
+            foreach ($groupManager->getUserGroupIds($this) as $groupId) {
284
+                $group = $groupManager->get($groupId);
285
+                if ($group) {
286
+                    $this->dispatcher->dispatchTyped(new BeforeUserRemovedEvent($group, $this));
287
+                    $group->removeUser($this);
288
+                    $this->dispatcher->dispatchTyped(new UserRemovedEvent($group, $this));
289
+                }
290
+            }
291
+            // Delete the user's keys in preferences
292
+            \OC::$server->getConfig()->deleteAllUserValues($this->uid);
293
+
294
+            \OC::$server->getCommentsManager()->deleteReferencesOfActor('users', $this->uid);
295
+            \OC::$server->getCommentsManager()->deleteReadMarksFromUser($this);
296
+
297
+            /** @var AvatarManager $avatarManager */
298
+            $avatarManager = \OC::$server->query(AvatarManager::class);
299
+            $avatarManager->deleteUserAvatar($this->uid);
300
+
301
+            $notification = \OC::$server->getNotificationManager()->createNotification();
302
+            $notification->setUser($this->uid);
303
+            \OC::$server->getNotificationManager()->markProcessed($notification);
304
+
305
+            /** @var AccountManager $accountManager */
306
+            $accountManager = \OC::$server->query(AccountManager::class);
307
+            $accountManager->deleteUser($this);
308
+
309
+            /** @deprecated 21.0.0 use UserDeletedEvent event with the IEventDispatcher instead */
310
+            $this->legacyDispatcher->dispatch(IUser::class . '::postDelete', new GenericEvent($this));
311
+            if ($this->emitter) {
312
+                /** @deprecated 21.0.0 use UserDeletedEvent event with the IEventDispatcher instead */
313
+                $this->emitter->emit('\OC\User', 'postDelete', [$this]);
314
+            }
315
+            $this->dispatcher->dispatchTyped(new UserDeletedEvent($this));
316
+        }
317
+        return !($result === false);
318
+    }
319
+
320
+    /**
321
+     * Set the password of the user
322
+     *
323
+     * @param string $password
324
+     * @param string $recoveryPassword for the encryption app to reset encryption keys
325
+     * @return bool
326
+     */
327
+    public function setPassword($password, $recoveryPassword = null) {
328
+        $this->legacyDispatcher->dispatch(IUser::class . '::preSetPassword', new GenericEvent($this, [
329
+            'password' => $password,
330
+            'recoveryPassword' => $recoveryPassword,
331
+        ]));
332
+        if ($this->emitter) {
333
+            $this->emitter->emit('\OC\User', 'preSetPassword', [$this, $password, $recoveryPassword]);
334
+        }
335
+        if ($this->backend->implementsActions(Backend::SET_PASSWORD)) {
336
+            /** @var ISetPasswordBackend $backend */
337
+            $backend = $this->backend;
338
+            $result = $backend->setPassword($this->uid, $password);
339
+
340
+            if ($result !== false) {
341
+                $this->legacyDispatcher->dispatch(IUser::class . '::postSetPassword', new GenericEvent($this, [
342
+                    'password' => $password,
343
+                    'recoveryPassword' => $recoveryPassword,
344
+                ]));
345
+                if ($this->emitter) {
346
+                    $this->emitter->emit('\OC\User', 'postSetPassword', [$this, $password, $recoveryPassword]);
347
+                }
348
+            }
349
+
350
+            return !($result === false);
351
+        } else {
352
+            return false;
353
+        }
354
+    }
355
+
356
+    /**
357
+     * get the users home folder to mount
358
+     *
359
+     * @return string
360
+     */
361
+    public function getHome() {
362
+        if (!$this->home) {
363
+            /** @psalm-suppress UndefinedInterfaceMethod Once we get rid of the legacy implementsActions, psalm won't complain anymore */
364
+            if (($this->backend instanceof IGetHomeBackend || $this->backend->implementsActions(Backend::GET_HOME)) && $home = $this->backend->getHome($this->uid)) {
365
+                $this->home = $home;
366
+            } elseif ($this->config) {
367
+                $this->home = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/' . $this->uid;
368
+            } else {
369
+                $this->home = \OC::$SERVERROOT . '/data/' . $this->uid;
370
+            }
371
+        }
372
+        return $this->home;
373
+    }
374
+
375
+    /**
376
+     * Get the name of the backend class the user is connected with
377
+     *
378
+     * @return string
379
+     */
380
+    public function getBackendClassName() {
381
+        if ($this->backend instanceof IUserBackend) {
382
+            return $this->backend->getBackendName();
383
+        }
384
+        return get_class($this->backend);
385
+    }
386
+
387
+    public function getBackend(): ?UserInterface {
388
+        return $this->backend;
389
+    }
390
+
391
+    /**
392
+     * Check if the backend allows the user to change his avatar on Personal page
393
+     *
394
+     * @return bool
395
+     */
396
+    public function canChangeAvatar() {
397
+        if ($this->backend instanceof IProvideAvatarBackend || $this->backend->implementsActions(Backend::PROVIDE_AVATAR)) {
398
+            /** @var IProvideAvatarBackend $backend */
399
+            $backend = $this->backend;
400
+            return $backend->canChangeAvatar($this->uid);
401
+        }
402
+        return true;
403
+    }
404
+
405
+    /**
406
+     * check if the backend supports changing passwords
407
+     *
408
+     * @return bool
409
+     */
410
+    public function canChangePassword() {
411
+        return $this->backend->implementsActions(Backend::SET_PASSWORD);
412
+    }
413
+
414
+    /**
415
+     * check if the backend supports changing display names
416
+     *
417
+     * @return bool
418
+     */
419
+    public function canChangeDisplayName() {
420
+        if ($this->config->getSystemValue('allow_user_to_change_display_name') === false) {
421
+            return false;
422
+        }
423
+        return $this->backend->implementsActions(Backend::SET_DISPLAYNAME);
424
+    }
425
+
426
+    /**
427
+     * check if the user is enabled
428
+     *
429
+     * @return bool
430
+     */
431
+    public function isEnabled() {
432
+        if ($this->enabled === null) {
433
+            $enabled = $this->config->getUserValue($this->uid, 'core', 'enabled', 'true');
434
+            $this->enabled = $enabled === 'true';
435
+        }
436
+        return (bool) $this->enabled;
437
+    }
438
+
439
+    /**
440
+     * set the enabled status for the user
441
+     *
442
+     * @param bool $enabled
443
+     */
444
+    public function setEnabled(bool $enabled = true) {
445
+        $oldStatus = $this->isEnabled();
446
+        $this->enabled = $enabled;
447
+        if ($oldStatus !== $this->enabled) {
448
+            // TODO: First change the value, then trigger the event as done for all other properties.
449
+            $this->triggerChange('enabled', $enabled, $oldStatus);
450
+            $this->config->setUserValue($this->uid, 'core', 'enabled', $enabled ? 'true' : 'false');
451
+        }
452
+    }
453
+
454
+    /**
455
+     * get the users email address
456
+     *
457
+     * @return string|null
458
+     * @since 9.0.0
459
+     */
460
+    public function getEMailAddress() {
461
+        return $this->getPrimaryEMailAddress() ?? $this->getSystemEMailAddress();
462
+    }
463
+
464
+    /**
465
+     * @inheritDoc
466
+     */
467
+    public function getSystemEMailAddress(): ?string {
468
+        return $this->config->getUserValue($this->uid, 'settings', 'email', null);
469
+    }
470
+
471
+    /**
472
+     * @inheritDoc
473
+     */
474
+    public function getPrimaryEMailAddress(): ?string {
475
+        return $this->config->getUserValue($this->uid, 'settings', 'primary_email', null);
476
+    }
477
+
478
+    /**
479
+     * get the users' quota
480
+     *
481
+     * @return string
482
+     * @since 9.0.0
483
+     */
484
+    public function getQuota() {
485
+        // allow apps to modify the user quota by hooking into the event
486
+        $event = new GetQuotaEvent($this);
487
+        $this->dispatcher->dispatchTyped($event);
488
+        $overwriteQuota = $event->getQuota();
489
+        if ($overwriteQuota) {
490
+            $quota = $overwriteQuota;
491
+        } else {
492
+            $quota = $this->config->getUserValue($this->uid, 'files', 'quota', 'default');
493
+        }
494
+        if ($quota === 'default') {
495
+            $quota = $this->config->getAppValue('files', 'default_quota', 'none');
496
+
497
+            // if unlimited quota is not allowed => avoid getting 'unlimited' as default_quota fallback value
498
+            // use the first preset instead
499
+            $allowUnlimitedQuota = $this->config->getAppValue('files', 'allow_unlimited_quota', '1') === '1';
500
+            if (!$allowUnlimitedQuota) {
501
+                $presets = $this->config->getAppValue('files', 'quota_preset', '1 GB, 5 GB, 10 GB');
502
+                $presets = array_filter(array_map('trim', explode(',', $presets)));
503
+                $quotaPreset = array_values(array_diff($presets, ['default', 'none']));
504
+                if (count($quotaPreset) > 0) {
505
+                    $quota = $this->config->getAppValue('files', 'default_quota', $quotaPreset[0]);
506
+                }
507
+            }
508
+        }
509
+        return $quota;
510
+    }
511
+
512
+    /**
513
+     * set the users' quota
514
+     *
515
+     * @param string $quota
516
+     * @return void
517
+     * @since 9.0.0
518
+     */
519
+    public function setQuota($quota) {
520
+        $oldQuota = $this->config->getUserValue($this->uid, 'files', 'quota', '');
521
+        if ($quota !== 'none' and $quota !== 'default') {
522
+            $quota = OC_Helper::computerFileSize($quota);
523
+            $quota = OC_Helper::humanFileSize((int)$quota);
524
+        }
525
+        if ($quota !== $oldQuota) {
526
+            $this->config->setUserValue($this->uid, 'files', 'quota', $quota);
527
+            $this->triggerChange('quota', $quota, $oldQuota);
528
+        }
529
+    }
530
+
531
+    /**
532
+     * get the avatar image if it exists
533
+     *
534
+     * @param int $size
535
+     * @return IImage|null
536
+     * @since 9.0.0
537
+     */
538
+    public function getAvatarImage($size) {
539
+        // delay the initialization
540
+        if (is_null($this->avatarManager)) {
541
+            $this->avatarManager = \OC::$server->getAvatarManager();
542
+        }
543
+
544
+        $avatar = $this->avatarManager->getAvatar($this->uid);
545
+        $image = $avatar->get(-1);
546
+        if ($image) {
547
+            return $image;
548
+        }
549
+
550
+        return null;
551
+    }
552
+
553
+    /**
554
+     * get the federation cloud id
555
+     *
556
+     * @return string
557
+     * @since 9.0.0
558
+     */
559
+    public function getCloudId() {
560
+        $uid = $this->getUID();
561
+        $server = rtrim($this->urlGenerator->getAbsoluteURL('/'), '/');
562
+        if (substr($server, -10) === '/index.php') {
563
+            $server = substr($server, 0, -10);
564
+        }
565
+        $server = $this->removeProtocolFromUrl($server);
566
+        return $uid . '@' . $server;
567
+    }
568
+
569
+    private function removeProtocolFromUrl(string $url): string {
570
+        if (strpos($url, 'https://') === 0) {
571
+            return substr($url, strlen('https://'));
572
+        }
573
+
574
+        return $url;
575
+    }
576
+
577
+    public function triggerChange($feature, $value = null, $oldValue = null) {
578
+        $this->legacyDispatcher->dispatch(IUser::class . '::changeUser', new GenericEvent($this, [
579
+            'feature' => $feature,
580
+            'value' => $value,
581
+            'oldValue' => $oldValue,
582
+        ]));
583
+        if ($this->emitter) {
584
+            $this->emitter->emit('\OC\User', 'changeUser', [$this, $feature, $value, $oldValue]);
585
+        }
586
+    }
587 587
 }
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -254,7 +254,7 @@  discard block
 block discarded – undo
254 254
 		if ($now - $previousLogin > 60) {
255 255
 			$this->lastLogin = time();
256 256
 			$this->config->setUserValue(
257
-				$this->uid, 'login', 'lastLogin', (string)$this->lastLogin);
257
+				$this->uid, 'login', 'lastLogin', (string) $this->lastLogin);
258 258
 		}
259 259
 
260 260
 		return $firstTimeLogin;
@@ -267,7 +267,7 @@  discard block
 block discarded – undo
267 267
 	 */
268 268
 	public function delete() {
269 269
 		/** @deprecated 21.0.0 use BeforeUserDeletedEvent event with the IEventDispatcher instead */
270
-		$this->legacyDispatcher->dispatch(IUser::class . '::preDelete', new GenericEvent($this));
270
+		$this->legacyDispatcher->dispatch(IUser::class.'::preDelete', new GenericEvent($this));
271 271
 		if ($this->emitter) {
272 272
 			/** @deprecated 21.0.0 use BeforeUserDeletedEvent event with the IEventDispatcher instead */
273 273
 			$this->emitter->emit('\OC\User', 'preDelete', [$this]);
@@ -307,7 +307,7 @@  discard block
 block discarded – undo
307 307
 			$accountManager->deleteUser($this);
308 308
 
309 309
 			/** @deprecated 21.0.0 use UserDeletedEvent event with the IEventDispatcher instead */
310
-			$this->legacyDispatcher->dispatch(IUser::class . '::postDelete', new GenericEvent($this));
310
+			$this->legacyDispatcher->dispatch(IUser::class.'::postDelete', new GenericEvent($this));
311 311
 			if ($this->emitter) {
312 312
 				/** @deprecated 21.0.0 use UserDeletedEvent event with the IEventDispatcher instead */
313 313
 				$this->emitter->emit('\OC\User', 'postDelete', [$this]);
@@ -325,7 +325,7 @@  discard block
 block discarded – undo
325 325
 	 * @return bool
326 326
 	 */
327 327
 	public function setPassword($password, $recoveryPassword = null) {
328
-		$this->legacyDispatcher->dispatch(IUser::class . '::preSetPassword', new GenericEvent($this, [
328
+		$this->legacyDispatcher->dispatch(IUser::class.'::preSetPassword', new GenericEvent($this, [
329 329
 			'password' => $password,
330 330
 			'recoveryPassword' => $recoveryPassword,
331 331
 		]));
@@ -338,7 +338,7 @@  discard block
 block discarded – undo
338 338
 			$result = $backend->setPassword($this->uid, $password);
339 339
 
340 340
 			if ($result !== false) {
341
-				$this->legacyDispatcher->dispatch(IUser::class . '::postSetPassword', new GenericEvent($this, [
341
+				$this->legacyDispatcher->dispatch(IUser::class.'::postSetPassword', new GenericEvent($this, [
342 342
 					'password' => $password,
343 343
 					'recoveryPassword' => $recoveryPassword,
344 344
 				]));
@@ -364,9 +364,9 @@  discard block
 block discarded – undo
364 364
 			if (($this->backend instanceof IGetHomeBackend || $this->backend->implementsActions(Backend::GET_HOME)) && $home = $this->backend->getHome($this->uid)) {
365 365
 				$this->home = $home;
366 366
 			} elseif ($this->config) {
367
-				$this->home = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/' . $this->uid;
367
+				$this->home = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data').'/'.$this->uid;
368 368
 			} else {
369
-				$this->home = \OC::$SERVERROOT . '/data/' . $this->uid;
369
+				$this->home = \OC::$SERVERROOT.'/data/'.$this->uid;
370 370
 			}
371 371
 		}
372 372
 		return $this->home;
@@ -520,7 +520,7 @@  discard block
 block discarded – undo
520 520
 		$oldQuota = $this->config->getUserValue($this->uid, 'files', 'quota', '');
521 521
 		if ($quota !== 'none' and $quota !== 'default') {
522 522
 			$quota = OC_Helper::computerFileSize($quota);
523
-			$quota = OC_Helper::humanFileSize((int)$quota);
523
+			$quota = OC_Helper::humanFileSize((int) $quota);
524 524
 		}
525 525
 		if ($quota !== $oldQuota) {
526 526
 			$this->config->setUserValue($this->uid, 'files', 'quota', $quota);
@@ -563,7 +563,7 @@  discard block
 block discarded – undo
563 563
 			$server = substr($server, 0, -10);
564 564
 		}
565 565
 		$server = $this->removeProtocolFromUrl($server);
566
-		return $uid . '@' . $server;
566
+		return $uid.'@'.$server;
567 567
 	}
568 568
 
569 569
 	private function removeProtocolFromUrl(string $url): string {
@@ -575,7 +575,7 @@  discard block
 block discarded – undo
575 575
 	}
576 576
 
577 577
 	public function triggerChange($feature, $value = null, $oldValue = null) {
578
-		$this->legacyDispatcher->dispatch(IUser::class . '::changeUser', new GenericEvent($this, [
578
+		$this->legacyDispatcher->dispatch(IUser::class.'::changeUser', new GenericEvent($this, [
579 579
 			'feature' => $feature,
580 580
 			'value' => $value,
581 581
 			'oldValue' => $oldValue,
Please login to merge, or discard this patch.