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