Passed
Push — master ( 6331f1...762a8b )
by Joas
11:56 queued 10s
created
lib/private/User/Manager.php 1 patch
Indentation   +549 added lines, -549 removed lines patch added patch discarded remove patch
@@ -59,557 +59,557 @@
 block discarded – undo
59 59
  * @package OC\User
60 60
  */
61 61
 class Manager extends PublicEmitter implements IUserManager {
62
-	/**
63
-	 * @var \OCP\UserInterface[] $backends
64
-	 */
65
-	private $backends = array();
66
-
67
-	/**
68
-	 * @var \OC\User\User[] $cachedUsers
69
-	 */
70
-	private $cachedUsers = array();
71
-
72
-	/** @var IConfig */
73
-	private $config;
74
-	/** @var EventDispatcherInterface */
75
-	private $dispatcher;
76
-
77
-	public function __construct(IConfig $config, EventDispatcherInterface $dispatcher) {
78
-		$this->config = $config;
79
-		$this->dispatcher = $dispatcher;
80
-		$cachedUsers = &$this->cachedUsers;
81
-		$this->listen('\OC\User', 'postDelete', function ($user) use (&$cachedUsers) {
82
-			/** @var \OC\User\User $user */
83
-			unset($cachedUsers[$user->getUID()]);
84
-		});
85
-	}
86
-
87
-	/**
88
-	 * Get the active backends
89
-	 * @return \OCP\UserInterface[]
90
-	 */
91
-	public function getBackends() {
92
-		return $this->backends;
93
-	}
94
-
95
-	/**
96
-	 * register a user backend
97
-	 *
98
-	 * @param \OCP\UserInterface $backend
99
-	 */
100
-	public function registerBackend($backend) {
101
-		$this->backends[] = $backend;
102
-	}
103
-
104
-	/**
105
-	 * remove a user backend
106
-	 *
107
-	 * @param \OCP\UserInterface $backend
108
-	 */
109
-	public function removeBackend($backend) {
110
-		$this->cachedUsers = array();
111
-		if (($i = array_search($backend, $this->backends)) !== false) {
112
-			unset($this->backends[$i]);
113
-		}
114
-	}
115
-
116
-	/**
117
-	 * remove all user backends
118
-	 */
119
-	public function clearBackends() {
120
-		$this->cachedUsers = array();
121
-		$this->backends = array();
122
-	}
123
-
124
-	/**
125
-	 * get a user by user id
126
-	 *
127
-	 * @param string $uid
128
-	 * @return \OC\User\User|null Either the user or null if the specified user does not exist
129
-	 */
130
-	public function get($uid) {
131
-		if (is_null($uid) || $uid === '' || $uid === false) {
132
-			return null;
133
-		}
134
-		if (isset($this->cachedUsers[$uid])) { //check the cache first to prevent having to loop over the backends
135
-			return $this->cachedUsers[$uid];
136
-		}
137
-		foreach ($this->backends as $backend) {
138
-			if ($backend->userExists($uid)) {
139
-				return $this->getUserObject($uid, $backend);
140
-			}
141
-		}
142
-		return null;
143
-	}
144
-
145
-	/**
146
-	 * get or construct the user object
147
-	 *
148
-	 * @param string $uid
149
-	 * @param \OCP\UserInterface $backend
150
-	 * @param bool $cacheUser If false the newly created user object will not be cached
151
-	 * @return \OC\User\User
152
-	 */
153
-	protected function getUserObject($uid, $backend, $cacheUser = true) {
154
-		if (isset($this->cachedUsers[$uid])) {
155
-			return $this->cachedUsers[$uid];
156
-		}
157
-
158
-		$user = new User($uid, $backend, $this->dispatcher, $this, $this->config);
159
-		if ($cacheUser) {
160
-			$this->cachedUsers[$uid] = $user;
161
-		}
162
-		return $user;
163
-	}
164
-
165
-	/**
166
-	 * check if a user exists
167
-	 *
168
-	 * @param string $uid
169
-	 * @return bool
170
-	 */
171
-	public function userExists($uid) {
172
-		$user = $this->get($uid);
173
-		return ($user !== null);
174
-	}
175
-
176
-	/**
177
-	 * Check if the password is valid for the user
178
-	 *
179
-	 * @param string $loginName
180
-	 * @param string $password
181
-	 * @return mixed the User object on success, false otherwise
182
-	 */
183
-	public function checkPassword($loginName, $password) {
184
-		$result = $this->checkPasswordNoLogging($loginName, $password);
185
-
186
-		if ($result === false) {
187
-			\OC::$server->getLogger()->warning('Login failed: \''. $loginName .'\' (Remote IP: \''. \OC::$server->getRequest()->getRemoteAddress(). '\')', ['app' => 'core']);
188
-		}
189
-
190
-		return $result;
191
-	}
192
-
193
-	/**
194
-	 * Check if the password is valid for the user
195
-	 *
196
-	 * @internal
197
-	 * @param string $loginName
198
-	 * @param string $password
199
-	 * @return mixed the User object on success, false otherwise
200
-	 */
201
-	public function checkPasswordNoLogging($loginName, $password) {
202
-		$loginName = str_replace("\0", '', $loginName);
203
-		$password = str_replace("\0", '', $password);
204
-
205
-		foreach ($this->backends as $backend) {
206
-			if ($backend->implementsActions(Backend::CHECK_PASSWORD)) {
207
-				$uid = $backend->checkPassword($loginName, $password);
208
-				if ($uid !== false) {
209
-					return $this->getUserObject($uid, $backend);
210
-				}
211
-			}
212
-		}
213
-
214
-		return false;
215
-	}
216
-
217
-	/**
218
-	 * search by user id
219
-	 *
220
-	 * @param string $pattern
221
-	 * @param int $limit
222
-	 * @param int $offset
223
-	 * @return \OC\User\User[]
224
-	 */
225
-	public function search($pattern, $limit = null, $offset = null) {
226
-		$users = array();
227
-		foreach ($this->backends as $backend) {
228
-			$backendUsers = $backend->getUsers($pattern, $limit, $offset);
229
-			if (is_array($backendUsers)) {
230
-				foreach ($backendUsers as $uid) {
231
-					$users[$uid] = $this->getUserObject($uid, $backend);
232
-				}
233
-			}
234
-		}
235
-
236
-		uasort($users, function ($a, $b) {
237
-			/**
238
-			 * @var \OC\User\User $a
239
-			 * @var \OC\User\User $b
240
-			 */
241
-			return strcasecmp($a->getUID(), $b->getUID());
242
-		});
243
-		return $users;
244
-	}
245
-
246
-	/**
247
-	 * search by displayName
248
-	 *
249
-	 * @param string $pattern
250
-	 * @param int $limit
251
-	 * @param int $offset
252
-	 * @return \OC\User\User[]
253
-	 */
254
-	public function searchDisplayName($pattern, $limit = null, $offset = null) {
255
-		$users = array();
256
-		foreach ($this->backends as $backend) {
257
-			$backendUsers = $backend->getDisplayNames($pattern, $limit, $offset);
258
-			if (is_array($backendUsers)) {
259
-				foreach ($backendUsers as $uid => $displayName) {
260
-					$users[] = $this->getUserObject($uid, $backend);
261
-				}
262
-			}
263
-		}
264
-
265
-		usort($users, function ($a, $b) {
266
-			/**
267
-			 * @var \OC\User\User $a
268
-			 * @var \OC\User\User $b
269
-			 */
270
-			return strcasecmp($a->getDisplayName(), $b->getDisplayName());
271
-		});
272
-		return $users;
273
-	}
274
-
275
-	/**
276
-	 * @param string $uid
277
-	 * @param string $password
278
-	 * @throws \InvalidArgumentException
279
-	 * @return bool|IUser the created user or false
280
-	 */
281
-	public function createUser($uid, $password) {
282
-		if (!$this->verifyUid($uid)) {
283
-			return false;
284
-		}
285
-
286
-		$localBackends = [];
287
-		foreach ($this->backends as $backend) {
288
-			if ($backend instanceof Database) {
289
-				// First check if there is another user backend
290
-				$localBackends[] = $backend;
291
-				continue;
292
-			}
293
-
294
-			if ($backend->implementsActions(Backend::CREATE_USER)) {
295
-				return $this->createUserFromBackend($uid, $password, $backend);
296
-			}
297
-		}
298
-
299
-		foreach ($localBackends as $backend) {
300
-			if ($backend->implementsActions(Backend::CREATE_USER)) {
301
-				return $this->createUserFromBackend($uid, $password, $backend);
302
-			}
303
-		}
304
-
305
-		return false;
306
-	}
307
-
308
-	/**
309
-	 * @param string $uid
310
-	 * @param string $password
311
-	 * @param UserInterface $backend
312
-	 * @return IUser|null
313
-	 * @throws \InvalidArgumentException
314
-	 */
315
-	public function createUserFromBackend($uid, $password, UserInterface $backend) {
316
-		$l = \OC::$server->getL10N('lib');
317
-
318
-		// Check the name for bad characters
319
-		// Allowed are: "a-z", "A-Z", "0-9" and "_.@-'"
320
-		if (preg_match('/[^a-zA-Z0-9 _\.@\-\']/', $uid)) {
321
-			throw new \InvalidArgumentException($l->t('Only the following characters are allowed in a username:'
322
-				. ' "a-z", "A-Z", "0-9", and "_.@-\'"'));
323
-		}
324
-		// No empty username
325
-		if (trim($uid) === '') {
326
-			throw new \InvalidArgumentException($l->t('A valid username must be provided'));
327
-		}
328
-		// No whitespace at the beginning or at the end
329
-		if (trim($uid) !== $uid) {
330
-			throw new \InvalidArgumentException($l->t('Username contains whitespace at the beginning or at the end'));
331
-		}
332
-		// Username only consists of 1 or 2 dots (directory traversal)
333
-		if ($uid === '.' || $uid === '..') {
334
-			throw new \InvalidArgumentException($l->t('Username must not consist of dots only'));
335
-		}
336
-		// No empty password
337
-		if (trim($password) === '') {
338
-			throw new \InvalidArgumentException($l->t('A valid password must be provided'));
339
-		}
340
-
341
-		// Check if user already exists
342
-		if ($this->userExists($uid)) {
343
-			throw new \InvalidArgumentException($l->t('The username is already being used'));
344
-		}
345
-
346
-		$this->emit('\OC\User', 'preCreateUser', [$uid, $password]);
347
-		$state = $backend->createUser($uid, $password);
348
-		if($state === false) {
349
-			throw new \InvalidArgumentException($l->t('Could not create user'));
350
-		}
351
-		$user = $this->getUserObject($uid, $backend);
352
-		if ($user instanceof IUser) {
353
-			$this->emit('\OC\User', 'postCreateUser', [$user, $password]);
354
-		}
355
-		return $user;
356
-	}
357
-
358
-	/**
359
-	 * returns how many users per backend exist (if supported by backend)
360
-	 *
361
-	 * @param boolean $hasLoggedIn when true only users that have a lastLogin
362
-	 *                entry in the preferences table will be affected
363
-	 * @return array|int an array of backend class as key and count number as value
364
-	 *                if $hasLoggedIn is true only an int is returned
365
-	 */
366
-	public function countUsers($hasLoggedIn = false) {
367
-		if ($hasLoggedIn) {
368
-			return $this->countSeenUsers();
369
-		}
370
-		$userCountStatistics = [];
371
-		foreach ($this->backends as $backend) {
372
-			if ($backend->implementsActions(Backend::COUNT_USERS)) {
373
-				$backendUsers = $backend->countUsers();
374
-				if($backendUsers !== false) {
375
-					if($backend instanceof IUserBackend) {
376
-						$name = $backend->getBackendName();
377
-					} else {
378
-						$name = get_class($backend);
379
-					}
380
-					if(isset($userCountStatistics[$name])) {
381
-						$userCountStatistics[$name] += $backendUsers;
382
-					} else {
383
-						$userCountStatistics[$name] = $backendUsers;
384
-					}
385
-				}
386
-			}
387
-		}
388
-		return $userCountStatistics;
389
-	}
390
-
391
-	/**
392
-	 * returns how many users per backend exist in the requested groups (if supported by backend)
393
-	 *
394
-	 * @param IGroup[] $groups an array of gid to search in
395
-	 * @return array|int an array of backend class as key and count number as value
396
-	 *                if $hasLoggedIn is true only an int is returned
397
-	 */
398
-	public function countUsersOfGroups(array $groups) {
399
-		$users = [];
400
-		foreach($groups as $group) {
401
-			$usersIds = array_map(function($user) {
402
-				return $user->getUID();
403
-			}, $group->getUsers());
404
-			$users = array_merge($users, $usersIds);
405
-		}
406
-		return count(array_unique($users));
407
-	}
408
-
409
-	/**
410
-	 * The callback is executed for each user on each backend.
411
-	 * If the callback returns false no further users will be retrieved.
412
-	 *
413
-	 * @param \Closure $callback
414
-	 * @param string $search
415
-	 * @param boolean $onlySeen when true only users that have a lastLogin entry
416
-	 *                in the preferences table will be affected
417
-	 * @since 9.0.0
418
-	 */
419
-	public function callForAllUsers(\Closure $callback, $search = '', $onlySeen = false) {
420
-		if ($onlySeen) {
421
-			$this->callForSeenUsers($callback);
422
-		} else {
423
-			foreach ($this->getBackends() as $backend) {
424
-				$limit = 500;
425
-				$offset = 0;
426
-				do {
427
-					$users = $backend->getUsers($search, $limit, $offset);
428
-					foreach ($users as $uid) {
429
-						if (!$backend->userExists($uid)) {
430
-							continue;
431
-						}
432
-						$user = $this->getUserObject($uid, $backend, false);
433
-						$return = $callback($user);
434
-						if ($return === false) {
435
-							break;
436
-						}
437
-					}
438
-					$offset += $limit;
439
-				} while (count($users) >= $limit);
440
-			}
441
-		}
442
-	}
443
-
444
-	/**
445
-	 * returns how many users are disabled
446
-	 *
447
-	 * @return int
448
-	 * @since 12.0.0
449
-	 */
450
-	public function countDisabledUsers(): int {
451
-		$queryBuilder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
452
-		$queryBuilder->select($queryBuilder->func()->count('*'))
453
-			->from('preferences')
454
-			->where($queryBuilder->expr()->eq('appid', $queryBuilder->createNamedParameter('core')))
455
-			->andWhere($queryBuilder->expr()->eq('configkey', $queryBuilder->createNamedParameter('enabled')))
456
-			->andWhere($queryBuilder->expr()->eq('configvalue', $queryBuilder->createNamedParameter('false'), IQueryBuilder::PARAM_STR));
62
+    /**
63
+     * @var \OCP\UserInterface[] $backends
64
+     */
65
+    private $backends = array();
66
+
67
+    /**
68
+     * @var \OC\User\User[] $cachedUsers
69
+     */
70
+    private $cachedUsers = array();
71
+
72
+    /** @var IConfig */
73
+    private $config;
74
+    /** @var EventDispatcherInterface */
75
+    private $dispatcher;
76
+
77
+    public function __construct(IConfig $config, EventDispatcherInterface $dispatcher) {
78
+        $this->config = $config;
79
+        $this->dispatcher = $dispatcher;
80
+        $cachedUsers = &$this->cachedUsers;
81
+        $this->listen('\OC\User', 'postDelete', function ($user) use (&$cachedUsers) {
82
+            /** @var \OC\User\User $user */
83
+            unset($cachedUsers[$user->getUID()]);
84
+        });
85
+    }
86
+
87
+    /**
88
+     * Get the active backends
89
+     * @return \OCP\UserInterface[]
90
+     */
91
+    public function getBackends() {
92
+        return $this->backends;
93
+    }
94
+
95
+    /**
96
+     * register a user backend
97
+     *
98
+     * @param \OCP\UserInterface $backend
99
+     */
100
+    public function registerBackend($backend) {
101
+        $this->backends[] = $backend;
102
+    }
103
+
104
+    /**
105
+     * remove a user backend
106
+     *
107
+     * @param \OCP\UserInterface $backend
108
+     */
109
+    public function removeBackend($backend) {
110
+        $this->cachedUsers = array();
111
+        if (($i = array_search($backend, $this->backends)) !== false) {
112
+            unset($this->backends[$i]);
113
+        }
114
+    }
115
+
116
+    /**
117
+     * remove all user backends
118
+     */
119
+    public function clearBackends() {
120
+        $this->cachedUsers = array();
121
+        $this->backends = array();
122
+    }
123
+
124
+    /**
125
+     * get a user by user id
126
+     *
127
+     * @param string $uid
128
+     * @return \OC\User\User|null Either the user or null if the specified user does not exist
129
+     */
130
+    public function get($uid) {
131
+        if (is_null($uid) || $uid === '' || $uid === false) {
132
+            return null;
133
+        }
134
+        if (isset($this->cachedUsers[$uid])) { //check the cache first to prevent having to loop over the backends
135
+            return $this->cachedUsers[$uid];
136
+        }
137
+        foreach ($this->backends as $backend) {
138
+            if ($backend->userExists($uid)) {
139
+                return $this->getUserObject($uid, $backend);
140
+            }
141
+        }
142
+        return null;
143
+    }
144
+
145
+    /**
146
+     * get or construct the user object
147
+     *
148
+     * @param string $uid
149
+     * @param \OCP\UserInterface $backend
150
+     * @param bool $cacheUser If false the newly created user object will not be cached
151
+     * @return \OC\User\User
152
+     */
153
+    protected function getUserObject($uid, $backend, $cacheUser = true) {
154
+        if (isset($this->cachedUsers[$uid])) {
155
+            return $this->cachedUsers[$uid];
156
+        }
157
+
158
+        $user = new User($uid, $backend, $this->dispatcher, $this, $this->config);
159
+        if ($cacheUser) {
160
+            $this->cachedUsers[$uid] = $user;
161
+        }
162
+        return $user;
163
+    }
164
+
165
+    /**
166
+     * check if a user exists
167
+     *
168
+     * @param string $uid
169
+     * @return bool
170
+     */
171
+    public function userExists($uid) {
172
+        $user = $this->get($uid);
173
+        return ($user !== null);
174
+    }
175
+
176
+    /**
177
+     * Check if the password is valid for the user
178
+     *
179
+     * @param string $loginName
180
+     * @param string $password
181
+     * @return mixed the User object on success, false otherwise
182
+     */
183
+    public function checkPassword($loginName, $password) {
184
+        $result = $this->checkPasswordNoLogging($loginName, $password);
185
+
186
+        if ($result === false) {
187
+            \OC::$server->getLogger()->warning('Login failed: \''. $loginName .'\' (Remote IP: \''. \OC::$server->getRequest()->getRemoteAddress(). '\')', ['app' => 'core']);
188
+        }
189
+
190
+        return $result;
191
+    }
192
+
193
+    /**
194
+     * Check if the password is valid for the user
195
+     *
196
+     * @internal
197
+     * @param string $loginName
198
+     * @param string $password
199
+     * @return mixed the User object on success, false otherwise
200
+     */
201
+    public function checkPasswordNoLogging($loginName, $password) {
202
+        $loginName = str_replace("\0", '', $loginName);
203
+        $password = str_replace("\0", '', $password);
204
+
205
+        foreach ($this->backends as $backend) {
206
+            if ($backend->implementsActions(Backend::CHECK_PASSWORD)) {
207
+                $uid = $backend->checkPassword($loginName, $password);
208
+                if ($uid !== false) {
209
+                    return $this->getUserObject($uid, $backend);
210
+                }
211
+            }
212
+        }
213
+
214
+        return false;
215
+    }
216
+
217
+    /**
218
+     * search by user id
219
+     *
220
+     * @param string $pattern
221
+     * @param int $limit
222
+     * @param int $offset
223
+     * @return \OC\User\User[]
224
+     */
225
+    public function search($pattern, $limit = null, $offset = null) {
226
+        $users = array();
227
+        foreach ($this->backends as $backend) {
228
+            $backendUsers = $backend->getUsers($pattern, $limit, $offset);
229
+            if (is_array($backendUsers)) {
230
+                foreach ($backendUsers as $uid) {
231
+                    $users[$uid] = $this->getUserObject($uid, $backend);
232
+                }
233
+            }
234
+        }
235
+
236
+        uasort($users, function ($a, $b) {
237
+            /**
238
+             * @var \OC\User\User $a
239
+             * @var \OC\User\User $b
240
+             */
241
+            return strcasecmp($a->getUID(), $b->getUID());
242
+        });
243
+        return $users;
244
+    }
245
+
246
+    /**
247
+     * search by displayName
248
+     *
249
+     * @param string $pattern
250
+     * @param int $limit
251
+     * @param int $offset
252
+     * @return \OC\User\User[]
253
+     */
254
+    public function searchDisplayName($pattern, $limit = null, $offset = null) {
255
+        $users = array();
256
+        foreach ($this->backends as $backend) {
257
+            $backendUsers = $backend->getDisplayNames($pattern, $limit, $offset);
258
+            if (is_array($backendUsers)) {
259
+                foreach ($backendUsers as $uid => $displayName) {
260
+                    $users[] = $this->getUserObject($uid, $backend);
261
+                }
262
+            }
263
+        }
264
+
265
+        usort($users, function ($a, $b) {
266
+            /**
267
+             * @var \OC\User\User $a
268
+             * @var \OC\User\User $b
269
+             */
270
+            return strcasecmp($a->getDisplayName(), $b->getDisplayName());
271
+        });
272
+        return $users;
273
+    }
274
+
275
+    /**
276
+     * @param string $uid
277
+     * @param string $password
278
+     * @throws \InvalidArgumentException
279
+     * @return bool|IUser the created user or false
280
+     */
281
+    public function createUser($uid, $password) {
282
+        if (!$this->verifyUid($uid)) {
283
+            return false;
284
+        }
285
+
286
+        $localBackends = [];
287
+        foreach ($this->backends as $backend) {
288
+            if ($backend instanceof Database) {
289
+                // First check if there is another user backend
290
+                $localBackends[] = $backend;
291
+                continue;
292
+            }
293
+
294
+            if ($backend->implementsActions(Backend::CREATE_USER)) {
295
+                return $this->createUserFromBackend($uid, $password, $backend);
296
+            }
297
+        }
298
+
299
+        foreach ($localBackends as $backend) {
300
+            if ($backend->implementsActions(Backend::CREATE_USER)) {
301
+                return $this->createUserFromBackend($uid, $password, $backend);
302
+            }
303
+        }
304
+
305
+        return false;
306
+    }
307
+
308
+    /**
309
+     * @param string $uid
310
+     * @param string $password
311
+     * @param UserInterface $backend
312
+     * @return IUser|null
313
+     * @throws \InvalidArgumentException
314
+     */
315
+    public function createUserFromBackend($uid, $password, UserInterface $backend) {
316
+        $l = \OC::$server->getL10N('lib');
317
+
318
+        // Check the name for bad characters
319
+        // Allowed are: "a-z", "A-Z", "0-9" and "_.@-'"
320
+        if (preg_match('/[^a-zA-Z0-9 _\.@\-\']/', $uid)) {
321
+            throw new \InvalidArgumentException($l->t('Only the following characters are allowed in a username:'
322
+                . ' "a-z", "A-Z", "0-9", and "_.@-\'"'));
323
+        }
324
+        // No empty username
325
+        if (trim($uid) === '') {
326
+            throw new \InvalidArgumentException($l->t('A valid username must be provided'));
327
+        }
328
+        // No whitespace at the beginning or at the end
329
+        if (trim($uid) !== $uid) {
330
+            throw new \InvalidArgumentException($l->t('Username contains whitespace at the beginning or at the end'));
331
+        }
332
+        // Username only consists of 1 or 2 dots (directory traversal)
333
+        if ($uid === '.' || $uid === '..') {
334
+            throw new \InvalidArgumentException($l->t('Username must not consist of dots only'));
335
+        }
336
+        // No empty password
337
+        if (trim($password) === '') {
338
+            throw new \InvalidArgumentException($l->t('A valid password must be provided'));
339
+        }
340
+
341
+        // Check if user already exists
342
+        if ($this->userExists($uid)) {
343
+            throw new \InvalidArgumentException($l->t('The username is already being used'));
344
+        }
345
+
346
+        $this->emit('\OC\User', 'preCreateUser', [$uid, $password]);
347
+        $state = $backend->createUser($uid, $password);
348
+        if($state === false) {
349
+            throw new \InvalidArgumentException($l->t('Could not create user'));
350
+        }
351
+        $user = $this->getUserObject($uid, $backend);
352
+        if ($user instanceof IUser) {
353
+            $this->emit('\OC\User', 'postCreateUser', [$user, $password]);
354
+        }
355
+        return $user;
356
+    }
357
+
358
+    /**
359
+     * returns how many users per backend exist (if supported by backend)
360
+     *
361
+     * @param boolean $hasLoggedIn when true only users that have a lastLogin
362
+     *                entry in the preferences table will be affected
363
+     * @return array|int an array of backend class as key and count number as value
364
+     *                if $hasLoggedIn is true only an int is returned
365
+     */
366
+    public function countUsers($hasLoggedIn = false) {
367
+        if ($hasLoggedIn) {
368
+            return $this->countSeenUsers();
369
+        }
370
+        $userCountStatistics = [];
371
+        foreach ($this->backends as $backend) {
372
+            if ($backend->implementsActions(Backend::COUNT_USERS)) {
373
+                $backendUsers = $backend->countUsers();
374
+                if($backendUsers !== false) {
375
+                    if($backend instanceof IUserBackend) {
376
+                        $name = $backend->getBackendName();
377
+                    } else {
378
+                        $name = get_class($backend);
379
+                    }
380
+                    if(isset($userCountStatistics[$name])) {
381
+                        $userCountStatistics[$name] += $backendUsers;
382
+                    } else {
383
+                        $userCountStatistics[$name] = $backendUsers;
384
+                    }
385
+                }
386
+            }
387
+        }
388
+        return $userCountStatistics;
389
+    }
390
+
391
+    /**
392
+     * returns how many users per backend exist in the requested groups (if supported by backend)
393
+     *
394
+     * @param IGroup[] $groups an array of gid to search in
395
+     * @return array|int an array of backend class as key and count number as value
396
+     *                if $hasLoggedIn is true only an int is returned
397
+     */
398
+    public function countUsersOfGroups(array $groups) {
399
+        $users = [];
400
+        foreach($groups as $group) {
401
+            $usersIds = array_map(function($user) {
402
+                return $user->getUID();
403
+            }, $group->getUsers());
404
+            $users = array_merge($users, $usersIds);
405
+        }
406
+        return count(array_unique($users));
407
+    }
408
+
409
+    /**
410
+     * The callback is executed for each user on each backend.
411
+     * If the callback returns false no further users will be retrieved.
412
+     *
413
+     * @param \Closure $callback
414
+     * @param string $search
415
+     * @param boolean $onlySeen when true only users that have a lastLogin entry
416
+     *                in the preferences table will be affected
417
+     * @since 9.0.0
418
+     */
419
+    public function callForAllUsers(\Closure $callback, $search = '', $onlySeen = false) {
420
+        if ($onlySeen) {
421
+            $this->callForSeenUsers($callback);
422
+        } else {
423
+            foreach ($this->getBackends() as $backend) {
424
+                $limit = 500;
425
+                $offset = 0;
426
+                do {
427
+                    $users = $backend->getUsers($search, $limit, $offset);
428
+                    foreach ($users as $uid) {
429
+                        if (!$backend->userExists($uid)) {
430
+                            continue;
431
+                        }
432
+                        $user = $this->getUserObject($uid, $backend, false);
433
+                        $return = $callback($user);
434
+                        if ($return === false) {
435
+                            break;
436
+                        }
437
+                    }
438
+                    $offset += $limit;
439
+                } while (count($users) >= $limit);
440
+            }
441
+        }
442
+    }
443
+
444
+    /**
445
+     * returns how many users are disabled
446
+     *
447
+     * @return int
448
+     * @since 12.0.0
449
+     */
450
+    public function countDisabledUsers(): int {
451
+        $queryBuilder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
452
+        $queryBuilder->select($queryBuilder->func()->count('*'))
453
+            ->from('preferences')
454
+            ->where($queryBuilder->expr()->eq('appid', $queryBuilder->createNamedParameter('core')))
455
+            ->andWhere($queryBuilder->expr()->eq('configkey', $queryBuilder->createNamedParameter('enabled')))
456
+            ->andWhere($queryBuilder->expr()->eq('configvalue', $queryBuilder->createNamedParameter('false'), IQueryBuilder::PARAM_STR));
457 457
 
458 458
 		
459
-		$result = $queryBuilder->execute();
460
-		$count = $result->fetchColumn();
461
-		$result->closeCursor();
459
+        $result = $queryBuilder->execute();
460
+        $count = $result->fetchColumn();
461
+        $result->closeCursor();
462 462
 		
463
-		if ($count !== false) {
464
-			$count = (int)$count;
465
-		} else {
466
-			$count = 0;
467
-		}
468
-
469
-		return $count;
470
-	}
471
-
472
-	/**
473
-	 * returns how many users are disabled in the requested groups
474
-	 *
475
-	 * @param array $groups groupids to search
476
-	 * @return int
477
-	 * @since 14.0.0
478
-	 */
479
-	public function countDisabledUsersOfGroups(array $groups): int {
480
-		$queryBuilder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
481
-		$queryBuilder->select($queryBuilder->createFunction('COUNT(DISTINCT ' . $queryBuilder->getColumnName('uid') . ')'))
482
-			->from('preferences', 'p')
483
-			->innerJoin('p', 'group_user', 'g', $queryBuilder->expr()->eq('p.userid', 'g.uid'))
484
-			->where($queryBuilder->expr()->eq('appid', $queryBuilder->createNamedParameter('core')))
485
-			->andWhere($queryBuilder->expr()->eq('configkey', $queryBuilder->createNamedParameter('enabled')))
486
-			->andWhere($queryBuilder->expr()->eq('configvalue', $queryBuilder->createNamedParameter('false'), IQueryBuilder::PARAM_STR))
487
-			->andWhere($queryBuilder->expr()->in('gid', $queryBuilder->createNamedParameter($groups, IQueryBuilder::PARAM_STR_ARRAY)));
488
-
489
-		$result = $queryBuilder->execute();
490
-		$count = $result->fetchColumn();
491
-		$result->closeCursor();
463
+        if ($count !== false) {
464
+            $count = (int)$count;
465
+        } else {
466
+            $count = 0;
467
+        }
468
+
469
+        return $count;
470
+    }
471
+
472
+    /**
473
+     * returns how many users are disabled in the requested groups
474
+     *
475
+     * @param array $groups groupids to search
476
+     * @return int
477
+     * @since 14.0.0
478
+     */
479
+    public function countDisabledUsersOfGroups(array $groups): int {
480
+        $queryBuilder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
481
+        $queryBuilder->select($queryBuilder->createFunction('COUNT(DISTINCT ' . $queryBuilder->getColumnName('uid') . ')'))
482
+            ->from('preferences', 'p')
483
+            ->innerJoin('p', 'group_user', 'g', $queryBuilder->expr()->eq('p.userid', 'g.uid'))
484
+            ->where($queryBuilder->expr()->eq('appid', $queryBuilder->createNamedParameter('core')))
485
+            ->andWhere($queryBuilder->expr()->eq('configkey', $queryBuilder->createNamedParameter('enabled')))
486
+            ->andWhere($queryBuilder->expr()->eq('configvalue', $queryBuilder->createNamedParameter('false'), IQueryBuilder::PARAM_STR))
487
+            ->andWhere($queryBuilder->expr()->in('gid', $queryBuilder->createNamedParameter($groups, IQueryBuilder::PARAM_STR_ARRAY)));
488
+
489
+        $result = $queryBuilder->execute();
490
+        $count = $result->fetchColumn();
491
+        $result->closeCursor();
492 492
 		
493
-		if ($count !== false) {
494
-			$count = (int)$count;
495
-		} else {
496
-			$count = 0;
497
-		}
498
-
499
-		return $count;
500
-	}
501
-
502
-	/**
503
-	 * returns how many users have logged in once
504
-	 *
505
-	 * @return int
506
-	 * @since 11.0.0
507
-	 */
508
-	public function countSeenUsers() {
509
-		$queryBuilder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
510
-		$queryBuilder->select($queryBuilder->func()->count('*'))
511
-			->from('preferences')
512
-			->where($queryBuilder->expr()->eq('appid', $queryBuilder->createNamedParameter('login')))
513
-			->andWhere($queryBuilder->expr()->eq('configkey', $queryBuilder->createNamedParameter('lastLogin')))
514
-			->andWhere($queryBuilder->expr()->isNotNull('configvalue'));
515
-
516
-		$query = $queryBuilder->execute();
517
-
518
-		$result = (int)$query->fetchColumn();
519
-		$query->closeCursor();
520
-
521
-		return $result;
522
-	}
523
-
524
-	/**
525
-	 * @param \Closure $callback
526
-	 * @since 11.0.0
527
-	 */
528
-	public function callForSeenUsers(\Closure $callback) {
529
-		$limit = 1000;
530
-		$offset = 0;
531
-		do {
532
-			$userIds = $this->getSeenUserIds($limit, $offset);
533
-			$offset += $limit;
534
-			foreach ($userIds as $userId) {
535
-				foreach ($this->backends as $backend) {
536
-					if ($backend->userExists($userId)) {
537
-						$user = $this->getUserObject($userId, $backend, false);
538
-						$return = $callback($user);
539
-						if ($return === false) {
540
-							return;
541
-						}
542
-						break;
543
-					}
544
-				}
545
-			}
546
-		} while (count($userIds) >= $limit);
547
-	}
548
-
549
-	/**
550
-	 * Getting all userIds that have a listLogin value requires checking the
551
-	 * value in php because on oracle you cannot use a clob in a where clause,
552
-	 * preventing us from doing a not null or length(value) > 0 check.
553
-	 *
554
-	 * @param int $limit
555
-	 * @param int $offset
556
-	 * @return string[] with user ids
557
-	 */
558
-	private function getSeenUserIds($limit = null, $offset = null) {
559
-		$queryBuilder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
560
-		$queryBuilder->select(['userid'])
561
-			->from('preferences')
562
-			->where($queryBuilder->expr()->eq(
563
-				'appid', $queryBuilder->createNamedParameter('login'))
564
-			)
565
-			->andWhere($queryBuilder->expr()->eq(
566
-				'configkey', $queryBuilder->createNamedParameter('lastLogin'))
567
-			)
568
-			->andWhere($queryBuilder->expr()->isNotNull('configvalue')
569
-			);
570
-
571
-		if ($limit !== null) {
572
-			$queryBuilder->setMaxResults($limit);
573
-		}
574
-		if ($offset !== null) {
575
-			$queryBuilder->setFirstResult($offset);
576
-		}
577
-		$query = $queryBuilder->execute();
578
-		$result = [];
579
-
580
-		while ($row = $query->fetch()) {
581
-			$result[] = $row['userid'];
582
-		}
583
-
584
-		$query->closeCursor();
585
-
586
-		return $result;
587
-	}
588
-
589
-	/**
590
-	 * @param string $email
591
-	 * @return IUser[]
592
-	 * @since 9.1.0
593
-	 */
594
-	public function getByEmail($email) {
595
-		$userIds = $this->config->getUsersForUserValueCaseInsensitive('settings', 'email', $email);
596
-
597
-		$users = array_map(function($uid) {
598
-			return $this->get($uid);
599
-		}, $userIds);
600
-
601
-		return array_values(array_filter($users, function($u) {
602
-			return ($u instanceof IUser);
603
-		}));
604
-	}
605
-
606
-	private function verifyUid(string $uid): bool {
607
-		$appdata = 'appdata_' . $this->config->getSystemValueString('instanceid');
608
-
609
-		if ($uid === '.htaccess' || $uid === 'files_external' || $uid === '.ocdata' || $uid === 'owncloud.log' || $uid === 'nextcloud.log' || $uid === $appdata) {
610
-			return false;
611
-		}
612
-
613
-		return true;
614
-	}
493
+        if ($count !== false) {
494
+            $count = (int)$count;
495
+        } else {
496
+            $count = 0;
497
+        }
498
+
499
+        return $count;
500
+    }
501
+
502
+    /**
503
+     * returns how many users have logged in once
504
+     *
505
+     * @return int
506
+     * @since 11.0.0
507
+     */
508
+    public function countSeenUsers() {
509
+        $queryBuilder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
510
+        $queryBuilder->select($queryBuilder->func()->count('*'))
511
+            ->from('preferences')
512
+            ->where($queryBuilder->expr()->eq('appid', $queryBuilder->createNamedParameter('login')))
513
+            ->andWhere($queryBuilder->expr()->eq('configkey', $queryBuilder->createNamedParameter('lastLogin')))
514
+            ->andWhere($queryBuilder->expr()->isNotNull('configvalue'));
515
+
516
+        $query = $queryBuilder->execute();
517
+
518
+        $result = (int)$query->fetchColumn();
519
+        $query->closeCursor();
520
+
521
+        return $result;
522
+    }
523
+
524
+    /**
525
+     * @param \Closure $callback
526
+     * @since 11.0.0
527
+     */
528
+    public function callForSeenUsers(\Closure $callback) {
529
+        $limit = 1000;
530
+        $offset = 0;
531
+        do {
532
+            $userIds = $this->getSeenUserIds($limit, $offset);
533
+            $offset += $limit;
534
+            foreach ($userIds as $userId) {
535
+                foreach ($this->backends as $backend) {
536
+                    if ($backend->userExists($userId)) {
537
+                        $user = $this->getUserObject($userId, $backend, false);
538
+                        $return = $callback($user);
539
+                        if ($return === false) {
540
+                            return;
541
+                        }
542
+                        break;
543
+                    }
544
+                }
545
+            }
546
+        } while (count($userIds) >= $limit);
547
+    }
548
+
549
+    /**
550
+     * Getting all userIds that have a listLogin value requires checking the
551
+     * value in php because on oracle you cannot use a clob in a where clause,
552
+     * preventing us from doing a not null or length(value) > 0 check.
553
+     *
554
+     * @param int $limit
555
+     * @param int $offset
556
+     * @return string[] with user ids
557
+     */
558
+    private function getSeenUserIds($limit = null, $offset = null) {
559
+        $queryBuilder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
560
+        $queryBuilder->select(['userid'])
561
+            ->from('preferences')
562
+            ->where($queryBuilder->expr()->eq(
563
+                'appid', $queryBuilder->createNamedParameter('login'))
564
+            )
565
+            ->andWhere($queryBuilder->expr()->eq(
566
+                'configkey', $queryBuilder->createNamedParameter('lastLogin'))
567
+            )
568
+            ->andWhere($queryBuilder->expr()->isNotNull('configvalue')
569
+            );
570
+
571
+        if ($limit !== null) {
572
+            $queryBuilder->setMaxResults($limit);
573
+        }
574
+        if ($offset !== null) {
575
+            $queryBuilder->setFirstResult($offset);
576
+        }
577
+        $query = $queryBuilder->execute();
578
+        $result = [];
579
+
580
+        while ($row = $query->fetch()) {
581
+            $result[] = $row['userid'];
582
+        }
583
+
584
+        $query->closeCursor();
585
+
586
+        return $result;
587
+    }
588
+
589
+    /**
590
+     * @param string $email
591
+     * @return IUser[]
592
+     * @since 9.1.0
593
+     */
594
+    public function getByEmail($email) {
595
+        $userIds = $this->config->getUsersForUserValueCaseInsensitive('settings', 'email', $email);
596
+
597
+        $users = array_map(function($uid) {
598
+            return $this->get($uid);
599
+        }, $userIds);
600
+
601
+        return array_values(array_filter($users, function($u) {
602
+            return ($u instanceof IUser);
603
+        }));
604
+    }
605
+
606
+    private function verifyUid(string $uid): bool {
607
+        $appdata = 'appdata_' . $this->config->getSystemValueString('instanceid');
608
+
609
+        if ($uid === '.htaccess' || $uid === 'files_external' || $uid === '.ocdata' || $uid === 'owncloud.log' || $uid === 'nextcloud.log' || $uid === $appdata) {
610
+            return false;
611
+        }
612
+
613
+        return true;
614
+    }
615 615
 }
Please login to merge, or discard this patch.