ILIAS  release_8 Revision v8.24
class.ilUserQuery.php
Go to the documentation of this file.
1<?php
2
25{
26 public const DEFAULT_ORDER_FIELD = 'login';
27
29 private string $order_dir = 'asc';
30 private int $offset = 0;
31 private int $limit = 50;
32 private string $text_filter = '';
33 private string $activation = '';
34 private ?ilDateTime $last_login = null;
35 private bool $limited_access = false;
36 private bool $no_courses = false;
37 private bool $no_groups = false;
38 private int $crs_grp = 0;
39 private int $role = 0;
40 private ?array $user_folder = null; // Missing array type.
41 private array $additional_fields = array(); // Missing array type.
42 private array $users = array(); // Missing array type.
43 private string $first_letter = '';
44 private bool $has_access = false;
45 private string $authentication_method = '';
46 protected array $udf_filter = array(); // Missing array type.
48 private array $default_fields = array(
49 "usr_id",
50 "login",
51 "firstname",
52 "lastname",
53 "email",
54 "second_email",
55 "time_limit_until",
56 "time_limit_unlimited",
57 "time_limit_owner",
58 "last_login",
59 "active"
60 );
61
62 public function __construct()
63 {
64 }
65
70 public function setUdfFilter(array $a_val): void // Missing array type.
71 {
72 $valid_udfs = [];
73
74 $definitions = \ilUserDefinedFields::_getInstance()->getDefinitions();
75 foreach ($a_val as $udf_name => $udf_value) {
76 [$udf_string, $udf_id] = explode('_', $udf_name);
77 if (array_key_exists((int) $udf_id, $definitions)) {
78 $valid_udfs[$udf_name] = $udf_value;
79 }
80 }
81 $this->udf_filter = $valid_udfs;
82 }
83
88 public function getUdfFilter(): array // Missing array type.
89 {
90 return $this->udf_filter;
91 }
92
97 public function setOrderField(string $a_order): void
98 {
99 $this->order_field = $a_order;
100 }
101
107 public function setOrderDirection(string $a_dir): void
108 {
109 $this->order_dir = $a_dir;
110 }
111
112 public function setOffset(int $a_offset): void
113 {
114 $this->offset = $a_offset;
115 }
116
117 public function setLimit(int $a_limit): void
118 {
119 $this->limit = $a_limit;
120 }
121
125 public function setTextFilter(string $a_filter): void
126 {
127 $this->text_filter = $a_filter;
128 }
129
134 public function setActionFilter(string $a_activation): void
135 {
136 $this->activation = $a_activation;
137 }
138
142 public function setLastLogin(ilDateTime $dt = null): void
143 {
144 $this->last_login = $dt;
145 }
146
150 public function setLimitedAccessFilter(bool $a_status): void
151 {
152 $this->limited_access = $a_status;
153 }
154
155 public function setNoCourseFilter(bool $a_no_course): void
156 {
157 $this->no_courses = $a_no_course;
158 }
159
160 public function setNoGroupFilter(bool $a_no_group): void
161 {
162 $this->no_groups = $a_no_group;
163 }
164
169 public function setCourseGroupFilter(int $a_cg_id): void
170 {
171 $this->crs_grp = $a_cg_id;
172 }
173
178 public function setRoleFilter(int $a_role_id): void
179 {
180 $this->role = $a_role_id;
181 }
182
187 public function setUserFolder(?array $a_fold_id): void // Missing array type.
188 {
189 $this->user_folder = $a_fold_id;
190 }
191
195 public function setAdditionalFields(array $a_add): void // Missing array type.
196 {
197 $this->additional_fields = $a_add;
198 }
199
203 public function setUserFilter(array $a_filter): void // Missing array type.
204 {
205 $this->users = $a_filter;
206 }
207
211 public function setFirstLetterLastname(string $a_fll): void
212 {
213 $this->first_letter = $a_fll;
214 }
215
219 public function setAccessFilter(bool $a_access): void
220 {
221 $this->has_access = $a_access;
222 }
223
228 public function setAuthenticationFilter(string $a_authentication): void
229 {
230 $this->authentication_method = $a_authentication;
231 }
232
237 public function query(): array
238 {
239 global $DIC;
240
241 $ilDB = $DIC['ilDB'];
242
243
244 $udf_fields = array();
245 $usr_ids = [];
246
247 $join = "";
248
249 if (is_array($this->additional_fields)) {
250 foreach ($this->additional_fields as $f) {
251 if (!in_array($f, $this->default_fields)) {
252 if ($f === "online_time") {
253 $this->default_fields[] = "ut_online.online_time";
254 $join = " LEFT JOIN ut_online ON (usr_data.usr_id = ut_online.usr_id) ";
255 } elseif (substr($f, 0, 4) === "udf_") {
256 $udf_fields[] = (int) substr($f, 4);
257 } else {
258 $this->default_fields[] = $f;
259 }
260 }
261 }
262 }
263
264 // if udf fields are involved we need the definitions
265 $udf_def = array();
266 if (count($udf_fields) > 0) {
267 $udf_def = ilUserDefinedFields::_getInstance()->getDefinitions();
268 }
269
270 // join udf table
271 foreach ($udf_fields as $id) {
272 $udf_table = ($udf_def[$id]["field_type"] != UDF_TYPE_WYSIWYG)
273 ? "udf_text"
274 : "udf_clob";
275 $join .= " LEFT JOIN " . $udf_table . " ud_" . $id . " ON (ud_" . $id . ".field_id=" . $ilDB->quote($id) . " AND ud_" . $id . ".usr_id = usr_data.usr_id) ";
276 }
277
278 // count query
279 $count_query = "SELECT count(usr_data.usr_id) cnt" .
280 " FROM usr_data";
281
282 $all_multi_fields = array("interests_general", "interests_help_offered", "interests_help_looking");
283 $multi_fields = array();
284
285 $sql_fields = array();
286 foreach ($this->default_fields as $idx => $field) {
287 if (!$field) {
288 continue;
289 }
290
291 if (in_array($field, $all_multi_fields)) {
292 $multi_fields[] = $field;
293 } elseif (strpos($field, ".") === false) {
294 $sql_fields[] = "usr_data." . $field;
295 } else {
296 $sql_fields[] = $field;
297 }
298 }
299
300 // udf fields
301 foreach ($udf_fields as $id) {
302 $sql_fields[] = "ud_" . $id . ".value udf_" . $id;
303 }
304
305 // basic query
306 $query = "SELECT " . implode(",", $sql_fields) .
307 " FROM usr_data" .
308 $join;
309
310 $count_query .= " " . $join;
311
312 // filter
313 $query .= " WHERE usr_data.usr_id <> " . $ilDB->quote(ANONYMOUS_USER_ID, "integer");
314
315 // User filter
316 $count_query .= " WHERE 1 = 1 ";
317 $count_user_filter = "usr_data.usr_id != " . $ilDB->quote(ANONYMOUS_USER_ID, "integer");
318 if ($this->users and is_array(($this->users))) {
319 $query .= ' AND ' . $ilDB->in('usr_data.usr_id', $this->users, false, 'integer');
320 $count_user_filter = $ilDB->in('usr_data.usr_id', $this->users, false, 'integer');
321 }
322
323 $count_query .= " AND " . $count_user_filter . " ";
324 $where = " AND";
325
326 if ($this->first_letter != "") {
327 $add = $where . " (" . $ilDB->upper($ilDB->substr("usr_data.lastname", 1, 1)) . " = " . $ilDB->upper($ilDB->quote($this->first_letter, "text")) . ") ";
328 $query .= $add;
329 $count_query .= $add;
330 $where = " AND";
331 }
332
333 if ($this->text_filter != "") { // email, name, login
334 $add = $where . " (" . $ilDB->like("usr_data.login", "text", "%" . $this->text_filter . "%") . " " .
335 "OR " . $ilDB->like("usr_data.firstname", "text", "%" . $this->text_filter . "%") . " " .
336 "OR " . $ilDB->like("usr_data.lastname", "text", "%" . $this->text_filter . "%") . " " .
337 "OR " . $ilDB->like("usr_data.second_email", "text", "%" . $this->text_filter . "%") . " " .
338 "OR " . $ilDB->like("usr_data.email", "text", "%" . $this->text_filter . "%") . ") ";
339 $query .= $add;
340 $count_query .= $add;
341 $where = " AND";
342 }
343
344 if ($this->activation != "") { // activation
345 if ($this->activation === "inactive") {
346 $add = $where . " usr_data.active = " . $ilDB->quote(0, "integer") . " ";
347 } else {
348 $add = $where . " usr_data.active = " . $ilDB->quote(1, "integer") . " ";
349 }
350 $query .= $add;
351 $count_query .= $add;
352 $where = " AND";
353 }
354
355 if ($this->last_login instanceof ilDateTime) { // last login
356 if (ilDateTime::_before($this->last_login, new ilDateTime(time() + (60 * 60 * 24), IL_CAL_UNIX), IL_CAL_DAY)) {
357 $add = $where . " usr_data.last_login < " .
358 $ilDB->quote($this->last_login->get(IL_CAL_DATETIME), "timestamp");
359 $query .= $add;
360 $count_query .= $add;
361 $where = " AND";
362 }
363 }
364 if ($this->limited_access) { // limited access
365 $add = $where . " usr_data.time_limit_unlimited= " . $ilDB->quote(0, "integer");
366 $query .= $add;
367 $count_query .= $add;
368 $where = " AND";
369 }
370
371 // udf filter
372 foreach ($this->getUdfFilter() as $k => $f) {
373 if ($f != "") {
374 $udf_id = explode("_", $k)[1];
375 if ($udf_def[$udf_id]["field_type"] == UDF_TYPE_TEXT) {
376 $add = $where . " " . $ilDB->like("ud_" . $udf_id . ".value", "text", "%" . $f . "%");
377 } else {
378 $add = $where . " ud_" . $udf_id . ".value = " . $ilDB->quote($f, "text");
379 }
380 $query .= $add;
381 $count_query .= $add;
382 $where = " AND";
383 }
384 }
385
386 if ($this->has_access) { //user is limited but has access
387 $unlimited = "time_limit_unlimited = " . $ilDB->quote(1, 'integer');
388 $from = "time_limit_from < " . $ilDB->quote(time(), 'integer');
389 $until = "time_limit_until > " . $ilDB->quote(time(), 'integer');
390
391 $add = $where . ' (' . $unlimited . ' OR (' . $from . ' AND ' . $until . '))';
392 $query .= $add;
393 $count_query .= $add;
394 $where = " AND";
395 }
396 if ($this->no_courses) { // no courses assigned
397 $add = $where . " usr_data.usr_id NOT IN (" .
398 "SELECT DISTINCT ud.usr_id " .
399 "FROM usr_data ud join rbac_ua ON (ud.usr_id = rbac_ua.usr_id) " .
400 "JOIN object_data od ON (rbac_ua.rol_id = od.obj_id) " .
401 "JOIN rbac_fa ON (rbac_ua.rol_id = rbac_fa.rol_id) " .
402 "JOIN tree ON (rbac_fa.parent = tree.child) " .
403 "WHERE od.title LIKE 'il_crs_%' " .
404 "AND rbac_fa.assign = 'y' " .
405 "AND tree.tree > 0)";
406 $query .= $add;
407 $count_query .= $add;
408 $where = " AND";
409 }
410 if ($this->no_groups) { // no groups assigned
411 $add = $where . " usr_data.usr_id NOT IN (" .
412 "SELECT DISTINCT ud.usr_id " .
413 "FROM usr_data ud join rbac_ua ON (ud.usr_id = rbac_ua.usr_id) " .
414 "JOIN object_data od ON (rbac_ua.rol_id = od.obj_id) " .
415 "JOIN rbac_fa ON (rbac_ua.rol_id = rbac_fa.rol_id) " .
416 "JOIN tree ON (rbac_fa.parent = tree.child) " .
417 "WHERE od.title LIKE 'il_grp_%' " .
418 "AND rbac_fa.assign = 'y' " .
419 "AND tree.tree > 0)";
420 $query .= $add;
421 $count_query .= $add;
422 $where = " AND";
423 }
424 if ($this->crs_grp > 0) { // members of course/group
425 $cgtype = ilObject::_lookupType($this->crs_grp, true);
426 $add = $where . " usr_data.usr_id IN (" .
427 "SELECT DISTINCT ud.usr_id " .
428 "FROM usr_data ud join rbac_ua ON (ud.usr_id = rbac_ua.usr_id) " .
429 "JOIN object_data od ON (rbac_ua.rol_id = od.obj_id) " .
430 "WHERE od.title = " . $ilDB->quote("il_" . $cgtype . "_member_" . $this->crs_grp, "text") . ")";
431 $query .= $add;
432 $count_query .= $add;
433 $where = " AND";
434 }
435 if ($this->role > 0) { // global role
436 $add = $where . " usr_data.usr_id IN (" .
437 "SELECT DISTINCT ud.usr_id " .
438 "FROM usr_data ud join rbac_ua ON (ud.usr_id = rbac_ua.usr_id) " .
439 "WHERE rbac_ua.rol_id = " . $ilDB->quote($this->role, "integer") . ")";
440 $query .= $add;
441 $count_query .= $add;
442 $where = " AND";
443 }
444
445 if ($this->user_folder) {
446 $add = $where . " " . $ilDB->in('usr_data.time_limit_owner', $this->user_folder, false, 'integer');
447 $query .= $add;
448 $count_query .= $add;
449 $where = " AND";
450 }
451
452 if ($this->authentication_method != "") { // authentication
453 $add = $where . " usr_data.auth_mode = " . $ilDB->quote($this->authentication_method, "text") . " ";
454 $query .= $add;
455 $count_query .= $add;
456 $where = " AND";
457 }
458
459 // order by
460 switch ($this->order_field) {
461 case "access_until":
462 if ($this->order_dir === "desc") {
463 $query .= " ORDER BY usr_data.active DESC, usr_data.time_limit_unlimited DESC, usr_data.time_limit_until DESC";
464 } else {
465 $query .= " ORDER BY usr_data.active ASC, usr_data.time_limit_unlimited ASC, usr_data.time_limit_until ASC";
466 }
467 break;
468
469 case "online_time":
470 if ($this->order_dir === "desc") {
471 $query .= " ORDER BY ut_online.online_time DESC";
472 } else {
473 $query .= " ORDER BY ut_online.online_time ASC";
474 }
475 break;
476
477 default:
478 if ($this->order_dir !== "asc" && $this->order_dir !== "desc") {
479 $this->order_dir = "asc";
480 }
481 if (substr($this->order_field, 0, 4) === "udf_") {
482 // #25311 check if order field is in field list
483 if (is_array($this->getUdfFilter()) && array_key_exists($this->order_field, $this->getUdfFilter())) {
484 $query .= " ORDER BY ud_" . ((int) substr($this->order_field, 4)) . ".value " . strtoupper($this->order_dir);
485 } else {
486 $query .= ' ORDER BY ' . self::DEFAULT_ORDER_FIELD . ' ' . strtoupper($this->order_dir);
487 }
488 } else {
489 if (!in_array($this->order_field, $this->default_fields)) {
490 $this->order_field = "login";
491 }
492 $query .= " ORDER BY usr_data." . $this->order_field . " " . strtoupper($this->order_dir);
493 }
494 break;
495 }
496
497 // count query
498 $set = $ilDB->query($count_query);
499 $cnt = 0;
500 if ($rec = $ilDB->fetchAssoc($set)) {
501 $cnt = $rec["cnt"];
502 }
503
506
507 // #9866: validate offset against rowcount
508 if ($offset >= $cnt) {
509 $offset = 0;
510 }
511
512 $ilDB->setLimit($limit, $offset);
513
514 if (count($multi_fields)) {
515 $usr_ids = array();
516 }
517
518 // set query
519 $set = $ilDB->query($query);
520 $result = array();
521
522 while ($rec = $ilDB->fetchAssoc($set)) {
523 $result[] = $rec;
524 if (count($multi_fields)) {
525 $usr_ids[] = (int) $rec["usr_id"];
526 }
527 }
528
529 // add multi-field-values to user-data
530 if (count($multi_fields) && count($usr_ids)) {
531 $usr_multi = array();
532 $set = $ilDB->query("SELECT * FROM usr_data_multi" .
533 " WHERE " . $ilDB->in("usr_id", $usr_ids, "", "integer"));
534 while ($row = $ilDB->fetchAssoc($set)) {
535 $usr_multi[(int) $row["usr_id"]][$row["field_id"]][] = $row["value"];
536 }
537 foreach ($result as $idx => $item) {
538 if (isset($usr_multi[$item["usr_id"]])) {
539 $result[$idx] = array_merge($item, $usr_multi[(int) $item["usr_id"]]);
540 }
541 }
542 }
543 return array("cnt" => $cnt, "set" => $result);
544 }
545
546
551 public static function getUserListData(
552 string $a_order_field,
553 string $a_order_dir,
554 int $a_offset,
555 int $a_limit,
556 string $a_string_filter = "",
557 string $a_activation_filter = "",
558 ?ilDateTime $a_last_login_filter = null,
559 bool $a_limited_access_filter = false,
560 bool $a_no_courses_filter = false,
561 int $a_course_group_filter = 0,
562 int $a_role_filter = 0,
563 array $a_user_folder_filter = null,
564 array $a_additional_fields = null,
565 array $a_user_filter = null,
566 string $a_first_letter = "",
567 string $a_authentication_filter = ""
568 ): array {
569 $query = new ilUserQuery();
570 $query->setOrderField($a_order_field);
571 $query->setOrderDirection($a_order_dir);
572 $query->setOffset($a_offset);
573 $query->setLimit($a_limit);
574 $query->setTextFilter($a_string_filter);
575 $query->setActionFilter($a_activation_filter);
576 $query->setLastLogin($a_last_login_filter);
577 $query->setLimitedAccessFilter($a_limited_access_filter);
578 $query->setNoCourseFilter($a_no_courses_filter);
579 $query->setCourseGroupFilter($a_course_group_filter);
580 $query->setRoleFilter($a_role_filter);
581 $query->setUserFolder($a_user_folder_filter);
582 $query->setAdditionalFields($a_additional_fields ?? []);
583 $query->setUserFilter($a_user_filter ?? []);
584 $query->setFirstLetterLastname($a_first_letter);
585 $query->setAuthenticationFilter($a_authentication_filter);
586 return $query->query();
587 }
588}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
const IL_CAL_UNIX
const IL_CAL_DATETIME
const IL_CAL_DAY
const UDF_TYPE_WYSIWYG
const UDF_TYPE_TEXT
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
@classDescription Date and time handling
static _before(ilDateTime $start, ilDateTime $end, string $a_compare_field='', string $a_tz='')
compare two dates and check start is before end This method does not consider tz offsets.
static _lookupType(int $id, bool $reference=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setLimitedAccessFilter(bool $a_status)
Enable limited access filter.
setCourseGroupFilter(int $a_cg_id)
Set course / group filter object_id of course or group.
array $additional_fields
getUdfFilter()
Get udf filter.
setUserFolder(?array $a_fold_id)
Set user folder filter reference id of user folder or category (local user administration)
setActionFilter(string $a_activation)
Set activation filter 'active' or 'inactive' or empty.
const DEFAULT_ORDER_FIELD
setLastLogin(ilDateTime $dt=null)
Set last login filter.
setOffset(int $a_offset)
setUserFilter(array $a_filter)
Array with user ids to query against.
setAdditionalFields(array $a_add)
Set additional fields (columns in usr_data or 'online_time')
setTextFilter(string $a_filter)
Text (like) filter in login, firstname, lastname or email.
setFirstLetterLastname(string $a_fll)
set first letter lastname filter
static getUserListData(string $a_order_field, string $a_order_dir, int $a_offset, int $a_limit, string $a_string_filter="", string $a_activation_filter="", ?ilDateTime $a_last_login_filter=null, bool $a_limited_access_filter=false, bool $a_no_courses_filter=false, int $a_course_group_filter=0, int $a_role_filter=0, array $a_user_folder_filter=null, array $a_additional_fields=null, array $a_user_filter=null, string $a_first_letter="", string $a_authentication_filter="")
Get data for user administration list.
string $authentication_method
setLimit(int $a_limit)
query()
Query usr_data.
setRoleFilter(int $a_role_id)
Set role filter obj_id of role.
setAuthenticationFilter(string $a_authentication)
Set authentication filter.
ilDateTime $last_login
setAccessFilter(bool $a_access)
set filter for user that are limited but has access
setNoCourseFilter(bool $a_no_course)
setOrderDirection(string $a_dir)
Set order direction 'asc' or 'desc' Default is 'asc'.
setOrderField(string $a_order)
Set order field (column in usr_data) Default order is 'login'.
setNoGroupFilter(bool $a_no_group)
setUdfFilter(array $a_val)
Set udf filter.
const ANONYMOUS_USER_ID
Definition: constants.php:27
global $DIC
Definition: feed.php:28
$query