ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilObjUser.php
Go to the documentation of this file.
1 <?php
2 
23 use ILIAS\Data\DateFormat\Factory as DateFormatFactory;
25 
32 class ilObjUser extends ilObject
33 {
34  public const NO_AVATAR_RID = '-';
35  public const PASSWD_PLAIN = "plain";
36  public const PASSWD_CRYPTED = "crypted";
37  protected string $ext_account = "";
38  protected string $time_limit_message = "";
39  protected bool $time_limit_unlimited = false;
40  protected ?int $time_limit_until = null;
41  protected ?int $time_limit_from = null;
42  protected ?int $time_limit_owner = null;
43  protected string $last_login = "";
44 
45  public string $login = '';
46  protected string $passwd = ""; // password encoded in the format specified by $passwd_type
47  protected string $passwd_type = "";
48  // specifies the password format.
49  // value: ilObjUser::PASSWD_PLAIN or ilObjUser::PASSWD_CRYPTED.
50  // Differences between password format in class ilObjUser and
51  // in table usr_data:
52  // Class ilObjUser supports two different password types
53  // (plain and crypted) and it uses the variables $passwd
54  // and $passwd_type to store them.
55  // Table usr_data supports only two different password types
56  // (md5 and bcrypt) and it uses the columns "passwd" and "passwd_type" to store them.
57  // The conversion between these two storage layouts is done
58  // in the methods that perform SQL statements. All other
59  // methods work exclusively with the $passwd and $passwd_type
60  // variables.
61  protected ?string $password_encoding_type = null; // The encoding algorithm of the user's password stored in the database
62  // A salt used to encrypt the user's password
63  protected ?string $password_salt = null;
64  public string $gender = ""; // 'm' or 'f'
65  public string $utitle = ""; // user title (keep in mind, that we derive $title from object also!)
66  public string $firstname = "";
67  public string $lastname = "";
68  protected ?string $birthday = null;
69  public string $fullname = ""; // title + firstname + lastname in one string
70  public string $institution = "";
71  public string $department = "";
72  public string $street = "";
73  public string $city = "";
74  public string $zipcode = "";
75  public string $country = "";
76  public string $sel_country = "";
77  public string $phone_office = "";
78  public string $phone_home = "";
79  public string $phone_mobile = "";
80  public string $fax = "";
81  public string $email = "";
82  protected ?string $second_email = null;
83  public string $hobby = "";
84  public string $matriculation = "";
85  public string $referral_comment = "";
86  public ?string $approve_date = null;
87  public ?string $agree_date = null;
88  public int $active = 0;
89  public string $client_ip = ""; // client ip to check before login
90  public ?string $auth_mode = null; // authentication mode
91  public ?string $latitude = null;
92  public ?string $longitude = null;
93  public ?string $loc_zoom = null;
94  public int $last_password_change_ts = 0;
95  protected bool $passwd_policy_reset = false;
96  public int $login_attempts = 0;
97  public array $user_defined_data = []; // Missing array type.
99  protected array $oldPrefs = [];
101  public array $prefs = [];
102  public string $skin = "";
103  protected static array $personal_image_cache = [];
104  protected ?string $inactivation_date = null;
105  private bool $is_self_registered = false; // flag for self registered users
106  protected string $org_units = ""; // ids of assigned org-units, comma seperated
108  protected array $interests_general = [];
110  protected array $interests_help_offered = [];
112  protected array $interests_help_looking = [];
113  protected string $last_profile_prompt = ""; // timestamp
114  protected string $first_login = ""; // timestamp
115  protected bool $profile_incomplete = false;
116  protected ?string $avatar_rid = null;
117 
118  protected DateFormatFactory $date_format_factory;
120  private Services $irss;
121 
122  public function __construct(
123  int $a_user_id = 0,
124  bool $a_call_by_reference = false
125  ) {
126  global $DIC;
127 
128  $this->type = "usr";
129  parent::__construct($a_user_id, $a_call_by_reference);
130 
131  $this->cron_delete_user_reminder_mail = new ilCronDeleteInactiveUserReminderMail($this->db);
132  $this->irss = $DIC->resourceStorage();
133  $this->auth_mode = "default";
134  $this->passwd_type = self::PASSWD_PLAIN;
135  if ($a_user_id > 0) {
136  $this->setId($a_user_id);
137  $this->read();
138  } else {
139  $this->prefs = [];
140  $this->prefs["language"] = $this->ilias->ini->readVariable("language", "default");
141  $this->skin = $this->ilias->ini->readVariable("layout", "skin");
142  $this->prefs["skin"] = $this->skin;
143  $this->prefs["style"] = $this->ilias->ini->readVariable("layout", "style");
144  }
145 
146  $this->app_event_handler = $DIC['ilAppEventHandler'];
147  $this->date_format_factory = (new DataFactory())->dateFormat();
148  }
149 
155  public function read(): void
156  {
157  global $DIC;
158 
159  $ilErr = $DIC['ilErr'];
160  $ilDB = $this->db;
161 
162  $r = $ilDB->queryF("SELECT * FROM usr_data " .
163  'WHERE usr_id= %s', ['integer'], [$this->id]);
164 
165  if ($data = $ilDB->fetchAssoc($r)) {
166  // convert password storage layout used by table usr_data into
167  // storage layout used by class ilObjUser
168  $data["passwd_type"] = self::PASSWD_CRYPTED;
169 
170  // this assign must not be set via $this->assignData($data)
171  // because this method will be called on profile updates and
172  // would set this values to 0, because they arent posted from form
173  $this->setLastPasswordChangeTS($data['last_password_change']);
174  $this->setLoginAttempts($data['login_attempts']);
175  $this->setPasswordPolicyResetStatus((bool) $data['passwd_policy_reset']);
176 
177  // fill member vars in one shot
178  $this->assignData($data);
179 
180  //get userpreferences from usr_pref table
181  $this->readPrefs();
182 
183  if (!isset($this->prefs['language']) || $this->prefs['language'] === '') {
184  $this->prefs['language'] = $this->oldPrefs['language'] ?? '';
185  }
186 
187  if (
188  !isset($this->prefs['skin']) || $this->prefs['skin'] === '' ||
189  !ilStyleDefinition::skinExists($this->prefs['skin'])
190  ) {
191  $this->prefs['skin'] = $this->oldPrefs['skin'] ?? '';
192  }
193 
194  $this->skin = $this->prefs["skin"];
195 
196  if (
197  !isset($this->prefs['style']) ||
198  $this->prefs['style'] === '' ||
199  !ilStyleDefinition::styleExists($this->prefs['style']) ||
200  (
201  !ilStyleDefinition::skinExists($this->skin) &&
202  ilStyleDefinition::styleExistsForSkinId($this->skin, $this->prefs['style'])
203  )
204  ) {
205  //load default (css)
206  $this->prefs["skin"] = $this->ilias->ini->readVariable("layout", "skin");
207  $this->prefs["style"] = $this->ilias->ini->readVariable("layout", "style");
208  }
209 
210  if (empty($this->prefs["hits_per_page"])) {
211  $this->prefs["hits_per_page"] = 10;
212  }
213  } else {
214  $ilErr->raiseError("<b>Error: There is no dataset with id " .
215  $this->id . "!</b><br />class: " . get_class($this) . "<br />Script: " . __FILE__ .
216  "<br />Line: " . __LINE__, $ilErr->FATAL);
217  }
218 
219  $this->readMultiTextFields();
220  $this->readUserDefinedFields();
221 
222  parent::read();
223  }
224 
225  public function getPasswordEncodingType(): ?string
226  {
228  }
229 
230  public function setPasswordEncodingType(?string $password_encryption_type): void
231  {
232  $this->password_encoding_type = $password_encryption_type;
233  }
234 
235  public function getPasswordSalt(): ?string
236  {
237  return $this->password_salt;
238  }
239 
240  public function setPasswordSalt(?string $password_salt): void
241  {
242  $this->password_salt = $password_salt;
243  }
244 
249  public function assignData(array $a_data): void
250  {
251  global $DIC;
252 
253  $ilErr = $DIC['ilErr'];
254 
255  // basic personal data
256  $this->setLogin($a_data["login"] ?? '');
257  if (!($a_data["passwd_type"] ?? false)) {
258  $ilErr->raiseError("<b>Error: passwd_type missing in function assignData(). " .
259  $this->id . "!</b><br />class: " . get_class($this) . "<br />Script: "
260  . __FILE__ . "<br />Line: " . __LINE__, $ilErr->FATAL);
261  }
262  if (($a_data["passwd"] ?? '') != "********" && strlen($a_data['passwd'] ?? '')) {
263  $this->setPasswd($a_data["passwd"] ?? '', $a_data["passwd_type"] ?? '');
264  }
265 
266  $this->setGender((string) ($a_data["gender"] ?? ''));
267  $this->setUTitle((string) ($a_data["title"] ?? ''));
268  $this->setFirstname((string) ($a_data["firstname"] ?? ''));
269  $this->setLastname((string) ($a_data["lastname"] ?? ''));
270  $this->setFullname();
271  if (isset($a_data['birthday']) && is_string($a_data['birthday'])) {
272  $this->setBirthday($a_data['birthday']);
273  } else {
274  $this->setBirthday(null);
275  }
276 
277  // address data
278  $this->setInstitution((string) ($a_data["institution"] ?? ''));
279  $this->setDepartment((string) ($a_data["department"] ?? ''));
280  $this->setStreet((string) ($a_data["street"] ?? ''));
281  $this->setCity((string) ($a_data["city"] ?? ''));
282  $this->setZipcode((string) ($a_data["zipcode"] ?? ''));
283  $this->setCountry((string) ($a_data["country"] ?? ''));
284  $this->setSelectedCountry((string) ($a_data["sel_country"] ?? ''));
285  $this->setPhoneOffice((string) ($a_data["phone_office"] ?? ''));
286  $this->setPhoneHome((string) ($a_data["phone_home"] ?? ''));
287  $this->setPhoneMobile((string) ($a_data["phone_mobile"] ?? ''));
288  $this->setFax((string) ($a_data["fax"] ?? ''));
289  $this->setMatriculation((string) ($a_data["matriculation"] ?? ''));
290  $this->setEmail((string) ($a_data["email"] ?? ''));
291  $this->setSecondEmail((string) ($a_data["second_email"] ?? null));
292  $this->setHobby((string) ($a_data["hobby"] ?? ''));
293  $this->setClientIP((string) ($a_data["client_ip"] ?? ''));
294  $this->setPasswordEncodingType($a_data['passwd_enc_type'] ?? null);
295  $this->setPasswordSalt($a_data['passwd_salt'] ?? null);
296 
297  // other data
298  $this->setLatitude($a_data["latitude"] ?? null);
299  $this->setLongitude($a_data["longitude"] ?? null);
300  $this->setLocationZoom($a_data["loc_zoom"] ?? null);
301 
302  // system data
303  $this->setLastLogin((string) ($a_data["last_login"] ?? ''));
304  $this->setFirstLogin((string) ($a_data["first_login"] ?? ''));
305  $this->setLastProfilePrompt((string) ($a_data["last_profile_prompt"] ?? ''));
306  $this->setLastUpdate((string) ($a_data["last_update"] ?? ''));
307  $this->create_date = $a_data["create_date"] ?? "";
308  $this->setComment((string) ($a_data["referral_comment"] ?? ''));
309  $this->approve_date = ($a_data["approve_date"] ?? null);
310  $this->active = ($a_data["active"] ?? 0);
311  $this->agree_date = ($a_data["agree_date"] ?? null);
312 
313  $this->setInactivationDate((string) ($a_data["inactivation_date"] ?? null));
314 
315  // time limitation
316  $this->setTimeLimitOwner((int) ($a_data["time_limit_owner"] ?? 0));
317  $this->setTimeLimitUnlimited((bool) ($a_data["time_limit_unlimited"] ?? false));
318  $this->setTimeLimitFrom((int) ($a_data["time_limit_from"] ?? 0));
319  $this->setTimeLimitUntil((int) ($a_data["time_limit_until"] ?? 0));
320  $this->setTimeLimitMessage((string) ($a_data['time_limit_message'] ?? ''));
321 
322  // user profile incomplete?
323  $this->setProfileIncomplete((bool) ($a_data["profile_incomplete"] ?? false));
324 
325  //authentication
326  $this->setAuthMode((string) ($a_data['auth_mode'] ?? null));
327  $this->setExternalAccount((string) ($a_data['ext_account'] ?? ''));
328 
329  $this->setIsSelfRegistered((bool) ($a_data['is_self_registered'] ?? false));
330 
331  // Avatar
332  $this->avatar_rid = (string) ($a_data['rid'] ?? self::NO_AVATAR_RID);
333  }
334 
340  public function saveAsNew(): void
341  {
342  global $DIC;
343 
344  $ilAppEventHandler = $DIC['ilAppEventHandler'];
345 
346  $ilErr = $DIC['ilErr'];
347  $ilDB = $this->db;
348  $pw_value = "";
349 
350  switch ($this->passwd_type) {
351  case self::PASSWD_PLAIN:
352  if (strlen($this->passwd)) {
353  ilUserPasswordManager::getInstance()->encodePassword($this, $this->passwd);
354  $pw_value = $this->getPasswd();
355  } else {
356  $pw_value = $this->passwd;
357  }
358  break;
359 
360  case self::PASSWD_CRYPTED:
361  $pw_value = $this->passwd;
362  break;
363 
364  default:
365  $ilErr->raiseError("<b>Error: passwd_type missing in function saveAsNew. " .
366  $this->id . "!</b><br />class: " . get_class($this) . "<br />Script: " . __FILE__ .
367  "<br />Line: " . __LINE__, $ilErr->FATAL);
368  }
369 
370  if (!$this->active) {
372  } else {
373  $this->setInactivationDate(null);
374  }
375 
376  $insert_array = [
377  "usr_id" => ["integer", $this->id],
378  "login" => ["text", $this->login],
379  "passwd" => ["text", $pw_value],
380  'passwd_enc_type' => ["text", $this->getPasswordEncodingType()],
381  'passwd_salt' => ["text", $this->getPasswordSalt()],
382  "firstname" => ["text", $this->firstname],
383  "lastname" => ["text", $this->lastname],
384  "title" => ["text", $this->utitle],
385  "gender" => ["text", $this->gender],
386  "email" => ["text", trim($this->email ?? '')],
387  "second_email" => ["text", trim($this->second_email ?? '')],
388  "hobby" => ["text", $this->hobby],
389  "institution" => ["text", $this->institution],
390  "department" => ["text", $this->department],
391  "street" => ["text", $this->street],
392  "city" => ["text", $this->city],
393  "zipcode" => ["text", $this->zipcode],
394  "country" => ["text", $this->country],
395  "sel_country" => ["text", $this->sel_country],
396  "phone_office" => ["text", $this->phone_office],
397  "phone_home" => ["text", $this->phone_home],
398  "phone_mobile" => ["text", $this->phone_mobile],
399  "fax" => ["text", $this->fax],
400  "birthday" => ['date', $this->getBirthday()],
401  "last_login" => ["timestamp", null],
402  "first_login" => ["timestamp", null],
403  "last_profile_prompt" => ["timestamp", null],
404  "last_update" => ["timestamp", ilUtil::now()],
405  "create_date" => ["timestamp", ilUtil::now()],
406  "referral_comment" => ["text", $this->referral_comment],
407  "matriculation" => ["text", $this->matriculation],
408  "client_ip" => ["text", $this->client_ip],
409  "approve_date" => ["timestamp", $this->approve_date],
410  "agree_date" => ["timestamp", $this->agree_date],
411  "active" => ["integer", $this->active],
412  "time_limit_unlimited" => ["integer", $this->getTimeLimitUnlimited()],
413  "time_limit_until" => ["integer", $this->getTimeLimitUntil()],
414  "time_limit_from" => ["integer", $this->getTimeLimitFrom()],
415  "time_limit_owner" => ["integer", $this->getTimeLimitOwner()],
416  "auth_mode" => ["text", $this->getAuthMode()],
417  "ext_account" => ["text", $this->getExternalAccount()],
418  "profile_incomplete" => ["integer", $this->getProfileIncomplete()],
419  "latitude" => ["text", $this->latitude],
420  "longitude" => ["text", $this->longitude],
421  "loc_zoom" => ["integer", (int) $this->loc_zoom],
422  "last_password_change" => ["integer", $this->last_password_change_ts],
423  "passwd_policy_reset" => ["integer", (int) $this->passwd_policy_reset],
424  'inactivation_date' => ['timestamp', $this->inactivation_date],
425  'is_self_registered' => ['integer', (int) $this->is_self_registered],
426  ];
427  $ilDB->insert("usr_data", $insert_array);
428 
429  $this->updateMultiTextFields(true);
430  $this->updateUserDefinedFields();
431 
432  // CREATE ENTRIES FOR MAIL BOX
433  $mbox = new ilMailbox($this->id);
434  $mbox->createDefaultFolder();
435 
436  $mail_options = new ilMailOptions($this->id);
437  $mail_options->createMailOptionsEntry();
438 
439  $ilAppEventHandler->raise(
440  "Services/User",
441  "afterCreate",
442  ["user_obj" => $this]
443  );
444  }
445 
446  public function update(): bool
447  {
448  global $DIC;
449 
450  $ilErr = $DIC['ilErr'];
451  $ilDB = $this->db;
452  $ilAppEventHandler = $this->app_event_handler;
453 
454  $this->syncActive();
455 
456  if ($this->getStoredActive($this->id) && !$this->active) {
458  } elseif ($this->active) {
459  $this->setInactivationDate(null);
460  }
461 
462  $update_array = [
463  "gender" => ["text", $this->gender],
464  "title" => ["text", $this->utitle],
465  "firstname" => ["text", substr($this->firstname, 0, 128)],
466  "lastname" => ["text", substr($this->lastname, 0, 128)],
467  "email" => ["text", substr(trim($this->email), 0, 128)],
468  "second_email" => ["text", trim($this->second_email ?? '')],
469  "birthday" => ['date', $this->getBirthday()],
470  "hobby" => ["text", $this->hobby],
471  "institution" => ["text", $this->institution],
472  "department" => ["text", $this->department],
473  "street" => ["text", $this->street],
474  "city" => ["text", $this->city],
475  "zipcode" => ["text", $this->zipcode],
476  "country" => ["text", $this->country],
477  "sel_country" => ["text", $this->sel_country],
478  "phone_office" => ["text", $this->phone_office],
479  "phone_home" => ["text", $this->phone_home],
480  "phone_mobile" => ["text", $this->phone_mobile],
481  "fax" => ["text", $this->fax],
482  "referral_comment" => ["text", $this->referral_comment],
483  "matriculation" => ["text", $this->matriculation],
484  "client_ip" => ["text", $this->client_ip],
485  "approve_date" => ["timestamp", $this->approve_date],
486  "active" => ["integer", $this->active],
487  "time_limit_unlimited" => ["integer", $this->getTimeLimitUnlimited()],
488  "time_limit_until" => ["integer", $this->getTimeLimitUntil()],
489  "time_limit_from" => ["integer", $this->getTimeLimitFrom()],
490  "time_limit_owner" => ["integer", $this->getTimeLimitOwner()],
491  "time_limit_message" => ["integer", $this->getTimeLimitMessage()],
492  "profile_incomplete" => ["integer", $this->getProfileIncomplete()],
493  "auth_mode" => ["text", $this->getAuthMode()],
494  "ext_account" => ["text", $this->getExternalAccount()],
495  "latitude" => ["text", $this->latitude],
496  "longitude" => ["text", $this->longitude],
497  "loc_zoom" => ["integer", (int) $this->loc_zoom],
498  'login_attempts' => ['integer', $this->login_attempts],
499  "last_password_change" => ["integer", $this->last_password_change_ts],
500  "passwd_policy_reset" => ["integer", $this->passwd_policy_reset],
501  "last_update" => ["timestamp", ilUtil::now()],
502  'inactivation_date' => ['timestamp', $this->inactivation_date],
503  'reg_hash' => ['text', null],
504  'rid' => [
505  'text',
506  ($this->avatar_rid ?? self::NO_AVATAR_RID)
507  ],
508  ];
509 
510  if ($this->agree_date === null || (is_string($this->agree_date) && strtotime($this->agree_date) !== false)) {
511  $update_array["agree_date"] = ["timestamp", $this->agree_date];
512  }
513  switch ($this->passwd_type) {
514  case self::PASSWD_PLAIN:
515  if (strlen($this->passwd)) {
516  ilUserPasswordManager::getInstance()->encodePassword($this, $this->passwd);
517  $update_array['passwd'] = ['text', $this->getPasswd()];
518  } else {
519  $update_array["passwd"] = ["text", $this->passwd];
520  }
521  break;
522 
523  case self::PASSWD_CRYPTED:
524  $update_array["passwd"] = ["text", $this->passwd];
525  break;
526 
527  default:
528  $ilErr->raiseError("<b>Error: passwd_type missing in function update()" . $this->id . "!</b><br />class: " .
529  get_class($this) . "<br />Script: " . __FILE__ . "<br />Line: " . __LINE__, $ilErr->FATAL);
530  }
531 
532  $update_array['passwd_enc_type'] = ['text', $this->getPasswordEncodingType()];
533  $update_array['passwd_salt'] = ['text', $this->getPasswordSalt()];
534 
535  $ilDB->update("usr_data", $update_array, ["usr_id" => ["integer", $this->id]]);
536 
537  $this->updateMultiTextFields();
538 
539  $this->writePrefs();
540 
541  // update user defined fields
542  $this->updateUserDefinedFields();
543 
544  parent::update();
545  $this->updateOwner();
546 
547  $this->read();
548 
549  $ilAppEventHandler->raise(
550  "Services/User",
551  "afterUpdate",
552  ["user_obj" => $this]
553  );
554 
555  return true;
556  }
557 
561  public function writeAccepted(): void
562  {
563  $ilDB = $this->db;
564  $ilDB->manipulateF("UPDATE usr_data SET agree_date = " . $ilDB->now() .
565  " WHERE usr_id = %s", ["integer"], [$this->getId()]);
566  }
567 
568  private static function _lookup(
569  int $a_user_id,
570  string $a_field
571  ): ?string {
572  global $DIC;
573 
574  $ilDB = $DIC->database();
575 
576  $res = $ilDB->queryF(
577  "SELECT " . $a_field . " FROM usr_data WHERE usr_id = %s",
578  ["integer"],
579  [$a_user_id]
580  );
581 
582  while ($set = $ilDB->fetchAssoc($res)) {
583  return $set[$a_field];
584  }
585  return null;
586  }
587 
588  public static function _lookupFullname(int $a_user_id): string
589  {
590  global $DIC;
591 
592  $fullname = "";
593  $ilDB = $DIC['ilDB'];
594 
595  $set = $ilDB->queryF(
596  "SELECT title, firstname, lastname FROM usr_data WHERE usr_id = %s",
597  ["integer"],
598  [$a_user_id]
599  );
600 
601  if ($rec = $ilDB->fetchAssoc($set)) {
602  if ($rec["title"]) {
603  $fullname = $rec["title"] . " ";
604  }
605  if ($rec["firstname"]) {
606  $fullname .= $rec["firstname"] . " ";
607  }
608  if ($rec["lastname"]) {
609  $fullname .= $rec["lastname"];
610  }
611  }
612  return $fullname;
613  }
614 
615  public static function _lookupEmail(int $a_user_id): string
616  {
617  return self::_lookup($a_user_id, "email") ?? '';
618  }
619 
620  public static function _lookupGender(int $a_user_id): string
621  {
622  return (string) self::_lookup($a_user_id, "gender") ?? '';
623  }
624 
625  public static function _lookupClientIP(int $a_user_id): string
626  {
627  return self::_lookup($a_user_id, "client_ip") ?? '';
628  }
629 
634  public static function _lookupName(int $a_user_id): array
635  {
636  global $DIC;
637 
638  $ilDB = $DIC['ilDB'];
639 
640  $res = $ilDB->queryF(
641  "SELECT firstname, lastname, title, login FROM usr_data WHERE usr_id = %s",
642  ["integer"],
643  [$a_user_id]
644  );
645  if ($user_rec = $ilDB->fetchAssoc($res)) {
646  return ["user_id" => $a_user_id,
647  "firstname" => $user_rec["firstname"],
648  "lastname" => $user_rec["lastname"],
649  "title" => $user_rec["title"],
650  "login" => $user_rec["login"]
651  ];
652  }
653  return ["user_id" => 0,
654  "firstname" => "",
655  "lastname" => "",
656  "title" => "",
657  "login" => ""
658  ];
659  }
660 
665  public static function _lookupFields(int $a_user_id): array // Missing array type.
666  {
667  global $DIC;
668 
669  $ilDB = $DIC['ilDB'];
670 
671  $res = $ilDB->queryF(
672  "SELECT * FROM usr_data WHERE usr_id = %s",
673  ["integer"],
674  [$a_user_id]
675  );
676  $user_rec = $ilDB->fetchAssoc($res);
677  return $user_rec;
678  }
679 
680  public static function _lookupLogin(int $a_user_id): string
681  {
682  return (string) self::_lookup($a_user_id, "login") ?? '';
683  }
684 
685  public static function _lookupExternalAccount(int $a_user_id): string
686  {
687  return (string) self::_lookup($a_user_id, "ext_account") ?? '';
688  }
689 
694  public static function _lookupId($a_user_str)
695  {
696  global $DIC;
697 
698  $ilDB = $DIC['ilDB'];
699 
700  if (!is_array($a_user_str)) {
701  $res = $ilDB->queryF(
702  "SELECT usr_id FROM usr_data WHERE login = %s",
703  ["text"],
704  [$a_user_str]
705  );
706 
707  $user_rec = $ilDB->fetchAssoc($res);
708  if (is_array($user_rec)) {
709  return (int) $user_rec["usr_id"];
710  }
711 
712  return null;
713  }
714 
715  $set = $ilDB->query(
716  "SELECT usr_id FROM usr_data " .
717  " WHERE " . $ilDB->in("login", $a_user_str, false, "text")
718  );
719 
720  $ids = [];
721  while ($rec = $ilDB->fetchAssoc($set)) {
722  $ids[] = (int) $rec['usr_id'];
723  }
724 
725  return $ids;
726  }
727 
728  public static function _lookupLastLogin(int $a_user_id): string
729  {
730  return self::_lookup($a_user_id, "last_login") ?? '';
731  }
732 
733  public static function _lookupFirstLogin(int $a_user_id): string
734  {
735  return self::_lookup($a_user_id, "first_login") ?? '';
736  }
737 
738 
743  public function refreshLogin(): void
744  {
745  $ilDB = $this->db;
746 
747  $ilDB->manipulateF(
748  "UPDATE usr_data SET " .
749  "last_login = " . $ilDB->now() .
750  " WHERE usr_id = %s",
751  ["integer"],
752  [$this->id]
753  );
754 
755  if ($this->getFirstLogin() == "") {
756  $ilDB->manipulateF(
757  "UPDATE usr_data SET " .
758  "first_login = " . $ilDB->now() .
759  " WHERE usr_id = %s",
760  ["integer"],
761  [$this->id]
762  );
763  $this->app_event_handler->raise(
764  "Services/User",
765  "firstLogin",
766  ["user_obj" => $this]
767  );
768  }
769  }
770 
771 
780  public function resetPassword(
781  string $raw,
782  string $raw_retype
783  ): bool {
784  $ilDB = $this->db;
785 
786  if (func_num_args() != 2) {
787  return false;
788  }
789 
790  if (!isset($raw) || !isset($raw_retype)) {
791  return false;
792  }
793 
794  if ($raw != $raw_retype) {
795  return false;
796  }
797 
798  ilUserPasswordManager::getInstance()->encodePassword($this, $raw);
799 
800  $ilDB->manipulateF(
801  'UPDATE usr_data
802  SET passwd = %s, passwd_enc_type = %s, passwd_salt = %s
803  WHERE usr_id = %s',
804  ['text', 'text', 'text', 'integer'],
805  [$this->getPasswd(), $this->getPasswordEncodingType(), $this->getPasswordSalt(), $this->getId()]
806  );
807 
808  return true;
809  }
810 
814  public static function _doesLoginnameExistInHistory(string $a_login): bool
815  {
816  global $DIC;
817 
818  $ilDB = $DIC->database();
819 
820  $res = $ilDB->queryF(
821  '
822  SELECT * FROM loginname_history
823  WHERE login = %s',
824  ['text'],
825  [$a_login]
826  );
827 
828  return (bool) $ilDB->fetchAssoc($res);
829  }
830 
837  public static function _getLastHistoryDataByUserId(int $a_usr_id): array
838  {
839  global $DIC;
840 
841  $ilDB = $DIC['ilDB'];
842 
843  $ilDB->setLimit(1, 0);
844  $res = $ilDB->queryF(
845  '
846  SELECT login, history_date FROM loginname_history
847  WHERE usr_id = %s ORDER BY history_date DESC',
848  ['integer'],
849  [$a_usr_id]
850  );
851  $row = $ilDB->fetchAssoc($res);
852  if (!is_array($row) || !count($row)) {
853  throw new ilUserException('');
854  }
855 
856  return [
857  $row['login'], $row['history_date']
858  ];
859  }
860 
868  public function updateLogin(string $a_login): bool
869  {
870  global $DIC;
871 
872  $ilDB = $this->db;
873  $ilSetting = $DIC['ilSetting'];
874  $lng = $DIC->language();
875 
876  if (func_num_args() != 1) {
877  return false;
878  }
879 
880  if (!isset($a_login)) {
881  return false;
882  }
883 
884  $former_login = self::_lookupLogin($this->getId());
885 
886  // Update not necessary
887  if (0 == strcmp($a_login, $former_login)) {
888  return false;
889  }
890 
891  try {
892  $last_history_entry = self::_getLastHistoryDataByUserId($this->getId());
893  } catch (ilUserException $e) {
894  $last_history_entry = null;
895  }
896 
897  // throw exception if the desired loginame is already in history and it is not allowed to reuse it
898  if ((int) $ilSetting->get('allow_change_loginname') &&
899  (int) $ilSetting->get('reuse_of_loginnames') == 0 &&
900  self::_doesLoginnameExistInHistory($a_login)) {
901  throw new ilUserException($lng->txt('loginname_already_exists'));
902  } elseif ((int) $ilSetting->get('allow_change_loginname') &&
903  (int) $ilSetting->get('loginname_change_blocking_time') &&
904  is_array($last_history_entry) &&
905  $last_history_entry[1] + (int) $ilSetting->get('loginname_change_blocking_time') > time()) {
906  throw new ilUserException(
907  sprintf(
908  $lng->txt('changing_loginname_not_possible_info'),
910  new ilDateTime($last_history_entry[1], IL_CAL_UNIX)
911  ),
913  new ilDateTime(($last_history_entry[1] + (int) $ilSetting->get('loginname_change_blocking_time')), IL_CAL_UNIX)
914  )
915  )
916  );
917  } else {
918  // log old loginname in history
919  if ((int) $ilSetting->get('allow_change_loginname') &&
920  (int) $ilSetting->get('create_history_loginname')) {
921  self::_writeHistory($this->getId(), $former_login);
922  }
923 
924  //update login
925  $this->login = $a_login;
926 
927  $ilDB->manipulateF(
928  '
929  UPDATE usr_data
930  SET login = %s
931  WHERE usr_id = %s',
932  ['text', 'integer'],
933  [$this->getLogin(), $this->getId()]
934  );
935  }
936 
937  return true;
938  }
939 
940  public function writePref(
941  string $a_keyword,
942  string $a_value
943  ): void {
944  self::_writePref($this->id, $a_keyword, $a_value);
945  $this->setPref($a_keyword, $a_value);
946  }
947 
948  public function deletePref(string $a_keyword): void
949  {
950  self::_deletePref($this->getId(), $a_keyword);
951  }
952 
953  public static function _deletePref(int $a_user_id, string $a_keyword): void
954  {
955  global $DIC;
956 
957  $ilDB = $DIC->database();
958 
959  $ilDB->manipulateF(
960  'DELETE FROM usr_pref WHERE usr_id = %s AND keyword = %s',
961  ['integer', 'text'],
962  [$a_user_id, $a_keyword]
963  );
964  }
965 
969  public static function _deleteAllPref(int $a_user_id): void
970  {
971  global $DIC;
972 
973  $ilDB = $DIC->database();
974 
975  $ilDB->manipulateF(
976  "DELETE FROM usr_pref WHERE usr_id = %s",
977  ["integer"],
978  [$a_user_id]
979  );
980  }
981 
982  public static function _writePref(
983  int $a_usr_id,
984  string $a_keyword,
985  string $a_value
986  ): void {
987  global $DIC;
988 
989  $ilDB = $DIC->database();
990  $ilDB->replace(
991  "usr_pref",
992  [
993  "usr_id" => ["integer", $a_usr_id],
994  "keyword" => ["text", $a_keyword],
995  ],
996  [
997  "value" => ["text",$a_value]
998  ]
999  );
1000  }
1001 
1002  public function writePrefs(): void
1003  {
1004  self::_deleteAllPref($this->id);
1005  foreach ($this->prefs as $keyword => $value) {
1006  self::_writePref($this->id, $keyword, (string) $value);
1007  }
1008  }
1009 
1010  public function getTimeZone(): string
1011  {
1012  if ($tz = $this->getPref('user_tz')) {
1013  return $tz;
1014  } else {
1016  return $settings->getDefaultTimeZone();
1017  }
1018  }
1019 
1020  public function getTimeFormat(): string
1021  {
1022  if ($format = $this->getPref('time_format')) {
1023  return $format;
1024  } else {
1026  return $settings->getDefaultTimeFormat();
1027  }
1028  }
1029 
1030  public function getDateFormat(): DateFormat
1031  {
1032  if (!($format = $this->getPref('date_format'))) {
1034  $format = $settings->getDefaultDateFormat();
1035  }
1036 
1037  switch ($format) {
1039  return $this->date_format_factory->germanShort();
1040 
1042  return $this->date_format_factory->americanShort();
1043 
1045  default:
1046  return $this->date_format_factory->standard();
1047  }
1048  }
1049 
1050  public function setPref(string $a_keyword, ?string $a_value): void
1051  {
1052  if ($a_keyword != "") {
1053  $this->prefs[$a_keyword] = $a_value;
1054  }
1055  }
1056 
1057  public function getPref(string $a_keyword): ?string
1058  {
1059  return $this->prefs[$a_keyword] ?? null;
1060  }
1061 
1062  public function existsPref(string $a_keyword): bool
1063  {
1064  return (array_key_exists($a_keyword, $this->prefs));
1065  }
1066 
1067  public static function _lookupPref(
1068  int $a_usr_id,
1069  string $a_keyword
1070  ): ?string {
1071  global $DIC;
1072 
1073  $ilDB = $DIC['ilDB'];
1074 
1075  $query = "SELECT * FROM usr_pref WHERE usr_id = " . $ilDB->quote($a_usr_id, "integer") . " " .
1076  "AND keyword = " . $ilDB->quote($a_keyword, "text");
1077  $res = $ilDB->query($query);
1078 
1079  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
1080  return $row->value;
1081  }
1082  return null;
1083  }
1084 
1085  public function readPrefs(): void
1086  {
1087  if (is_array($this->prefs)) {
1088  $this->oldPrefs = $this->prefs;
1089  }
1090  $this->prefs = self::_getPreferences($this->id);
1091  }
1092 
1093  public function delete(): bool
1094  {
1095  global $DIC;
1096 
1097  $rbacadmin = $DIC->rbac()->admin();
1098  $ilDB = $this->db;
1099 
1100  $ilAppEventHandler = $DIC['ilAppEventHandler'];
1101  $ilAppEventHandler->raise(
1102  'Services/User',
1103  'deleteUser',
1104  ['usr_id' => $this->getId()]
1105  );
1106 
1107  // deassign from ldap groups
1109  $mapping->deleteUser($this->getId());
1110 
1111  // remove mailbox / update sent mails
1112  $mailbox = new ilMailbox($this->getId());
1113  $mailbox->delete();
1114  $mailbox->updateMailsOfDeletedUser($this->getLogin());
1115 
1116  // delete block settings
1118 
1119  // delete user_account
1120  $ilDB->manipulateF(
1121  "DELETE FROM usr_data WHERE usr_id = %s",
1122  ["integer"],
1123  [$this->getId()]
1124  );
1125 
1126  $this->deleteMultiTextFields();
1127 
1128  // delete user_prefs
1129  self::_deleteAllPref($this->getId());
1130 
1131  $this->removeUserPicture(false); // #8597
1132 
1133  // delete user_session
1135 
1136  // remove user from rbac
1137  $rbacadmin->removeUser($this->getId());
1138 
1139  // remove bookmarks
1140  // TODO: move this to class.ilBookmarkFolder
1141  $q = "DELETE FROM bookmark_tree WHERE tree = " .
1142  $ilDB->quote($this->getId(), "integer");
1143  $ilDB->manipulate($q);
1144 
1145  $q = "DELETE FROM bookmark_data WHERE user_id = " .
1146  $ilDB->quote($this->getId(), "integer");
1147  $ilDB->manipulate($q);
1148 
1149  // Delete crs entries
1150  ilObjCourse::_deleteUser($this->getId());
1151 
1152  // Delete user tracking
1154 
1156 
1157  // Delete Tracking data SCORM 2004 RTE
1159 
1160  // Delete Tracking data SCORM 1.2 RTE
1162 
1163  // remove all notifications
1165 
1166  // remove portfolios
1168 
1169  // remove workspace
1170  $tree = new ilWorkspaceTree($this->getId());
1171  $tree->cascadingDelete();
1172 
1173  // remove reminder entries
1174  $this->cron_delete_user_reminder_mail->removeSingleUserFromTable($this->getId());
1175 
1176  // badges
1178 
1179  // remove org unit assignments
1180  $ilOrgUnitUserAssignmentQueries = ilOrgUnitUserAssignmentQueries::getInstance();
1181  $ilOrgUnitUserAssignmentQueries->deleteAllAssignmentsOfUser($this->getId());
1182 
1183  // Delete user defined field entries
1185 
1186  // Delete clipboard entries
1187  $this->clipboardDeleteAll();
1188 
1189  // Reset owner
1190  $this->resetOwner();
1191 
1192  // delete object data
1193  parent::delete();
1194  return true;
1195  }
1196 
1202  public function setFullname(): void
1203  {
1204  $this->fullname = ($this->utitle != "")
1205  ? $this->utitle . " "
1206  : "";
1207  $this->fullname .= $this->firstname . " ";
1208  $this->fullname .= $this->lastname;
1209  }
1210 
1223  public function getFullname(int $a_max_strlen = 0): string
1224  {
1225  if (!$a_max_strlen) {
1226  return ilUtil::stripSlashes($this->fullname);
1227  }
1228 
1229  if (strlen($this->fullname) <= $a_max_strlen) {
1230  return ilUtil::stripSlashes($this->fullname);
1231  }
1232 
1233  if ((strlen($this->utitle) + strlen($this->lastname) + 4) <= $a_max_strlen) {
1234  return ilUtil::stripSlashes($this->utitle . " " . substr($this->firstname, 0, 1) . ". " . $this->lastname);
1235  }
1236 
1237  if ((strlen($this->firstname) + strlen($this->lastname) + 1) <= $a_max_strlen) {
1238  return ilUtil::stripSlashes($this->firstname . " " . $this->lastname);
1239  }
1240 
1241  if ((strlen($this->lastname) + 3) <= $a_max_strlen) {
1242  return ilUtil::stripSlashes(substr($this->firstname, 0, 1) . ". " . $this->lastname);
1243  }
1244 
1245  return ilUtil::stripSlashes(substr($this->lastname, 0, $a_max_strlen));
1246  }
1247 
1248  public function setLogin(string $a_str): void
1249  {
1250  $this->login = $a_str;
1251  }
1252 
1253  public function getLogin(): string
1254  {
1255  return $this->login;
1256  }
1257 
1258  public function setPasswd(
1259  string $a_str,
1260  string $a_type = ilObjUser::PASSWD_PLAIN
1261  ): void {
1262  $this->passwd = $a_str;
1263  $this->passwd_type = $a_type;
1264  }
1265 
1269  public function getPasswd(): string
1270  {
1271  return $this->passwd;
1272  }
1273 
1277  public function getPasswdType(): string
1278  {
1279  return $this->passwd_type;
1280  }
1281 
1282  public function setGender(string $a_str): void
1283  {
1284  $this->gender = substr($a_str, -1);
1285  }
1286 
1287  public function getGender(): string
1288  {
1289  return $this->gender;
1290  }
1291 
1297  public function setUTitle(string $a_str): void
1298  {
1299  $this->utitle = $a_str;
1300  }
1301 
1302  public function getUTitle(): string
1303  {
1304  return $this->utitle;
1305  }
1306 
1307  public function setFirstname(string $a_str): void
1308  {
1309  $this->firstname = $a_str;
1310  }
1311 
1312  public function getFirstname(): string
1313  {
1314  return $this->firstname;
1315  }
1316 
1317  public function setLastname(string $a_str): void
1318  {
1319  $this->lastname = $a_str;
1320  }
1321 
1322  public function getLastname(): string
1323  {
1324  return $this->lastname;
1325  }
1326 
1327  public function setInstitution(string $a_str): void
1328  {
1329  $this->institution = $a_str;
1330  }
1331 
1332  public function getInstitution(): string
1333  {
1334  return $this->institution;
1335  }
1336 
1337  public function setDepartment(string $a_str): void
1338  {
1339  $this->department = $a_str;
1340  }
1341 
1342  public function getDepartment(): string
1343  {
1344  return $this->department;
1345  }
1346 
1347  public function setStreet(string $a_str): void
1348  {
1349  $this->street = $a_str;
1350  }
1351 
1352  public function getStreet(): string
1353  {
1354  return $this->street;
1355  }
1356 
1357  public function setCity(string $a_str): void
1358  {
1359  $this->city = $a_str;
1360  }
1361 
1362  public function getCity(): string
1363  {
1364  return $this->city;
1365  }
1366 
1367  public function setZipcode(string $a_str): void
1368  {
1369  $this->zipcode = $a_str;
1370  }
1371 
1372  public function getZipcode(): string
1373  {
1374  return $this->zipcode;
1375  }
1376 
1377  public function setCountry(string $a_str): void
1378  {
1379  $this->country = $a_str;
1380  }
1381 
1382  public function getCountry(): string
1383  {
1384  return $this->country;
1385  }
1386 
1390  public function setSelectedCountry(string $a_val): void
1391  {
1392  $this->sel_country = $a_val;
1393  }
1394 
1398  public function getSelectedCountry(): string
1399  {
1400  return $this->sel_country;
1401  }
1402 
1403  public function setPhoneOffice(string $a_str): void
1404  {
1405  $this->phone_office = $a_str;
1406  }
1407 
1408  public function getPhoneOffice(): string
1409  {
1410  return $this->phone_office;
1411  }
1412 
1413  public function setPhoneHome(string $a_str): void
1414  {
1415  $this->phone_home = $a_str;
1416  }
1417 
1418  public function getPhoneHome(): string
1419  {
1420  return $this->phone_home;
1421  }
1422 
1423  public function setPhoneMobile(string $a_str): void
1424  {
1425  $this->phone_mobile = $a_str;
1426  }
1427 
1428  public function getPhoneMobile(): string
1429  {
1430  return $this->phone_mobile;
1431  }
1432 
1433  public function setFax(string $a_str): void
1434  {
1435  $this->fax = $a_str;
1436  }
1437 
1438  public function getFax(): string
1439  {
1440  return $this->fax;
1441  }
1442 
1443  public function setClientIP(string $a_str): void
1444  {
1445  $this->client_ip = $a_str;
1446  }
1447 
1448  public function getClientIP(): string
1449  {
1450  return $this->client_ip;
1451  }
1452 
1453  public function setMatriculation(string $a_str): void
1454  {
1455  $this->matriculation = $a_str;
1456  }
1457 
1458  public function getMatriculation(): string
1459  {
1460  return $this->matriculation;
1461  }
1462 
1463  public static function lookupMatriculation(int $a_usr_id): string
1464  {
1465  global $DIC;
1466 
1467  $ilDB = $DIC['ilDB'];
1468 
1469  $query = "SELECT matriculation FROM usr_data " .
1470  "WHERE usr_id = " . $ilDB->quote($a_usr_id);
1471  $res = $ilDB->query($query);
1472  $row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT);
1473  return $row->matriculation ?: '';
1474  }
1475 
1476  public function setEmail(string $a_str): void
1477  {
1478  $this->email = $a_str;
1479  }
1480 
1481  public function getEmail(): string
1482  {
1483  return $this->email;
1484  }
1485 
1486  public function getSecondEmail(): ?string
1487  {
1488  return $this->second_email;
1489  }
1490 
1491  public function setSecondEmail(?string $second_email): void
1492  {
1493  $this->second_email = $second_email;
1494  }
1495 
1496  public function setHobby(string $a_str): void
1497  {
1498  $this->hobby = $a_str;
1499  }
1500 
1501  public function getHobby(): string
1502  {
1503  return $this->hobby;
1504  }
1505 
1506  public function setLanguage(string $a_str): void
1507  {
1508  $this->setPref("language", $a_str);
1509  ilSession::clear('lang');
1510  }
1511 
1512  public function getLanguage(): string
1513  {
1514  return $this->prefs["language"];
1515  }
1516 
1517  public function setLastPasswordChangeTS(int $a_last_password_change_ts): void
1518  {
1519  $this->last_password_change_ts = $a_last_password_change_ts;
1520  }
1521 
1522  public function getLastPasswordChangeTS(): int
1523  {
1525  }
1526 
1527  public function getPasswordPolicyResetStatus(): bool
1528  {
1530  }
1531 
1532  public function setPasswordPolicyResetStatus(bool $status): void
1533  {
1534  $this->passwd_policy_reset = $status;
1535  }
1536 
1537  public static function _lookupLanguage(int $a_usr_id): string
1538  {
1539  global $DIC;
1540 
1541  $ilDB = $DIC->database();
1542  $lng = $DIC->language();
1543 
1544  $q = "SELECT value FROM usr_pref WHERE usr_id= " .
1545  $ilDB->quote($a_usr_id, "integer") . " AND keyword = " .
1546  $ilDB->quote('language', "text");
1547  $r = $ilDB->query($q);
1548 
1549  while ($row = $ilDB->fetchAssoc($r)) {
1550  return (string) $row['value'];
1551  }
1552  if (is_object($lng)) {
1553  return $lng->getDefaultLanguage();
1554  }
1555  return 'en';
1556  }
1557 
1558  public static function _writeExternalAccount(
1559  int $a_usr_id,
1560  string $a_ext_id
1561  ): void {
1562  global $DIC;
1563 
1564  $ilDB = $DIC['ilDB'];
1565 
1566  $ilDB->manipulateF(
1567  "UPDATE usr_data " .
1568  " SET ext_account = %s WHERE usr_id = %s",
1569  ["text", "integer"],
1570  [$a_ext_id, $a_usr_id]
1571  );
1572  }
1573 
1574  public static function _writeAuthMode(int $a_usr_id, string $a_auth_mode): void
1575  {
1576  global $DIC;
1577 
1578  $ilDB = $DIC['ilDB'];
1579 
1580  $ilDB->manipulateF(
1581  "UPDATE usr_data " .
1582  " SET auth_mode = %s WHERE usr_id = %s",
1583  ["text", "integer"],
1584  [$a_auth_mode, $a_usr_id]
1585  );
1586  }
1587 
1591  public function getCurrentLanguage(): string
1592  {
1593  return (string) ilSession::get('lang');
1594  }
1595 
1599  public function setCurrentLanguage(string $a_val): void
1600  {
1601  ilSession::set('lang', $a_val);
1602  }
1603 
1604  public function setLastLogin(string $a_str): void
1605  {
1606  $this->last_login = $a_str;
1607  }
1608 
1609  public function getLastLogin(): string
1610  {
1611  return $this->last_login;
1612  }
1613 
1614  public function setFirstLogin(string $a_str): void
1615  {
1616  $this->first_login = $a_str;
1617  }
1618 
1619  public function getFirstLogin(): string
1620  {
1621  return $this->first_login;
1622  }
1623 
1624  public function setLastProfilePrompt(string $a_str): void
1625  {
1626  $this->last_profile_prompt = $a_str;
1627  }
1628 
1629  public function getLastProfilePrompt(): string
1630  {
1632  }
1633 
1634  public function setLastUpdate(string $a_str): void
1635  {
1636  $this->last_update = $a_str;
1637  }
1638 
1639  public function getLastUpdate(): string
1640  {
1641  return $this->last_update;
1642  }
1643 
1644  public function setComment(string $a_str): void
1645  {
1646  $this->referral_comment = $a_str;
1647  }
1648 
1649  public function getComment(): string
1650  {
1651  return $this->referral_comment;
1652  }
1653 
1658  public function setApproveDate(?string $a_str): void
1659  {
1660  $this->approve_date = $a_str;
1661  }
1662 
1663  public function getApproveDate(): ?string
1664  {
1665  return $this->approve_date;
1666  }
1667 
1668  public function getAgreeDate(): ?string
1669  {
1670  return $this->agree_date;
1671  }
1672  public function setAgreeDate(?string $a_str): void
1673  {
1674  $this->agree_date = $a_str;
1675  }
1676 
1681  public function setActive(
1682  bool $a_active,
1683  int $a_owner = 0
1684  ): void {
1685  $this->setOwner($a_owner);
1686 
1687  if ($a_active) {
1688  $this->active = 1;
1689  $this->setApproveDate(date('Y-m-d H:i:s'));
1690  $this->setOwner($a_owner);
1691  } else {
1692  $this->active = 0;
1693  $this->setApproveDate(null);
1694  }
1695  }
1696 
1697  public function getActive(): bool
1698  {
1699  return (bool) $this->active;
1700  }
1701 
1702  public static function _lookupActive(int $a_usr_id): bool
1703  {
1704  global $DIC;
1705 
1706  $ilDB = $DIC['ilDB'];
1707 
1708  $query = 'SELECT usr_id FROM usr_data ' .
1709  'WHERE active = ' . $ilDB->quote(1, 'integer') . ' ' .
1710  'AND usr_id = ' . $ilDB->quote($a_usr_id, 'integer');
1711  $res = $ilDB->query($query);
1712  while ($res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
1713  return true;
1714  }
1715  return false;
1716  }
1717 
1723  public function syncActive(): void
1724  {
1725  $storedActive = 0;
1726  if ($this->getStoredActive($this->id)) {
1727  $storedActive = 1;
1728  }
1729 
1730  $currentActive = 0;
1731  if ($this->active) {
1732  $currentActive = 1;
1733  }
1734 
1735  if ((!empty($storedActive) && empty($currentActive)) ||
1736  (empty($storedActive) && !empty($currentActive))) {
1737  $this->setActive($currentActive, self::getUserIdByLogin(self::getLoginFromAuth()));
1738  }
1739  }
1740 
1744  public function getStoredActive(int $a_id): bool
1745  {
1746  return (bool) self::_lookup($a_id, "active");
1747  }
1748 
1749  public function setSkin(string $a_str): void
1750  {
1751  $this->skin = $a_str;
1752  }
1753 
1754  public function setTimeLimitOwner(int $a_owner): void
1755  {
1756  $this->time_limit_owner = $a_owner;
1757  }
1758 
1759  public function getTimeLimitOwner(): int
1760  {
1761  return $this->time_limit_owner ?: 7;
1762  }
1763 
1764  public function setTimeLimitFrom(?int $a_from): void
1765  {
1766  $this->time_limit_from = $a_from;
1767  }
1768 
1769  public function getTimeLimitFrom(): ?int
1770  {
1771  return $this->time_limit_from;
1772  }
1773 
1774  public function setTimeLimitUntil(?int $a_until): void
1775  {
1776  $this->time_limit_until = $a_until;
1777  }
1778 
1779  public function getTimeLimitUntil(): ?int
1780  {
1781  return $this->time_limit_until;
1782  }
1783 
1784  public function setTimeLimitUnlimited(bool $a_unlimited): void
1785  {
1786  $this->time_limit_unlimited = $a_unlimited;
1787  }
1788 
1789  public function getTimeLimitUnlimited(): bool
1790  {
1792  }
1793 
1794  public function setTimeLimitMessage(string $a_time_limit_message): void
1795  {
1796  $this->time_limit_message = $a_time_limit_message;
1797  }
1798 
1799  public function getTimeLimitMessage(): string
1800  {
1802  }
1803 
1804  public function setLoginAttempts(int $a_login_attempts): void
1805  {
1806  $this->login_attempts = $a_login_attempts;
1807  }
1808 
1809  public function getLoginAttempts(): int
1810  {
1811  return $this->login_attempts;
1812  }
1813 
1814  public function checkTimeLimit(): bool
1815  {
1816  if ($this->getTimeLimitUnlimited()) {
1817  return true;
1818  }
1819  if ($this->getTimeLimitFrom() < time() and $this->getTimeLimitUntil() > time()) {
1820  return true;
1821  }
1822  return false;
1823  }
1824 
1825  public function setProfileIncomplete(bool $a_prof_inc): void
1826  {
1827  $this->profile_incomplete = $a_prof_inc;
1828  }
1829 
1830  public function getProfileIncomplete(): bool
1831  {
1832  if ($this->id == ANONYMOUS_USER_ID) {
1833  return false;
1834  }
1836  }
1837 
1838  public function isPasswordChangeDemanded(): bool
1839  {
1840  if ($this->id == ANONYMOUS_USER_ID) {
1841  return false;
1842  }
1843 
1844  if ($this->id == SYSTEM_USER_ID) {
1845  if (
1846  \ilUserPasswordManager::getInstance()->verifyPassword($this, base64_decode('aG9tZXI=')) &&
1848  ) {
1849  return true;
1850  } else {
1851  return false;
1852  }
1853  }
1854 
1855  $security = ilSecuritySettings::_getInstance();
1856 
1857  $authModeAllowsPasswordChange = !ilAuthUtils::_needsExternalAccountByAuthMode($this->getAuthMode(true));
1858  $passwordResetOnFirstLogin = (
1859  $security->isPasswordChangeOnFirstLoginEnabled() &&
1860  $this->getLastPasswordChangeTS() == 0 && $this->is_self_registered == false
1861  );
1862  $passwordResetOnChangedPolicy = $this->getPasswordPolicyResetStatus();
1863 
1864  return ($authModeAllowsPasswordChange && ($passwordResetOnFirstLogin || $passwordResetOnChangedPolicy));
1865  }
1866 
1867  public function isPasswordExpired(): bool
1868  {
1869  if ($this->id == ANONYMOUS_USER_ID) {
1870  return false;
1871  }
1872 
1873  $security = ilSecuritySettings::_getInstance();
1874  if ($this->getLastPasswordChangeTS() > 0) {
1875  $max_pass_age = $security->getPasswordMaxAge();
1876  if ($max_pass_age > 0) {
1877  $max_pass_age_ts = ($max_pass_age * 86400);
1878  $pass_change_ts = $this->getLastPasswordChangeTS();
1879  $current_ts = time();
1880 
1881  if (($current_ts - $pass_change_ts) > $max_pass_age_ts) {
1883  return true;
1884  }
1885  }
1886  }
1887  }
1888 
1889  return false;
1890  }
1891 
1892  public function getPasswordAge(): int
1893  {
1894  $current_ts = time();
1895  $pass_change_ts = $this->getLastPasswordChangeTS();
1896  $password_age = (int) (($current_ts - $pass_change_ts) / 86400);
1897  return $password_age;
1898  }
1899 
1900  public function setLastPasswordChangeToNow(): bool
1901  {
1902  global $DIC;
1903 
1904  $ilDB = $DIC['ilDB'];
1905 
1906  $this->setLastPasswordChangeTS(time());
1907 
1908  $query = "UPDATE usr_data SET last_password_change = %s " .
1909  "WHERE usr_id = %s";
1910  $affected = $ilDB->manipulateF(
1911  $query,
1912  ['integer','integer'],
1913  [$this->getLastPasswordChangeTS(),$this->id]
1914  );
1915  if ($affected) {
1916  return true;
1917  } else {
1918  return false;
1919  }
1920  }
1921 
1922  public function resetLastPasswordChange(): bool
1923  {
1924  $ilDB = $this->db;
1925 
1926  $query = "UPDATE usr_data SET last_password_change = 0 " .
1927  "WHERE usr_id = %s";
1928  $affected = $ilDB->manipulateF(
1929  $query,
1930  ['integer'],
1931  [$this->getId()]
1932  );
1933  if ($affected) {
1934  return true;
1935  } else {
1936  return false;
1937  }
1938  }
1939 
1940  public function setLatitude(?string $a_latitude): void
1941  {
1942  $this->latitude = $a_latitude;
1943  }
1944 
1945  public function getLatitude(): ?string
1946  {
1947  return $this->latitude;
1948  }
1949 
1950  public function setLongitude(?string $a_longitude): void
1951  {
1952  $this->longitude = $a_longitude;
1953  }
1954 
1955  public function getLongitude(): ?string
1956  {
1957  return $this->longitude;
1958  }
1959 
1960  public function setLocationZoom(?int $a_locationzoom): void
1961  {
1962  $this->loc_zoom = $a_locationzoom;
1963  }
1964 
1965  public function getLocationZoom(): ?int
1966  {
1967  return $this->loc_zoom;
1968  }
1969 
1970  public function getAvatarRid(): ?string
1971  {
1972  return $this->avatar_rid;
1973  }
1974 
1975  public function setAvatarRid(?string $avatar_rid): void
1976  {
1977  $this->avatar_rid = $avatar_rid;
1978  }
1979 
1980 
1981  public static function hasActiveSession(
1982  int $a_user_id,
1983  string $a_session_id
1984  ): bool {
1985  global $DIC;
1986 
1987  $ilDB = $DIC['ilDB'];
1988 
1989  $set = $ilDB->queryf(
1990  '
1991  SELECT COUNT(*) session_count
1992  FROM usr_session WHERE user_id = %s AND expires > %s AND session_id != %s ',
1993  ['integer', 'integer', 'text'],
1994  [$a_user_id, time(), $a_session_id]
1995  );
1996  $row = $ilDB->fetchAssoc($set);
1997  return (bool) $row['session_count'];
1998  }
1999 
2003  public function checkUserId(): bool
2004  {
2005  $login = self::getLoginFromAuth();
2006  $id = self::_lookupId($login);
2007  if ($id > 0) {
2008  return $id;
2009  }
2010  return false;
2011  }
2012 
2016  private static function getLoginFromAuth(): string
2017  {
2018  $uid = $GLOBALS['DIC']['ilAuthSession']->getUserId();
2019  $login = self::_lookupLogin($uid);
2020 
2021  // BEGIN WebDAV: Strip Microsoft Domain Names from logins
2023  $login = self::toUsernameWithoutDomain($login);
2024  }
2025  return $login;
2026  }
2027 
2032  public static function toUsernameWithoutDomain(string $a_login): string
2033  {
2034  // Remove all characters including the last slash or the last backslash
2035  // in the username
2036  $pos = strrpos($a_login, '/');
2037  $pos2 = strrpos($a_login, '\\');
2038  if ($pos === false || $pos < $pos2) {
2039  $pos = $pos2;
2040  }
2041  if (is_int($pos)) {
2042  $a_login = substr($a_login, $pos + 1);
2043  }
2044  return $a_login;
2045  }
2046 
2047  /*
2048  * check to see if current user has been made active
2049  */
2050  public function isCurrentUserActive(): bool
2051  {
2052  $ilDB = $this->db;
2053 
2054  $login = self::getLoginFromAuth();
2055  $set = $ilDB->queryF(
2056  "SELECT active FROM usr_data WHERE login= %s",
2057  ["text"],
2058  [$login]
2059  );
2060  //query has got a result
2061  if ($rec = $ilDB->fetchAssoc($set)) {
2062  if ($rec["active"]) {
2063  return true;
2064  }
2065  }
2066 
2067  return false;
2068  }
2069 
2070  public static function getUserIdByLogin(string $a_login): int
2071  {
2072  return (int) self::_lookupId($a_login);
2073  }
2074 
2078  public static function getUserIdsByEmail(string $a_email): array
2079  {
2080  global $DIC;
2081 
2082  $ilDB = $DIC->database();
2083 
2084  $res = $ilDB->queryF(
2085  "SELECT usr_id FROM usr_data " .
2086  "WHERE email = %s and active = 1",
2087  ["text"],
2088  [$a_email]
2089  );
2090  $ids = [];
2091  while ($row = $ilDB->fetchObject($res)) {
2092  $ids[] = (int) $row->usr_id;
2093  }
2094 
2095  return $ids;
2096  }
2097 
2098 
2102  public static function getUserLoginsByEmail(string $a_email): array
2103  {
2104  global $DIC;
2105 
2106  $ilDB = $DIC->database();
2107 
2108  $res = $ilDB->queryF(
2109  "SELECT login FROM usr_data " .
2110  "WHERE email = %s and active = 1",
2111  ["text"],
2112  [$a_email]
2113  );
2114  $ids = [];
2115  while ($row = $ilDB->fetchObject($res)) {
2116  $ids[] = $row->login;
2117  }
2118 
2119  return $ids;
2120  }
2121 
2122  public function getLoginByUserId(int $a_userid): ?string
2123  {
2124  $login = self::_lookupLogin($a_userid);
2125  return $login ?: null;
2126  }
2127 
2131  public static function getAllUserLogins(): array
2132  {
2136  global $DIC;
2137 
2138  $ilDB = $DIC['ilDB'];
2139 
2140  $logins = [];
2141 
2142  $res = $ilDB->query(
2143  "SELECT login FROM usr_data WHERE " . $ilDB->in('usr_id', [ANONYMOUS_USER_ID], true, 'integer')
2144  );
2145  while ($row = $ilDB->fetchAssoc($res)) {
2146  $logins[] = $row['login'];
2147  }
2148 
2149  return $logins;
2150  }
2151 
2156  public static function _readUsersProfileData(array $a_user_ids): array
2157  {
2158  global $DIC;
2159 
2160  $ilDB = $DIC['ilDB'];
2161  $res = $ilDB->query("SELECT * FROM usr_data WHERE " .
2162  $ilDB->in("usr_id", $a_user_ids, false, "integer"));
2163  $user_data = [];
2164  while ($row = $ilDB->fetchAssoc($res)) {
2165  $user_data[$row['usr_id']] = $row;
2166  }
2167  return $user_data;
2168  }
2169 
2175  public static function _getAllUserData(
2176  ?array $a_fields = null,
2177  int $active = -1
2178  ): array {
2179  global $DIC;
2180 
2181  $ilDB = $DIC['ilDB'];
2182 
2183  $result_arr = [];
2184 
2185  if ($a_fields !== null and is_array($a_fields)) {
2186  if (count($a_fields) == 0) {
2187  $select = "*";
2188  } else {
2189  if (($usr_id_field = array_search("usr_id", $a_fields)) !== false) {
2190  unset($a_fields[$usr_id_field]);
2191  }
2192 
2193  $select = implode(",", $a_fields) . ",usr_data.usr_id";
2194  // online time
2195  if (in_array('online_time', $a_fields)) {
2196  $select .= ",ut_online.online_time ";
2197  }
2198  }
2199 
2200  $q = "SELECT " . $select . " FROM usr_data ";
2201 
2202  // Add online_time if desired
2203  // Need left join here to show users that never logged in
2204  if (in_array('online_time', $a_fields)) {
2205  $q .= "LEFT JOIN ut_online ON usr_data.usr_id = ut_online.usr_id ";
2206  }
2207 
2208  switch ($active) {
2209  case 0:
2210  case 1:
2211  $q .= "WHERE active = " . $ilDB->quote($active, "integer");
2212  break;
2213  case 2:
2214  $q .= "WHERE time_limit_unlimited= " . $ilDB->quote(0, "integer");
2215  break;
2216  case 3:
2217  $qtemp = $q . ", rbac_ua, object_data WHERE rbac_ua.rol_id = object_data.obj_id AND " .
2218  $ilDB->like("object_data.title", "text", "%crs%") . " AND usr_data.usr_id = rbac_ua.usr_id";
2219  $r = $ilDB->query($qtemp);
2220  $course_users = [];
2221  while ($row = $ilDB->fetchAssoc($r)) {
2222  $course_users[] = $row["usr_id"];
2223  }
2224  if (count($course_users)) {
2225  $q .= " WHERE " . $ilDB->in("usr_data.usr_id", $course_users, true, "integer") . " ";
2226  } else {
2227  return $result_arr;
2228  }
2229  break;
2230  case 4:
2231  $session_data = ilSession::get('user_filter_data');
2232  $date = date("Y-m-d H:i:s", mktime(0, 0, 0, $session_data["m"], $session_data["d"], $session_data["y"]));
2233  $q .= " AND last_login < " . $ilDB->quote($date, "timestamp");
2234  break;
2235  case 5:
2236  $ref_id = ilSession::get('user_filter_data');
2237  if ($ref_id) {
2238  $q .= " LEFT JOIN obj_members ON usr_data.usr_id = obj_members.usr_id " .
2239  "WHERE obj_members.obj_id = (SELECT obj_id FROM object_reference " .
2240  "WHERE ref_id = " . $ilDB->quote($ref_id, "integer") . ") ";
2241  }
2242  break;
2243  case 6:
2244  global $DIC;
2245 
2246  $rbacreview = $DIC['rbacreview'];
2247  $ref_id = ilSession::get('user_filter_data');
2248  if ($ref_id) {
2249  $local_roles = $rbacreview->getRolesOfRoleFolder($ref_id, false);
2250  if (is_array($local_roles) && count($local_roles)) {
2251  $q .= " LEFT JOIN rbac_ua ON usr_data.usr_id = rbac_ua.usr_id WHERE " .
2252  $ilDB->in("rbac_ua.rol_id", $local_roles, false, "integer") . " ";
2253  }
2254  }
2255  break;
2256  case 7:
2257  $rol_id = ilSession::get('user_filter_data');
2258  if ($rol_id) {
2259  $q .= " LEFT JOIN rbac_ua ON usr_data.usr_id = rbac_ua.usr_id WHERE rbac_ua.rol_id = " .
2260  $ilDB->quote($rol_id, "integer");
2261  }
2262  break;
2263  }
2264  $r = $ilDB->query($q);
2265 
2266  while ($row = $ilDB->fetchAssoc($r)) {
2267  $result_arr[] = $row;
2268  }
2269  }
2270 
2271  return $result_arr;
2272  }
2273 
2274  public static function _getNumberOfUsersForStyle(
2275  string $a_skin,
2276  string $a_style
2277  ): int {
2278  global $DIC;
2279 
2280  $ilDB = $DIC['ilDB'];
2281 
2282  $q = "SELECT count(*) as cnt FROM usr_pref up1, usr_pref up2 " .
2283  " WHERE up1.keyword= " . $ilDB->quote("style", "text") .
2284  " AND up1.value= " . $ilDB->quote($a_style, "text") .
2285  " AND up2.keyword= " . $ilDB->quote("skin", "text") .
2286  " AND up2.value= " . $ilDB->quote($a_skin, "text") .
2287  " AND up1.usr_id = up2.usr_id ";
2288 
2289  $cnt_set = $ilDB->query($q);
2290 
2291  $cnt_rec = $ilDB->fetchAssoc($cnt_set);
2292 
2293  return (int) $cnt_rec["cnt"];
2294  }
2295 
2299  public static function _getAllUserAssignedStyles(): array
2300  {
2301  global $DIC;
2302 
2303  $ilDB = $DIC['ilDB'];
2304 
2305  $q = "SELECT DISTINCT up1.value style, up2.value skin FROM usr_pref up1, usr_pref up2 " .
2306  " WHERE up1.keyword = " . $ilDB->quote("style", "text") .
2307  " AND up2.keyword = " . $ilDB->quote("skin", "text") .
2308  " AND up1.usr_id = up2.usr_id";
2309 
2310  $sty_set = $ilDB->query($q);
2311 
2312  $styles = [];
2313  while ($sty_rec = $ilDB->fetchAssoc($sty_set)) {
2314  $styles[] = $sty_rec["skin"] . ":" . $sty_rec["style"];
2315  }
2316 
2317  return $styles;
2318  }
2319 
2320  public static function _moveUsersToStyle(
2321  string $a_from_skin,
2322  string $a_from_style,
2323  string $a_to_skin,
2324  string $a_to_style
2325  ): void {
2326  global $DIC;
2327 
2328  $ilDB = $DIC['ilDB'];
2329 
2330  $q = "SELECT up1.usr_id usr_id FROM usr_pref up1, usr_pref up2 " .
2331  " WHERE up1.keyword= " . $ilDB->quote("style", "text") .
2332  " AND up1.value= " . $ilDB->quote($a_from_style, "text") .
2333  " AND up2.keyword= " . $ilDB->quote("skin", "text") .
2334  " AND up2.value= " . $ilDB->quote($a_from_skin, "text") .
2335  " AND up1.usr_id = up2.usr_id ";
2336 
2337  $usr_set = $ilDB->query($q);
2338 
2339  while ($usr_rec = $ilDB->fetchAssoc($usr_set)) {
2340  self::_writePref($usr_rec["usr_id"], "skin", $a_to_skin);
2341  self::_writePref($usr_rec["usr_id"], "style", $a_to_style);
2342  }
2343  }
2344 
2345 
2351 
2358  public function addObjectToClipboard(
2359  int $a_item_id,
2360  string $a_type,
2361  string $a_title,
2362  int $a_parent = 0,
2363  string $a_time = "",
2364  int $a_order_nr = 0
2365  ): void {
2366  global $DIC;
2367 
2368  $ilDB = $DIC['ilDB'];
2369 
2370  if ($a_time === "") {
2371  $a_time = date("Y-m-d H:i:s");
2372  }
2373 
2374  $item_set = $ilDB->queryF(
2375  "SELECT * FROM personal_clipboard WHERE " .
2376  "parent = %s AND item_id = %s AND type = %s AND user_id = %s",
2377  ["integer", "integer", "text", "integer"],
2378  [0, $a_item_id, $a_type, $this->getId()]
2379  );
2380 
2381  // only insert if item is not already in clipboard
2382  if (!$item_set->fetchRow()) {
2383  $ilDB->manipulateF(
2384  "INSERT INTO personal_clipboard " .
2385  "(item_id, type, user_id, title, parent, insert_time, order_nr) VALUES " .
2386  " (%s,%s,%s,%s,%s,%s,%s)",
2387  ["integer", "text", "integer", "text", "integer", "timestamp", "integer"],
2388  [$a_item_id, $a_type, $this->getId(), $a_title, $a_parent, $a_time, $a_order_nr]
2389  );
2390  } else {
2391  $ilDB->manipulateF(
2392  "UPDATE personal_clipboard SET insert_time = %s " .
2393  "WHERE user_id = %s AND item_id = %s AND type = %s AND parent = 0",
2394  ["timestamp", "integer", "integer", "text"],
2395  [$a_time, $this->getId(), $a_item_id, $a_type]
2396  );
2397  }
2398  }
2399 
2404  public function addToPCClipboard(
2405  string $a_content,
2406  string $a_time,
2407  int $a_nr
2408  ): void {
2409  $ilDB = $this->db;
2410  if ($a_time == 0) {
2411  $a_time = date("Y-m-d H:i:s");
2412  }
2413  ilSession::set("user_pc_clip", true);
2414  $ilDB->insert("personal_pc_clipboard", [
2415  "user_id" => ["integer", $this->getId()],
2416  "content" => ["clob", $a_content],
2417  "insert_time" => ["timestamp", $a_time],
2418  "order_nr" => ["integer", $a_nr]
2419  ]);
2420  }
2421 
2426  public function getPCClipboardContent(): array // Missing array type.
2427  {
2428  $ilDB = $this->db;
2429 
2430  if (!ilSession::get("user_pc_clip")) {
2431  return [];
2432  }
2433 
2434  $set = $ilDB->queryF("SELECT MAX(insert_time) mtime FROM personal_pc_clipboard " .
2435  " WHERE user_id = %s", ["integer"], [$this->getId()]);
2436  $row = $ilDB->fetchAssoc($set);
2437 
2438  $set = $ilDB->queryF(
2439  "SELECT * FROM personal_pc_clipboard " .
2440  " WHERE user_id = %s AND insert_time = %s ORDER BY order_nr ASC",
2441  ["integer", "timestamp"],
2442  [$this->getId(), $row["mtime"]]
2443  );
2444  $content = [];
2445  while ($row = $ilDB->fetchAssoc($set)) {
2446  $content[] = $row["content"];
2447  }
2448 
2449  return $content;
2450  }
2451 
2455  public function clipboardHasObjectsOfType(string $a_type): bool
2456  {
2457  global $DIC;
2458 
2459  $ilDB = $DIC['ilDB'];
2460 
2461  $set = $ilDB->queryF(
2462  "SELECT * FROM personal_clipboard WHERE " .
2463  "parent = %s AND type = %s AND user_id = %s",
2464  ["integer", "text", "integer"],
2465  [0, $a_type, $this->getId()]
2466  );
2467  if ($ilDB->fetchAssoc($set)) {
2468  return true;
2469  }
2470 
2471  return false;
2472  }
2473 
2474  public function clipboardDeleteObjectsOfType(string $a_type): void
2475  {
2476  $ilDB = $this->db;
2477 
2478  $ilDB->manipulateF(
2479  "DELETE FROM personal_clipboard WHERE " .
2480  "type = %s AND user_id = %s",
2481  ["text", "integer"],
2482  [$a_type, $this->getId()]
2483  );
2484  }
2485 
2486  public function clipboardDeleteAll(): void
2487  {
2488  global $DIC;
2489 
2490  $ilDB = $DIC['ilDB'];
2491 
2492  $ilDB->manipulateF("DELETE FROM personal_clipboard WHERE " .
2493  "user_id = %s", ["integer"], [$this->getId()]);
2494  }
2495 
2499  public function getClipboardObjects(
2500  string $a_type = "",
2501  bool $a_top_nodes_only = false
2502  ): array {
2503  global $DIC;
2504 
2505  $ilDB = $DIC['ilDB'];
2506 
2507  $par = "";
2508  if ($a_top_nodes_only) {
2509  $par = " AND parent = " . $ilDB->quote(0, "integer") . " ";
2510  }
2511 
2512  $type_str = ($a_type != "")
2513  ? " AND type = " . $ilDB->quote($a_type, "text") . " "
2514  : "";
2515  $q = "SELECT * FROM personal_clipboard WHERE " .
2516  "user_id = " . $ilDB->quote($this->getId(), "integer") . " " .
2517  $type_str . $par .
2518  " ORDER BY order_nr";
2519  $objs = $ilDB->query($q);
2520  $objects = [];
2521  while ($obj = $ilDB->fetchAssoc($objs)) {
2522  if ($obj["type"] == "mob") {
2523  $obj["title"] = ilObject::_lookupTitle($obj["item_id"]);
2524  if (ilObject::_lookupType((int) $obj["item_id"]) !== "mob") {
2525  continue;
2526  }
2527  }
2528  if ($obj["type"] == "incl") {
2529  $obj["title"] = ilMediaPoolPage::lookupTitle($obj["item_id"]);
2530  if (!ilPageObject::_exists("mep", (int) $obj["item_id"], "-")) {
2531  continue;
2532  }
2533  }
2534  $objects[] = ["id" => $obj["item_id"],
2535  "type" => $obj["type"], "title" => $obj["title"],
2536  "insert_time" => $obj["insert_time"]];
2537  }
2538  return $objects;
2539  }
2540 
2544  public function getClipboardChilds(
2545  int $a_parent,
2546  string $a_insert_time
2547  ): array {
2548  global $DIC;
2549 
2550  $ilDB = $DIC['ilDB'];
2551  $ilUser = $DIC['ilUser'];
2552 
2553  $objs = $ilDB->queryF(
2554  "SELECT * FROM personal_clipboard WHERE " .
2555  "user_id = %s AND parent = %s AND insert_time = %s " .
2556  " ORDER BY order_nr",
2557  ["integer", "integer", "timestamp"],
2558  [$ilUser->getId(), $a_parent, $a_insert_time]
2559  );
2560  $objects = [];
2561  while ($obj = $ilDB->fetchAssoc($objs)) {
2562  if ($obj["type"] == "mob") {
2563  $obj["title"] = ilObject::_lookupTitle($obj["item_id"]);
2564  }
2565  $objects[] = ["id" => $obj["item_id"],
2566  "type" => $obj["type"], "title" => $obj["title"], "insert_time" => $obj["insert_time"]];
2567  }
2568  return $objects;
2569  }
2570 
2575  public static function _getUsersForClipboadObject(
2576  string $a_type,
2577  int $a_id
2578  ): array {
2579  global $DIC;
2580 
2581  $ilDB = $DIC['ilDB'];
2582 
2583  $q = "SELECT DISTINCT user_id FROM personal_clipboard WHERE " .
2584  "item_id = " . $ilDB->quote($a_id, "integer") . " AND " .
2585  "type = " . $ilDB->quote($a_type, "text");
2586  $user_set = $ilDB->query($q);
2587  $users = [];
2588  while ($user_rec = $ilDB->fetchAssoc($user_set)) {
2589  $users[] = (int) $user_rec["user_id"];
2590  }
2591 
2592  return $users;
2593  }
2594 
2595  public function removeObjectFromClipboard(
2596  int $a_item_id,
2597  string $a_type
2598  ): void {
2599  $ilDB = $this->db;
2600 
2601  $q = "DELETE FROM personal_clipboard WHERE " .
2602  "item_id = " . $ilDB->quote($a_item_id, "integer") .
2603  " AND type = " . $ilDB->quote($a_type, "text") . " " .
2604  " AND user_id = " . $ilDB->quote($this->getId(), "integer");
2605  $ilDB->manipulate($q);
2606  }
2607 
2608  public static function _getImportedUserId(
2609  string $i2_id
2610  ): int {
2611  global $DIC;
2612 
2613  $ilDB = $DIC['ilDB'];
2614 
2615  $query = "SELECT obj_id FROM object_data WHERE import_id = " .
2616  $ilDB->quote($i2_id, "text");
2617 
2618  $res = $ilDB->query($query);
2619  $id = 0;
2620  while ($row = $ilDB->fetchObject($res)) {
2621  $id = (int) $row->obj_id;
2622  }
2623  return $id;
2624  }
2625 
2629  public static function lookupOrgUnitsRepresentation(
2630  int $a_usr_id
2631  ): string {
2632  return ilOrgUnitPathStorage::getTextRepresentationOfUsersOrgUnits($a_usr_id);
2633  }
2634 
2635  public function getOrgUnitsRepresentation(): string
2636  {
2637  return self::lookupOrgUnitsRepresentation($this->getId());
2638  }
2639 
2640  public function setAuthMode(?string $a_str): void
2641  {
2642  $this->auth_mode = $a_str;
2643  }
2644 
2645  public function getAuthMode(bool $a_auth_key = false): ?string
2646  {
2647  if (!$a_auth_key) {
2648  return $this->auth_mode;
2649  }
2650  return ilAuthUtils::_getAuthMode($this->auth_mode);
2651  }
2652 
2653  public function setExternalAccount(string $a_str): void
2654  {
2655  $this->ext_account = $a_str;
2656  }
2657 
2658  public function getExternalAccount(): string
2659  {
2660  return $this->ext_account;
2661  }
2662 
2669  public static function _getExternalAccountsByAuthMode(
2670  string $a_auth_mode,
2671  bool $a_read_auth_default = false
2672  ): array {
2673  global $DIC;
2674 
2675  $ilDB = $DIC['ilDB'];
2676  $ilSetting = $DIC['ilSetting'];
2677 
2678  $q = "SELECT login,usr_id,ext_account,auth_mode FROM usr_data " .
2679  "WHERE auth_mode = %s";
2680  $types[] = "text";
2681  $values[] = $a_auth_mode;
2682  if ($a_read_auth_default and ilAuthUtils::_getAuthModeName($ilSetting->get('auth_mode', ilAuthUtils::AUTH_LOCAL)) == $a_auth_mode) {
2683  $q .= " OR auth_mode = %s ";
2684  $types[] = "text";
2685  $values[] = 'default';
2686  }
2687 
2688  $res = $ilDB->queryF($q, $types, $values);
2689  $accounts = [];
2690  while ($row = $ilDB->fetchObject($res)) {
2691  if ($row->auth_mode == 'default') {
2692  $accounts[$row->usr_id] = $row->login;
2693  } else {
2694  $accounts[$row->usr_id] = $row->ext_account;
2695  }
2696  }
2697  return $accounts;
2698  }
2699 
2700  public static function _toggleActiveStatusOfUsers(
2701  array $a_usr_ids,
2702  bool $a_status
2703  ): void {
2704  global $DIC;
2705 
2706  $ilDB = $DIC['ilDB'];
2707 
2708  if ($a_status) {
2709  $q = "UPDATE usr_data SET active = 1, inactivation_date = NULL WHERE " .
2710  $ilDB->in("usr_id", $a_usr_ids, false, "integer");
2711  $ilDB->manipulate($q);
2712  } else {
2713  $usrId_IN_usrIds = $ilDB->in("usr_id", $a_usr_ids, false, "integer");
2714 
2715  $q = "UPDATE usr_data SET active = 0 WHERE $usrId_IN_usrIds";
2716  $ilDB->manipulate($q);
2717 
2718  $queryString = "
2719  UPDATE usr_data
2720  SET inactivation_date = %s
2721  WHERE inactivation_date IS NULL
2722  AND $usrId_IN_usrIds
2723  ";
2724  $ilDB->manipulateF($queryString, ['timestamp'], [ilUtil::now()]);
2725  }
2726  }
2727 
2728  public static function _lookupAuthMode(int $a_usr_id): string
2729  {
2730  return (string) self::_lookup($a_usr_id, "auth_mode");
2731  }
2732 
2737  public static function _checkExternalAuthAccount(
2738  string $a_auth,
2739  string $a_account,
2740  bool $tryFallback = true
2741  ): ?string {
2742  $db = $GLOBALS['DIC']->database();
2743  $settings = $GLOBALS['DIC']->settings();
2744 
2745  // Check directly with auth_mode
2746  $r = $db->queryF(
2747  "SELECT * FROM usr_data WHERE " .
2748  " ext_account = %s AND auth_mode = %s",
2749  ["text", "text"],
2750  [$a_account, $a_auth]
2751  );
2752  if ($usr = $db->fetchAssoc($r)) {
2753  return $usr["login"];
2754  }
2755 
2756  if (!$tryFallback) {
2757  return null;
2758  }
2759 
2760  // For compatibility, check for login (no ext_account entry given)
2761  $res = $db->queryF(
2762  "SELECT login FROM usr_data " .
2763  "WHERE login = %s AND auth_mode = %s AND (ext_account IS NULL OR ext_account = '') ",
2764  ["text", "text"],
2765  [$a_account, $a_auth]
2766  );
2767  if ($usr = $db->fetchAssoc($res)) {
2768  return $usr['login'];
2769  }
2770 
2771  // If auth_default == $a_auth => check for login
2772  if (ilAuthUtils::_getAuthModeName($settings->get('auth_mode')) == $a_auth) {
2773  $res = $db->queryF(
2774  "SELECT login FROM usr_data WHERE " .
2775  " ext_account = %s AND auth_mode = %s",
2776  ["text", "text"],
2777  [$a_account, "default"]
2778  );
2779  if ($usr = $db->fetchAssoc($res)) {
2780  return $usr["login"];
2781  }
2782  // Search for login (no ext_account given)
2783  $res = $db->queryF(
2784  "SELECT login FROM usr_data " .
2785  "WHERE login = %s AND (ext_account IS NULL OR ext_account = '') AND auth_mode = %s",
2786  ["text", "text"],
2787  [$a_account, "default"]
2788  );
2789  if ($usr = $db->fetchAssoc($res)) {
2790  return $usr["login"];
2791  }
2792  }
2793  return null;
2794  }
2795 
2799  public static function _getNumberOfUsersPerAuthMode(): array // Missing array type.
2800  {
2801  global $DIC;
2802 
2803  $ilDB = $DIC['ilDB'];
2804 
2805  $r = $ilDB->query("SELECT count(*) AS cnt, auth_mode FROM usr_data " .
2806  "GROUP BY auth_mode");
2807  $cnt_arr = [];
2808  while ($cnt = $ilDB->fetchAssoc($r)) {
2809  $cnt_arr[$cnt["auth_mode"]] = (int) $cnt["cnt"];
2810  }
2811 
2812  return $cnt_arr;
2813  }
2814 
2815  public static function _getLocalAccountsForEmail(string $a_email): array // Missing array type.
2816  {
2817  global $DIC;
2818 
2819  $ilDB = $DIC['ilDB'];
2820  $ilSetting = $DIC['ilSetting'];
2821 
2822  // default set to local (1)?
2823 
2824  $q = "SELECT * FROM usr_data WHERE " .
2825  " email = %s AND (auth_mode = %s ";
2826  $types = ["text", "text"];
2827  $values = [$a_email, "local"];
2828 
2829  if ($ilSetting->get("auth_mode") == 1) {
2830  $q .= " OR auth_mode = %s";
2831  $types[] = "text";
2832  $values[] = "default";
2833  }
2834 
2835  $q .= ")";
2836 
2837  $users = [];
2838  $usr_set = $ilDB->queryF($q, $types, $values);
2839  while ($usr_rec = $ilDB->fetchAssoc($usr_set)) {
2840  $users[$usr_rec["usr_id"]] = $usr_rec["login"];
2841  }
2842 
2843  return $users;
2844  }
2845 
2846 
2851  public static function _uploadPersonalPicture(
2852  string $tmp_file,
2853  int $obj_id
2854  ): bool {
2855  global $DIC;
2856  $user = new ilObjUser($obj_id);
2857  $stakeholder = new ilUserProfilePictureStakeholder();
2858  $stakeholder->setOwner($user->getId());
2859  $stream = Streams::ofResource(fopen($tmp_file, 'rb'));
2860 
2861  if ($user->getAvatarRid() !== null && $user->getAvatarRid() !== ilObjUser::NO_AVATAR_RID) {
2862  $rid = $DIC->resourceStorage()->manage()->find($user->getAvatarRid());
2863  // append profile picture
2864  $DIC->resourceStorage()->manage()->replaceWithStream(
2865  $rid,
2866  $stream,
2867  $stakeholder
2868  );
2869  } else {
2870  // new profile picture
2871  $rid = $DIC->resourceStorage()->manage()->stream(
2872  $stream,
2873  $stakeholder
2874  );
2875  }
2876 
2877  $user->setAvatarRid($rid->serialize());
2878  $user->update();
2879  return true;
2880  }
2881 
2882 
2887  public function getPersonalPicturePath(
2888  string $a_size = "small",
2889  bool $a_force_pic = false
2890  ): string {
2891  if (isset(self::$personal_image_cache[$this->getId()][$a_size][(int) $a_force_pic])) {
2892  return self::$personal_image_cache[$this->getId()][$a_size][(int) $a_force_pic];
2893  }
2894 
2895  self::$personal_image_cache[$this->getId()][$a_size][(int) $a_force_pic] = self::_getPersonalPicturePath($this->getId(), $a_size, $a_force_pic);
2896 
2897  return self::$personal_image_cache[$this->getId()][$a_size][(int) $a_force_pic];
2898  }
2899 
2900  public function hasProfilePicture(): bool
2901  {
2902  return (new ilUserAvatarResolver($this->getId()))->hasProfilePicture();
2903  }
2904 
2905  public function getAvatar(): Avatar
2906  {
2907  return self::_getAvatar($this->getId());
2908  }
2909 
2910  public static function _getAvatar(int $a_usr_id): Avatar
2911  {
2912  $define = new ilUserAvatarResolver($a_usr_id ?: ANONYMOUS_USER_ID);
2913  $define->setSize('xsmall');
2914  return $define->getAvatar();
2915  }
2916 
2921  public static function _getPersonalPicturePath(
2922  int $a_usr_id,
2923  string $a_size = "small",
2924  bool $a_force_pic = false,
2925  bool $a_prevent_no_photo_image = false,
2926  bool $html_export = false
2927  ): string {
2928  $define = new ilUserAvatarResolver($a_usr_id);
2929  $define->setForcePicture($a_force_pic);
2930  $define->setSize($a_size);
2931  return $define->getLegacyPictureURL();
2932  }
2933 
2934  public static function copyProfilePicturesToDirectory(
2935  int $a_user_id,
2936  string $a_dir
2937  ): void {
2938  $a_dir = trim(str_replace("..", "", $a_dir));
2939  if ($a_dir == "" || !is_dir($a_dir)) {
2940  return;
2941  }
2942  // if profile picture is on IRSS
2943  global $DIC;
2944  $irss = $DIC->resourceStorage();
2945  $user = new ilObjUser($a_user_id);
2946  if ($user->getAvatarRid() !== null && $user->getAvatarRid() !== ilObjUser::NO_AVATAR_RID) {
2947  $rid = $irss->manage()->find($user->getAvatarRid());
2948  // Main Picture only is needed
2949  $stream = $irss->consume()->stream($rid)->getStream();
2950  $target = $a_dir . "/usr_" . $a_user_id . ".jpg";
2951  fwrite(fopen($target, 'wb'), (string) $stream);
2952 
2953  return;
2954  }
2955 
2956  // Legacy Picture Handling
2957  $webspace_dir = ilFileUtils::getWebspaceDir();
2958  $image_dir = $webspace_dir . "/usr_images";
2959  $images = [
2960  "upload_" . $a_user_id . "pic",
2961  "usr_" . $a_user_id . "." . "jpg",
2962  "usr_" . $a_user_id . "_small.jpg",
2963  "usr_" . $a_user_id . "_xsmall.jpg",
2964  "usr_" . $a_user_id . "_xxsmall.jpg",
2965  "upload_" . $a_user_id];
2966  foreach ($images as $image) {
2967  if (is_file($image_dir . "/" . $image)) {
2968  copy($image_dir . "/" . $image, $a_dir . "/" . $image);
2969  }
2970  }
2971  }
2972 
2973 
2974  public function removeUserPicture(
2975  bool $a_do_update = true
2976  ): void {
2977  if ($this->getAvatarRid() !== null && $this->getAvatarRid() !== self::NO_AVATAR_RID) {
2978  $rid = $this->irss->manage()->find($this->getAvatarRid());
2979  $this->irss->manage()->remove($rid, new ilUserProfilePictureStakeholder());
2980  }
2981 
2982  if ($a_do_update) {
2983  // remove user pref file name
2985  $this->setPref("profile_image", "");
2986  $this->update();
2987  }
2988  }
2989 
2990 
2991  public function setUserDefinedData(array $a_data): void // Missing array type.
2992  {
2993  foreach ($a_data as $field => $data) {
2994  $this->user_defined_data['f_' . $field] = $data;
2995  }
2996  }
2997 
2998  public function getUserDefinedData(): array // Missing array type.
2999  {
3000  return $this->user_defined_data ?: [];
3001  }
3002 
3003  public function updateUserDefinedFields(): void
3004  {
3005  $udata = new ilUserDefinedData($this->getId());
3006  foreach ($this->user_defined_data as $field => $value) {
3007  if ($field !== 'usr_id' && $value !== null) {
3008  $udata->set($field, $value);
3009  }
3010  }
3011  $udata->update();
3012  }
3013 
3014  public function readUserDefinedFields(): void
3015  {
3016  $udata = new ilUserDefinedData($this->getId());
3017  $this->user_defined_data = $udata->getAll();
3018  }
3019 
3020  public function deleteUserDefinedFieldEntries(): void
3021  {
3023  }
3024 
3029  public function getProfileAsString(ilLanguage $language): string
3030  {
3031  global $DIC;
3032 
3033  $rbacreview = $DIC['rbacreview'];
3034 
3035  $language->loadLanguageModule('registration');
3036  $language->loadLanguageModule('crs');
3037 
3038  $body = ($language->txt("login") . ": " . $this->getLogin() . "\n");
3039 
3040  if (strlen($this->getUTitle())) {
3041  $body .= ($language->txt("title") . ": " . $this->getUTitle() . "\n");
3042  }
3043  if (1 === strlen($this->getGender())) {
3044  $body .= ($language->txt("gender") . ": " . $language->txt('gender_' . strtolower($this->getGender())) . "\n");
3045  }
3046  if (strlen($this->getFirstname())) {
3047  $body .= ($language->txt("firstname") . ": " . $this->getFirstname() . "\n");
3048  }
3049  if (strlen($this->getLastname())) {
3050  $body .= ($language->txt("lastname") . ": " . $this->getLastname() . "\n");
3051  }
3052  if (strlen($this->getInstitution())) {
3053  $body .= ($language->txt("institution") . ": " . $this->getInstitution() . "\n");
3054  }
3055  if (strlen($this->getDepartment())) {
3056  $body .= ($language->txt("department") . ": " . $this->getDepartment() . "\n");
3057  }
3058  if (strlen($this->getStreet())) {
3059  $body .= ($language->txt("street") . ": " . $this->getStreet() . "\n");
3060  }
3061  if (strlen($this->getCity())) {
3062  $body .= ($language->txt("city") . ": " . $this->getCity() . "\n");
3063  }
3064  if (strlen($this->getZipcode())) {
3065  $body .= ($language->txt("zipcode") . ": " . $this->getZipcode() . "\n");
3066  }
3067  if (strlen($this->getCountry())) {
3068  $body .= ($language->txt("country") . ": " . $this->getCountry() . "\n");
3069  }
3070  if (strlen($this->getSelectedCountry())) {
3071  $body .= ($language->txt("sel_country") . ": " . $this->getSelectedCountry() . "\n");
3072  }
3073  if (strlen($this->getPhoneOffice())) {
3074  $body .= ($language->txt("phone_office") . ": " . $this->getPhoneOffice() . "\n");
3075  }
3076  if (strlen($this->getPhoneHome())) {
3077  $body .= ($language->txt("phone_home") . ": " . $this->getPhoneHome() . "\n");
3078  }
3079  if (strlen($this->getPhoneMobile())) {
3080  $body .= ($language->txt("phone_mobile") . ": " . $this->getPhoneMobile() . "\n");
3081  }
3082  if (strlen($this->getFax())) {
3083  $body .= ($language->txt("fax") . ": " . $this->getFax() . "\n");
3084  }
3085  if ($this->getEmail() !== '') {
3086  $body .= ($language->txt("email") . ": " . $this->getEmail() . "\n");
3087  }
3088  if ($this->getSecondEmail() !== null
3089  && $this->getSecondEmail() !== '') {
3090  $body .= ($language->txt("second_email") . ": " . $this->getSecondEmail() . "\n");
3091  }
3092  if (strlen($this->getHobby())) {
3093  $body .= ($language->txt("hobby") . ": " . $this->getHobby() . "\n");
3094  }
3095  if (strlen($this->getComment())) {
3096  $body .= ($language->txt("referral_comment") . ": " . $this->getComment() . "\n");
3097  }
3098  if (strlen($this->getMatriculation())) {
3099  $body .= ($language->txt("matriculation") . ": " . $this->getMatriculation() . "\n");
3100  }
3101  if (strlen($this->getCreateDate())) {
3106 
3107  $body .= ($language->txt("create_date") . ": " . $date . "\n");
3108  }
3109 
3110  $gr = [];
3111  foreach ($rbacreview->getGlobalRoles() as $role) {
3112  if ($rbacreview->isAssigned($this->getId(), $role)) {
3113  $gr[] = ilObjRole::_lookupTitle($role);
3114  }
3115  }
3116  if (count($gr)) {
3117  $body .= ($language->txt('reg_role_info') . ': ' . implode(',', $gr) . "\n");
3118  }
3119 
3120  // Time limit
3121  if ($this->getTimeLimitUnlimited()) {
3122  $body .= ($language->txt('time_limit') . ": " . $language->txt('crs_unlimited') . "\n");
3123  } else {
3127  new ilDateTime($this->getTimeLimitFrom(), IL_CAL_UNIX),
3129  );
3131 
3132  $start = new ilDateTime($this->getTimeLimitFrom(), IL_CAL_UNIX);
3133  $end = new ilDateTime($this->getTimeLimitUntil(), IL_CAL_UNIX);
3134 
3135  $body .= $language->txt('time_limit') . ': ' .
3136  $language->txt('from') . " " .
3137  $start->get(IL_CAL_DATETIME) . " ";
3138  $body .= $language->txt('to') . ' ' . $end->get(IL_CAL_DATETIME) . "\n";
3139  }
3140 
3144  $user_defined_fields = ilUserDefinedFields::_getInstance();
3145  $user_defined_data = $this->getUserDefinedData();
3146 
3147  foreach ($user_defined_fields->getDefinitions() as $field_id => $definition) {
3148  $data = $user_defined_data["f_" . $field_id] ?? '';
3149  if ($data !== '') {
3150  if ($definition['field_type'] == UDF_TYPE_WYSIWYG) {
3151  $data = strip_tags(
3152  preg_replace('/<br(\s*)?\/?>/i', "\n", $data)
3153  );
3154  }
3155 
3156  $body .= $definition['field_name'] . ': ' . $data . "\n";
3157  }
3158  }
3159 
3160  return $body;
3161  }
3162 
3166  public static function _lookupFeedHash(int $a_user_id, bool $a_create = false): ?string
3167  {
3168  global $DIC;
3169  $ilDB = $DIC['ilDB'];
3170 
3171  if ($a_user_id > 0) {
3172  $set = $ilDB->queryF(
3173  'SELECT feed_hash from usr_data WHERE usr_id = %s',
3175  [$a_user_id]
3176  );
3177  if ($rec = $ilDB->fetchAssoc($set)) {
3178  $feed_hash = $rec['feed_hash'];
3179  if (is_string($feed_hash) && strlen($feed_hash) === 32) {
3180  return $feed_hash;
3181  }
3182 
3183  if ($a_create) {
3184  $hash = md5(random_int(1, 9999999) + str_replace(' ', '', microtime()));
3185  $ilDB->manipulateF(
3186  'UPDATE usr_data SET feed_hash = %s' .
3187  ' WHERE usr_id = %s',
3189  [$hash, $a_user_id]
3190  );
3191  return $hash;
3192  }
3193  }
3194  }
3195  return null;
3196  }
3197 
3203  public static function _getFeedPass(
3204  int $a_user_id
3205  ): ?string {
3206  if ($a_user_id > 0) {
3207  return self::_lookupPref($a_user_id, "priv_feed_pass");
3208  }
3209  return null;
3210  }
3211 
3216  public static function _setFeedPass(
3217  int $a_user_id,
3218  string $a_password
3219  ): void {
3220  self::_writePref(
3221  $a_user_id,
3222  "priv_feed_pass",
3223  ($a_password == "") ? "" : md5($a_password)
3224  );
3225  }
3226 
3231  public static function _loginExists(
3232  string $a_login,
3233  int $a_user_id = 0
3234  ): ?int {
3235  global $DIC;
3236 
3237  $ilDB = $DIC['ilDB'];
3238 
3239  $q = "SELECT DISTINCT login, usr_id FROM usr_data " .
3240  "WHERE login = %s";
3241  $types[] = "text";
3242  $values[] = $a_login;
3243 
3244  if ($a_user_id != 0) {
3245  $q .= " AND usr_id != %s ";
3246  $types[] = "integer";
3247  $values[] = $a_user_id;
3248  }
3249 
3250  $r = $ilDB->queryF($q, $types, $values);
3251 
3252  if ($row = $ilDB->fetchAssoc($r)) {
3253  return (int) $row['usr_id'];
3254  }
3255  return null;
3256  }
3257 
3261  public static function _externalAccountExists(
3262  string $a_external_account,
3263  string $a_auth_mode
3264  ): bool {
3265  global $DIC;
3266 
3267  $ilDB = $DIC['ilDB'];
3268 
3269  $res = $ilDB->queryF(
3270  "SELECT * FROM usr_data " .
3271  "WHERE ext_account = %s AND auth_mode = %s",
3272  ["text", "text"],
3273  [$a_external_account, $a_auth_mode]
3274  );
3275  return (bool) $ilDB->fetchAssoc($res);
3276  }
3277 
3282  public static function _getUsersForRole(
3283  int $role_id,
3284  int $active = -1
3285  ): array {
3286  global $DIC;
3287 
3288  $ilDB = $DIC['ilDB'];
3289  $rbacreview = $DIC['rbacreview'];
3290  $ids = $rbacreview->assignedUsers($role_id);
3291 
3292  if (count($ids) == 0) {
3293  $ids = [-1];
3294  }
3295 
3296  $query = "SELECT usr_data.*, usr_pref.value AS language
3297  FROM usr_data
3298  LEFT JOIN usr_pref ON usr_pref.usr_id = usr_data.usr_id AND usr_pref.keyword = %s
3299  WHERE " . $ilDB->in("usr_data.usr_id", $ids, false, "integer");
3300  $values[] = "language";
3301  $types[] = "text";
3302 
3303 
3304  if (is_numeric($active) && $active > -1) {
3305  $query .= " AND usr_data.active = %s";
3306  $values[] = $active;
3307  $types[] = "integer";
3308  }
3309 
3310  $query .= " ORDER BY usr_data.lastname, usr_data.firstname ";
3311 
3312  $r = $ilDB->queryF($query, $types, $values);
3313  $data = [];
3314  while ($row = $ilDB->fetchAssoc($r)) {
3315  $data[] = $row;
3316  }
3317  return $data;
3318  }
3319 
3320 
3325  public static function _getUsersForFolder(
3326  int $ref_id,
3327  int $active
3328  ): array {
3329  global $DIC;
3330 
3331  $ilDB = $DIC['ilDB'];
3332  $query = "SELECT usr_data.*, usr_pref.value AS language FROM usr_data LEFT JOIN usr_pref ON usr_pref.usr_id = usr_data.usr_id and usr_pref.keyword = %s WHERE 1=1";
3333  $types[] = "text";
3334  $values[] = "language";
3335 
3336  if (is_numeric($active) && $active > -1) {
3337  $query .= " AND usr_data.active = %s";
3338  $values[] = $active;
3339  $types[] = "integer";
3340  }
3341 
3342  if ($ref_id != USER_FOLDER_ID) {
3343  $query .= " AND usr_data.time_limit_owner = %s";
3344  $values[] = $ref_id;
3345  $types[] = "integer";
3346  }
3347 
3348  $query .= " AND usr_data.usr_id != %s ";
3349  $values[] = ANONYMOUS_USER_ID;
3350  $types[] = "integer";
3351 
3352  $query .= " ORDER BY usr_data.lastname, usr_data.firstname ";
3353 
3354  $result = $ilDB->queryF($query, $types, $values);
3355  $data = [];
3356  while ($row = $ilDB->fetchAssoc($result)) {
3357  $data[] = $row;
3358  }
3359 
3360  return $data;
3361  }
3362 
3363 
3369  public static function _getUsersForGroup(
3370  array $a_mem_ids,
3371  int $active = -1
3372  ): array {
3373  return self::_getUsersForIds($a_mem_ids, $active);
3374  }
3375 
3376 
3382  public static function _getUsersForIds(
3383  array $a_mem_ids,
3384  int $active = -1,
3385  int $timelimitowner = -1
3386  ): array {
3387  global $DIC;
3388 
3389  $ilDB = $DIC['ilDB'];
3390 
3391  $query = "SELECT usr_data.*, usr_pref.value AS language
3392  FROM usr_data
3393  LEFT JOIN usr_pref ON usr_pref.usr_id = usr_data.usr_id AND usr_pref.keyword = %s
3394  WHERE " . $ilDB->in("usr_data.usr_id", $a_mem_ids, false, "integer") . "
3395  AND usr_data.usr_id != %s";
3396  $values[] = "language";
3397  $types[] = "text";
3398  $values[] = ANONYMOUS_USER_ID;
3399  $types[] = "integer";
3400 
3401  if (is_numeric($active) && $active > -1) {
3402  $query .= " AND active = %s";
3403  $values[] = $active;
3404  $types[] = "integer";
3405  }
3406 
3407  if ($timelimitowner != USER_FOLDER_ID && $timelimitowner != -1) {
3408  $query .= " AND usr_data.time_limit_owner = %s";
3409  $values[] = $timelimitowner;
3410  $types[] = "integer";
3411  }
3412 
3413  $query .= " ORDER BY usr_data.lastname, usr_data.firstname ";
3414 
3415  $result = $ilDB->queryF($query, $types, $values);
3416  $mem_arr = [];
3417  while ($row = $ilDB->fetchAssoc($result)) {
3418  $mem_arr[] = $row;
3419  }
3420 
3421  return $mem_arr;
3422  }
3423 
3424 
3425 
3430  public static function _getUserData(array $a_internalids): array
3431  {
3432  global $DIC;
3433 
3434  $ilDB = $DIC['ilDB'];
3435 
3436  $ids = [];
3437  if (is_array($a_internalids)) {
3438  foreach ($a_internalids as $internalid) {
3439  if (is_numeric($internalid)) {
3440  $ids[] = $internalid;
3441  } else {
3442  $parsedid = ilUtil::__extractId($internalid, IL_INST_ID);
3443  if (is_numeric($parsedid) && $parsedid > 0) {
3444  $ids[] = $parsedid;
3445  }
3446  }
3447  }
3448  }
3449  if (count($ids) == 0) {
3450  $ids [] = -1;
3451  }
3452 
3453  $query = "SELECT usr_data.*, usr_pref.value AS language
3454  FROM usr_data
3455  LEFT JOIN usr_pref
3456  ON usr_pref.usr_id = usr_data.usr_id AND usr_pref.keyword = %s
3457  WHERE " . $ilDB->in("usr_data.usr_id", $ids, false, "integer");
3458  $values[] = "language";
3459  $types[] = "text";
3460 
3461  $query .= " ORDER BY usr_data.lastname, usr_data.firstname ";
3462 
3463  $data = [];
3464  $result = $ilDB->queryF($query, $types, $values);
3465  while ($row = $ilDB->fetchAssoc($result)) {
3466  $data[] = $row;
3467  }
3468  return $data;
3469  }
3470 
3477  public static function _getPreferences(int $user_id): array
3478  {
3479  global $DIC;
3480 
3481  $ilDB = $DIC['ilDB'];
3482 
3483  $prefs = [];
3484 
3485  $r = $ilDB->queryF(
3486  "SELECT * FROM usr_pref WHERE usr_id = %s",
3487  ["integer"],
3488  [$user_id]
3489  );
3490 
3491  while ($row = $ilDB->fetchAssoc($r)) {
3492  $prefs[$row["keyword"]] = $row["value"];
3493  }
3494 
3495  return $prefs;
3496  }
3497 
3502  public static function getUserSubsetByPreferenceValue(
3503  array $a_user_ids,
3504  string $a_keyword,
3505  string $a_val
3506  ): array {
3507  global $DIC;
3508 
3509  $ilDB = $DIC['ilDB'];
3510 
3511  $users = [];
3512  $set = $ilDB->query(
3513  "SELECT usr_id FROM usr_pref " .
3514  " WHERE keyword = " . $ilDB->quote($a_keyword, "text") .
3515  " AND " . $ilDB->in("usr_id", $a_user_ids, false, "integer") .
3516  " AND value = " . $ilDB->quote($a_val, "text")
3517  );
3518  while ($rec = $ilDB->fetchAssoc($set)) {
3519  $users[] = $rec["usr_id"];
3520  }
3521  return $users;
3522  }
3523 
3524  public static function _getLoginAttempts(
3525  int $a_usr_id
3526  ): int {
3527  global $DIC;
3528 
3529  $ilDB = $DIC['ilDB'];
3530 
3531  $query = "SELECT login_attempts FROM usr_data WHERE usr_id = %s";
3532  $result = $ilDB->queryF($query, ['integer'], [$a_usr_id]);
3533  $record = $ilDB->fetchAssoc($result);
3534  return (int) ($record['login_attempts'] ?? 0);
3535  }
3536 
3537  public static function _incrementLoginAttempts(
3538  int $a_usr_id
3539  ): bool {
3540  global $DIC;
3541 
3542  $ilDB = $DIC['ilDB'];
3543 
3544  $query = "UPDATE usr_data SET login_attempts = (login_attempts + 1) WHERE usr_id = %s";
3545  $affected = $ilDB->manipulateF($query, ['integer'], [$a_usr_id]);
3546 
3547  if ($affected) {
3548  return true;
3549  } else {
3550  return false;
3551  }
3552  }
3553 
3554  public static function _setUserInactive(
3555  int $a_usr_id
3556  ): bool {
3557  global $DIC;
3558 
3559  $ilDB = $DIC['ilDB'];
3560 
3561  $query = "UPDATE usr_data SET active = 0, inactivation_date = %s WHERE usr_id = %s";
3562  $affected = $ilDB->manipulateF($query, ['timestamp', 'integer'], [ilUtil::now(), $a_usr_id]);
3563 
3564  if ($affected) {
3565  return true;
3566  } else {
3567  return false;
3568  }
3569  }
3570 
3574  public function hasPublicProfile(): bool
3575  {
3576  return in_array($this->getPref("public_profile"), ["y", "g"]);
3577  }
3578 
3582  public function getPublicName(): string
3583  {
3584  if ($this->hasPublicProfile()) {
3585  return $this->getFirstname() . " " . $this->getLastname() . " (" . $this->getLogin() . ")";
3586  } else {
3587  return $this->getLogin();
3588  }
3589  }
3590 
3591  public static function _writeHistory(
3592  int $a_usr_id,
3593  string $a_login
3594  ): void {
3595  global $DIC;
3596 
3597  $ilDB = $DIC['ilDB'];
3598 
3599  $timestamp = time();
3600 
3601  $res = $ilDB->queryF(
3602  'SELECT * FROM loginname_history WHERE usr_id = %s AND login = %s AND history_date = %s',
3603  ['integer', 'text', 'integer'],
3604  [$a_usr_id, $a_login, $timestamp]
3605  );
3606 
3607  if ($ilDB->numRows($res) == 0) {
3608  $ilDB->manipulateF(
3609  '
3610  INSERT INTO loginname_history
3611  (usr_id, login, history_date)
3612  VALUES (%s, %s, %s)',
3613  ['integer', 'text', 'integer'],
3614  [$a_usr_id, $a_login, $timestamp]
3615  );
3616  }
3617  }
3618 
3623  public static function _getUsersOnline(
3624  int $a_user_id = 0,
3625  bool $a_no_anonymous = false
3626  ): array {
3627  global $DIC;
3628 
3629  $ilDB = $DIC->database();
3630 
3631  $log = ilLoggerFactory::getLogger("user");
3632 
3633  $pd_set = new ilSetting('pd');
3634  $atime = $pd_set->get('user_activity_time') * 60;
3635  $ctime = time();
3636 
3637  $where = [];
3638 
3639  if ($a_user_id === 0) {
3640  $where[] = 'user_id > 0';
3641  } else {
3642  $where[] = 'user_id = ' . $ilDB->quote($a_user_id, 'integer');
3643  }
3644 
3645  if ($a_no_anonymous) {
3646  $where[] = 'user_id != ' . $ilDB->quote(ANONYMOUS_USER_ID, 'integer');
3647  }
3648 
3649  if (ilUserAccountSettings::getInstance()->isUserAccessRestricted()) {
3650  $where[] = $ilDB->in('time_limit_owner', ilUserFilter::getInstance()->getFolderIds(), false, 'integer');
3651  }
3652 
3653  $where[] = 'expires > ' . $ilDB->quote($ctime, 'integer');
3654  $where[] = '(p.value IS NULL OR NOT p.value = ' . $ilDB->quote('y', 'text') . ')';
3655 
3656  $where = 'WHERE ' . implode(' AND ', $where);
3657 
3658  $r = $ilDB->queryF(
3659  $q = "
3660  SELECT COUNT(user_id) num, user_id, firstname, lastname, title, login, last_login, MAX(ctime) ctime, context, agree_date
3661  FROM usr_session
3662  LEFT JOIN usr_data u
3663  ON user_id = u.usr_id
3664  LEFT JOIN usr_pref p
3665  ON (p.usr_id = u.usr_id AND p.keyword = %s)
3666  $where
3667  GROUP BY user_id, firstname, lastname, title, login, last_login, context, agree_date
3668  ORDER BY lastname, firstname
3669  ",
3670  ['text'],
3671  ['hide_own_online_status']
3672  );
3673 
3674  $log->debug("Query: " . $q);
3675 
3676  $users = [];
3677  while ($user = $ilDB->fetchAssoc($r)) {
3678  if ($atime <= 0 || $user['ctime'] + $atime > $ctime) {
3679  $users[$user['user_id']] = $user;
3680  }
3681  }
3682 
3683  $log->debug("Found users: " . count($users));
3684 
3685  $hide_users = $DIC['legalDocuments']->usersWithHiddenOnlineStatus(array_map(intval(...), array_column($users, 'user_id')));
3686  $users = array_filter(
3687  $users,
3688  fn($user) => !in_array((int) $user['user_id'], $hide_users, true)
3689  );
3690 
3691  return $users;
3692  }
3693 
3698  public static function _generateRegistrationHash(int $a_usr_id): string
3699  {
3700  global $DIC;
3701 
3702  $ilDB = $DIC['ilDB'];
3703 
3704  do {
3705  $continue = false;
3706 
3707  $hashcode = substr(md5(uniqid(mt_rand(), true)), 0, 16);
3708 
3709  $res = $ilDB->queryf(
3710  '
3711  SELECT COUNT(usr_id) cnt FROM usr_data
3712  WHERE reg_hash = %s',
3713  ['text'],
3714  [$hashcode]
3715  );
3716  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
3717  if ($row->cnt > 0) {
3718  $continue = true;
3719  }
3720  break;
3721  }
3722 
3723  if ($continue) {
3724  continue;
3725  }
3726 
3727  $ilDB->manipulateF(
3728  '
3729  UPDATE usr_data
3730  SET reg_hash = %s
3731  WHERE usr_id = %s',
3732  ['text', 'integer'],
3733  [$hashcode, $a_usr_id]
3734  );
3735 
3736  break;
3737  } while (true);
3738 
3739  return $hashcode;
3740  }
3741 
3747  public static function _verifyRegistrationHash(
3748  string $a_hash
3749  ): int {
3750  global $DIC;
3751 
3752  $ilDB = $DIC['ilDB'];
3753 
3754  $res = $ilDB->queryf(
3755  '
3756  SELECT usr_id, create_date FROM usr_data
3757  WHERE reg_hash = %s',
3758  ['text'],
3759  [$a_hash]
3760  );
3761  while ($row = $ilDB->fetchAssoc($res)) {
3762  $oRegSettigs = new ilRegistrationSettings();
3763 
3764  if ($oRegSettigs->getRegistrationHashLifetime() != 0 &&
3765  time() - $oRegSettigs->getRegistrationHashLifetime() > strtotime($row['create_date'])) {
3767  'reg_confirmation_hash_life_time_expired',
3768  (int) $row['usr_id']
3769  );
3770  }
3771 
3772  $ilDB->manipulateF(
3773  '
3774  UPDATE usr_data
3775  SET reg_hash = %s
3776  WHERE usr_id = %s',
3777  ['text', 'integer'],
3778  ['', (int) $row['usr_id']]
3779  );
3780 
3781  return (int) $row['usr_id'];
3782  }
3783 
3784  throw new ilRegistrationHashNotFoundException('reg_confirmation_hash_not_found');
3785  }
3786 
3787  public function setBirthday(?string $a_birthday): void
3788  {
3789  if ($a_birthday && strlen($a_birthday)) {
3790  $date = new ilDate($a_birthday, IL_CAL_DATE);
3791  $this->birthday = $date->get(IL_CAL_DATE);
3792  } else {
3793  $this->birthday = null;
3794  }
3795  }
3796 
3797  public function getBirthday(): ?string
3798  {
3799  return $this->birthday;
3800  }
3801 
3808  public static function getUserIdsByInactivityPeriod(
3809  int $periodInDays
3810  ): array {
3811  global $DIC;
3812 
3813  if ($periodInDays < 1) {
3814  throw new ilException('Invalid period given');
3815  }
3816 
3817  $date = date('Y-m-d H:i:s', (time() - ($periodInDays * 24 * 60 * 60)));
3818 
3819  $query = "SELECT usr_id FROM usr_data WHERE last_login IS NOT NULL AND last_login < %s";
3820 
3821  $ids = [];
3822 
3823  $types = ['timestamp'];
3824  $values = [$date];
3825 
3826  $res = $DIC->database()->queryF($query, $types, $values);
3827  while ($row = $DIC->database()->fetchAssoc($res)) {
3828  $ids[] = (int) $row['usr_id'];
3829  }
3830 
3831  return $ids;
3832  }
3833 
3839  public static function getUserIdsNeverLoggedIn(
3840  int $thresholdInDays
3841  ): array {
3842  global $DIC;
3843 
3844  $date = date('Y-m-d H:i:s', (time() - ($thresholdInDays * 24 * 60 * 60)));
3845 
3846  $query = "SELECT usr_id FROM usr_data WHERE last_login IS NULL AND create_date < %s";
3847 
3848  $ids = [];
3849 
3850  $types = ['timestamp'];
3851  $values = [$date];
3852 
3853  $res = $DIC->database()->queryF($query, $types, $values);
3854  while ($row = $DIC->database()->fetchAssoc($res)) {
3855  $ids[] = (int) $row['usr_id'];
3856  }
3857 
3858  return $ids;
3859  }
3860 
3867  public static function _getUserIdsByInactivationPeriod(
3868  int $period
3869  ): array {
3871  $field = 'inactivation_date';
3873 
3874  if (!$period) {
3875  throw new ilException('no valid period given');
3876  }
3877 
3878  global $DIC;
3879 
3880  $ilDB = $DIC['ilDB'];
3881 
3882  $date = date('Y-m-d H:i:s', (time() - ($period * 24 * 60 * 60)));
3883 
3884  $query = "SELECT usr_id FROM usr_data WHERE $field < %s AND active = %s";
3885 
3886  $res = $ilDB->queryF($query, ['timestamp', 'integer'], [$date, 0]);
3887 
3888  $ids = [];
3889  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
3890  $ids[] = (int) $row->usr_id;
3891  }
3892 
3893  return $ids;
3894  }
3895 
3896  public function resetOwner(): void
3897  {
3898  $ilDB = $this->db;
3899 
3900  $query = "UPDATE object_data SET owner = 0 " .
3901  "WHERE owner = " . $ilDB->quote($this->getId(), 'integer');
3902  $ilDB->query($query);
3903  }
3904 
3909  public static function getFirstLettersOfLastnames(
3910  ?array $user_ids = null
3911  ): array {
3912  global $DIC;
3913 
3914  $ilDB = $DIC->database();
3915 
3916  $q = "SELECT DISTINCT " . $ilDB->upper($ilDB->substr("lastname", 1, 1)) . " let" .
3917  " FROM usr_data" .
3918  " WHERE usr_id <> " . $ilDB->quote(ANONYMOUS_USER_ID, "integer") .
3919  ($user_ids !== null ? " AND " . $ilDB->in('usr_id', $user_ids, false, "integer") : "") .
3920  " ORDER BY let";
3921  $let_set = $ilDB->query($q);
3922 
3923  $let = [];
3924  while ($let_rec = $ilDB->fetchAssoc($let_set)) {
3925  $let[$let_rec["let"]] = $let_rec["let"];
3926  }
3927  return $let;
3928  }
3929 
3930  public static function userExists(
3931  array $a_usr_ids = []
3932  ): bool {
3933  global $DIC;
3934 
3935  $ilDB = $DIC['ilDB'];
3936 
3937  $query = 'SELECT count(*) num FROM object_data od ' .
3938  'JOIN usr_data ud ON obj_id = usr_id ' .
3939  'WHERE ' . $ilDB->in('obj_id', $a_usr_ids, false, 'integer') . ' ';
3940  $res = $ilDB->query($query);
3941  $num_rows = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)->num;
3942  return $num_rows == count($a_usr_ids);
3943  }
3944 
3945  public function exportPersonalData(): void
3946  {
3947  $exp = new ilExport();
3948  $dir = ilExport::_getExportDirectory($this->getId(), "xml", "usr", "personal_data");
3949  ilFileUtils::delDir($dir, true);
3950  $title = $this->getLastname() . ", " . $this->getLastname() . " [" . $this->getLogin() . "]";
3951  $exp->exportEntity(
3952  "personal_data",
3953  $this->getId(),
3954  "",
3955  "Services/User",
3956  $title,
3957  $dir
3958  );
3959  }
3960 
3961  public function getPersonalDataExportFile(): string
3962  {
3963  $dir = ilExport::_getExportDirectory($this->getId(), "xml", "usr", "personal_data");
3964  if (!is_dir($dir)) {
3965  return "";
3966  }
3967  foreach (ilFileUtils::getDir($dir) as $entry) {
3968  if (is_int(strpos($entry["entry"], ".zip"))) {
3969  return $entry["entry"];
3970  }
3971  }
3972 
3973  return "";
3974  }
3975 
3976  public function sendPersonalDataFile(): void
3977  {
3978  $file = ilExport::_getExportDirectory($this->getId(), "xml", "usr", "personal_data") .
3979  "/" . $this->getPersonalDataExportFile();
3980  if (is_file($file)) {
3982  }
3983  }
3984 
3985  public function importPersonalData(
3986  array $a_file,
3987  bool $a_profile_data,
3988  bool $a_settings,
3989  bool $a_notes,
3990  bool $a_calendar
3991  ): void {
3992  $imp = new ilImport();
3993  // bookmarks need to be skipped, importer does not exist anymore
3994  $imp->addSkipImporter("Services/Bookmarks");
3995  if (!$a_profile_data) {
3996  $imp->addSkipEntity("Services/User", "usr_profile");
3997  }
3998  if (!$a_settings) {
3999  $imp->addSkipEntity("Services/User", "usr_setting");
4000  }
4001  if (!$a_notes) {
4002  $imp->addSkipEntity("Services/Notes", "user_notes");
4003  }
4004  if (!$a_calendar) {
4005  $imp->addSkipEntity("Services/Calendar", "calendar");
4006  }
4007  $imp->importEntity(
4008  $a_file["tmp_name"],
4009  $a_file["name"],
4010  "personal_data",
4011  "Services/User"
4012  );
4013  }
4014 
4015  public function setInactivationDate(?string $inactivation_date): void
4016  {
4017  $this->inactivation_date = $inactivation_date;
4018  }
4019 
4020  public function getInactivationDate(): ?string
4021  {
4022  return $this->inactivation_date;
4023  }
4024 
4025  public function isAnonymous(): bool
4026  {
4027  return self::_isAnonymous($this->getId());
4028  }
4029 
4030  public static function _isAnonymous(int $usr_id): bool
4031  {
4032  return $usr_id == ANONYMOUS_USER_ID;
4033  }
4034 
4035  public function activateDeletionFlag(): void
4036  {
4037  $this->writePref("delete_flag", true);
4038  }
4039 
4040  public function removeDeletionFlag(): void
4041  {
4042  $this->writePref("delete_flag", false);
4043  }
4044 
4045  public function hasDeletionFlag(): bool
4046  {
4047  return (bool) $this->getPref("delete_flag");
4048  }
4049 
4050  public function setIsSelfRegistered(bool $status): void
4051  {
4052  $this->is_self_registered = $status;
4053  }
4054 
4055  public function isSelfRegistered(): bool
4056  {
4058  }
4059 
4060 
4061  //
4062  // MULTI-TEXT / INTERESTS
4063  //
4064 
4068  public function setGeneralInterests(?array $value = null): void
4069  {
4070  $this->interests_general = $value ?? [];
4071  }
4072 
4076  public function getGeneralInterests(): array
4077  {
4078  return $this->interests_general;
4079  }
4080 
4084  public function getGeneralInterestsAsText(): string
4085  {
4086  return $this->buildTextFromArray($this->interests_general);
4087  }
4088 
4092  public function setOfferingHelp(?array $value = null): void
4093  {
4094  $this->interests_help_offered = $value ?? [];
4095  }
4096 
4100  public function getOfferingHelp(): array
4101  {
4103  }
4104 
4108  public function getOfferingHelpAsText(): string
4109  {
4110  return $this->buildTextFromArray($this->interests_help_offered);
4111  }
4112 
4116  public function setLookingForHelp(?array $value = null): void
4117  {
4118  $this->interests_help_looking = $value ?? [];
4119  }
4120 
4124  public function getLookingForHelp(): array
4125  {
4127  }
4128 
4132  public function getLookingForHelpAsText(): string
4133  {
4134  return $this->buildTextFromArray($this->interests_help_looking);
4135  }
4136 
4142  protected function buildTextFromArray(array $a_attr): string
4143  {
4144  if (count($a_attr) > 0) {
4145  return implode(", ", $a_attr);
4146  }
4147  return "";
4148  }
4149 
4150  protected function readMultiTextFields(): void
4151  {
4152  global $DIC;
4153 
4154  $ilDB = $DIC['ilDB'];
4155 
4156  if (!$this->getId()) {
4157  return;
4158  }
4159 
4160  $set = $ilDB->query("SELECT field_id,value" .
4161  " FROM usr_data_multi" .
4162  " WHERE usr_id = " . $ilDB->quote($this->getId(), "integer") .
4163  " ORDER BY value");
4164  while ($row = $ilDB->fetchAssoc($set)) {
4165  $values[$row["field_id"]][] = $row["value"];
4166  }
4167 
4168  if (isset($values["interests_general"])) {
4169  $this->setGeneralInterests($values["interests_general"]);
4170  } else {
4171  $this->setGeneralInterests();
4172  }
4173  if (isset($values["interests_help_offered"])) {
4174  $this->setOfferingHelp($values["interests_help_offered"]);
4175  } else {
4176  $this->setOfferingHelp();
4177  }
4178  if (isset($values["interests_help_looking"])) {
4179  $this->setLookingForHelp($values["interests_help_looking"]);
4180  } else {
4181  $this->setLookingForHelp();
4182  }
4183  }
4184 
4185  public function updateMultiTextFields(bool $a_create = false): void
4186  {
4187  global $DIC;
4188 
4189  $ilDB = $DIC['ilDB'];
4190 
4191  if (!$this->getId()) {
4192  return;
4193  }
4194 
4195  if (!$a_create) {
4196  $this->deleteMultiTextFields();
4197  }
4198 
4199  $map = [
4200  "interests_general" => $this->getGeneralInterests(),
4201  "interests_help_offered" => $this->getOfferingHelp(),
4202  "interests_help_looking" => $this->getLookingForHelp()
4203  ];
4204 
4205  foreach ($map as $id => $values) {
4206  if (is_array($values) && count($values)) {
4207  foreach ($values as $value) {
4208  $value = trim($value);
4209  if ($value) {
4210  $uniq_id = $ilDB->nextId('usr_data_multi');
4211 
4212  $ilDB->manipulate("INSERT usr_data_multi" .
4213  " (id,usr_id,field_id,value) VALUES" .
4214  " (" . $ilDB->quote($uniq_id, "integer") .
4215  "," . $ilDB->quote($this->getId(), "integer") .
4216  "," . $ilDB->quote($id, "text") .
4217  "," . $ilDB->quote($value, "text") .
4218  ")");
4219  }
4220  }
4221  }
4222  }
4223  }
4224 
4225  protected function deleteMultiTextFields(): void
4226  {
4227  global $DIC;
4228 
4229  $ilDB = $DIC['ilDB'];
4230 
4231  if (!$this->getId()) {
4232  return;
4233  }
4234 
4235  $ilDB->manipulate("DELETE FROM usr_data_multi" .
4236  " WHERE usr_id = " . $ilDB->quote($this->getId(), "integer"));
4237  }
4238 
4239  public static function findInterests(
4240  string $a_term,
4241  ?int $a_user_id = null,
4242  string $a_field_id = null
4243  ): array {
4244  global $DIC;
4245 
4246  $ilDB = $DIC['ilDB'];
4247 
4248  $res = [];
4249 
4250  $sql = "SELECT DISTINCT(value)" .
4251  " FROM usr_data_multi" .
4252  " WHERE " . $ilDB->like("value", "text", "%" . $a_term . "%");
4253  if ($a_field_id) {
4254  $sql .= " AND field_id = " . $ilDB->quote($a_field_id, "text");
4255  }
4256  if ($a_user_id) {
4257  $sql .= " AND usr_id <> " . $ilDB->quote($a_user_id, "integer");
4258  }
4259  $sql .= " ORDER BY value";
4260  $set = $ilDB->query($sql);
4261  while ($row = $ilDB->fetchAssoc($set)) {
4262  $res[] = $row["value"];
4263  }
4264 
4265  return $res;
4266  }
4267 
4276  public static function getProfileStatusOfUsers(
4277  array $a_user_ids
4278  ): array {
4279  global $DIC;
4280 
4281  $ilDB = $DIC->database();
4282 
4283  $set = $ilDB->query(
4284  "SELECT * FROM usr_pref " .
4285  " WHERE keyword = " . $ilDB->quote("public_profile", "text") .
4286  " AND " . $ilDB->in("usr_id", $a_user_ids, false, "integer")
4287  );
4288  $r = [
4289  "global" => [],
4290  "local" => [],
4291  "public" => [],
4292  "not_public" => []
4293  ];
4294  while ($rec = $ilDB->fetchAssoc($set)) {
4295  if ($rec["value"] == "g") {
4296  $r["global"][] = $rec["usr_id"];
4297  $r["public"][] = $rec["usr_id"];
4298  }
4299  if ($rec["value"] == "y") {
4300  $r["local"][] = $rec["usr_id"];
4301  $r["public"][] = $rec["usr_id"];
4302  }
4303  }
4304  foreach ($a_user_ids as $id) {
4305  if (!in_array($id, $r["public"])) {
4306  $r["not_public"][] = $id;
4307  }
4308  }
4309 
4310  return $r;
4311  }
4312 }
getCurrentLanguage()
returns the current language (may differ from user&#39;s pref setting!)
static getWebspaceDir(string $mode="filesystem")
get webspace directory
static hasActiveSession(int $a_user_id, string $a_session_id)
setUTitle(string $a_str)
set user title (note: don&#39;t mix up this method with setTitle() that is derived from ilObject and sets...
string $title
setProfileIncomplete(bool $a_prof_inc)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
string $passwd
string $loc_zoom
static get(string $a_var)
setTimeLimitUnlimited(bool $a_unlimited)
static _setFeedPass(int $a_user_id, string $a_password)
Set news feed password for user.
setClientIP(string $a_str)
setAvatarRid(?string $avatar_rid)
string $avatar_rid
$res
Definition: ltiservices.php:69
array $settings
Setting values (LTI parameters, custom parameters and local parameters).
Definition: System.php:200
getStoredActive(int $a_id)
get user active state
setLastLogin(string $a_str)
static _getUsersForRole(int $role_id, int $active=-1)
return array of complete users which belong to a specific role
resetPassword(string $raw, string $raw_retype)
Resets the user password.
refreshLogin()
updates the login data of a "user"
static _getLoginAttempts(int $a_usr_id)
static _destroyByUserId(int $a_user_id)
Destroy session.
static copyProfilePicturesToDirectory(int $a_user_id, string $a_dir)
static _deleteUser(int $a_usr_id)
static _lookupLanguage(int $a_usr_id)
buildTextFromArray(array $a_attr)
Convert multi-text values to plain text.
string $utitle
const IL_INST_ID
Definition: constants.php:40
const IL_CAL_DATETIME
const ANONYMOUS_USER_ID
Definition: constants.php:27
static getLogger(string $a_component_id)
Get component logger.
static _getAllUserData(?array $a_fields=null, int $active=-1)
const USER_FOLDER_ID
Definition: constants.php:33
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _getAuthMode(?string $a_auth_mode)
writePref(string $a_keyword, string $a_value)
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
setAgreeDate(?string $a_str)
array $interests_help_looking
static styleExists(string $style_id)
static getUserIdsByInactivityPeriod(int $periodInDays)
Get ids of all users that have been inactive for at least the given period.
string $street
static lookupMatriculation(int $a_usr_id)
static getFirstLettersOfLastnames(?array $user_ids=null)
Get first letters of all lastnames.
string $fullname
__construct(int $a_user_id=0, bool $a_call_by_reference=false)
static getProfileStatusOfUsers(array $a_user_ids)
Get profile status.
static _verifyRegistrationHash(string $a_hash)
Verifies a registration hash.
assignData(array $a_data)
loads a record "user" from array
fetchAssoc(ilDBStatement $statement)
static _externalAccountExists(string $a_external_account, string $a_auth_mode)
Check if an external account name already exists.
setMatriculation(string $a_str)
static _lookupFullname(int $a_user_id)
getGeneralInterestsAsText()
Get general interests as plain text.
getDefaultLanguage()
Return default language.
Class for user related exception handling in ILIAS.
setPhoneOffice(string $a_str)
addToPCClipboard(string $a_content, string $a_time, int $a_nr)
Add a page content item to PC clipboard (should go to another class)
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
static _moveUsersToStyle(string $a_from_skin, string $a_from_style, string $a_to_skin, string $a_to_style)
static _getPreferences(int $user_id)
get preferences for user
removeObjectFromClipboard(int $a_item_id, string $a_type)
getPasswordPolicyResetStatus()
static _removeTrackingDataForUser(int $user_id)
to be called from IlObjUser
const SYSTEM_USER_ID
This file contains constants for PHPStan analyis, see: https://phpstan.org/config-reference#constants...
Definition: constants.php:26
updateLogin(string $a_login)
update login name
setSelectedCountry(string $a_val)
Set selected country (selection drop down)
deletePref(string $a_keyword)
static _lookupLastLogin(int $a_user_id)
array $interests_help_offered
string $phone_mobile
int $time_limit_from
string $time_limit_message
static array $personal_image_cache
setFullname()
builds a string with title + firstname + lastname method is used to build fullname in member variable...
const PASSWD_PLAIN
ilTree $tree
string $matriculation
static formatDate(ilDateTime $date, bool $a_skip_day=false, bool $a_include_wd=false, bool $include_seconds=false)
static _writeAuthMode(int $a_usr_id, string $a_auth_mode)
static _lookupName(int $a_user_id)
lookup user name
static resetToDefaults()
reset to defaults
Import class.
static _lookupId($a_user_str)
static lookupTitle(int $a_page_id)
static _deleteSettingsOfUser(int $a_user)
getFullname(int $a_max_strlen=0)
string $passwd_type
removeUserPicture(bool $a_do_update=true)
static getUserIdsByEmail(string $a_email)
loadLanguageModule(string $a_module)
Load language module.
int $time_limit_until
static _lookupPref(int $a_usr_id, string $a_keyword)
static _checkExternalAuthAccount(string $a_auth, string $a_account, bool $tryFallback=true)
check whether external account and authentication method matches with a user
static getUserSubsetByPreferenceValue(array $a_user_ids, string $a_keyword, string $a_val)
For a given set of user IDs return a subset that has a given user preference set. ...
string $longitude
Export.
getCreateDate()
Get create date in YYYY-MM-DD HH-MM-SS format.
static _lookupExternalAccount(int $a_user_id)
static _getUsersForGroup(array $a_mem_ids, int $active=-1)
return user data for group members
static _deleteByUser(int $a_usr_id)
static _needsExternalAccountByAuthMode($a_auth_mode)
Check if chosen auth mode needs an external account entry.
string $institution
const IL_CAL_UNIX
static setLanguage(ilLanguage $a_lng)
static _lookupAuthMode(int $a_usr_id)
setPasswordSalt(?string $password_salt)
static lookupOrgUnitsRepresentation(int $a_usr_id)
lookup org unit representation
static _lookupGender(int $a_user_id)
setTimeLimitUntil(?int $a_until)
static _getAuthModeName($a_auth_key)
static _uploadPersonalPicture(string $tmp_file, int $obj_id)
Create a personal picture image file from a temporary image file.
setLoginAttempts(int $a_login_attempts)
static now()
Return current timestamp in Y-m-d H:i:s format.
static _deleteAllPref(int $a_user_id)
Deletes a userpref value of the user from the database.
static _getExportDirectory(int $a_obj_id, string $a_type="xml", string $a_obj_type="", string $a_entity="")
Get export directory for an repository object.
string $latitude
setInstitution(string $a_str)
setCity(string $a_str)
getPublicName()
returns firstname lastname and login if profile is public, login otherwise
deleteUserDefinedFieldEntries()
Services $irss
getAuthMode(bool $a_auth_key=false)
static _deleteUser(int $a_usr_id)
getOfferingHelpAsText()
Get help offering as plain text.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$ilErr
Definition: raiseError.php:17
setLatitude(?string $a_latitude)
setComment(string $a_str)
setPasswd(string $a_str, string $a_type=ilObjUser::PASSWD_PLAIN)
setGender(string $a_str)
addObjectToClipboard(int $a_item_id, string $a_type, string $a_title, int $a_parent=0, string $a_time="", int $a_order_nr=0)
add an item to user&#39;s personal clipboard
int $last_password_change_ts
setId(int $id)
static _getAvatar(int $a_usr_id)
Factory for Date Formats.
Definition: Factory.php:26
setExternalAccount(string $a_str)
static _getNumberOfUsersForStyle(string $a_skin, string $a_style)
static deliverFileLegacy(string $a_file, ?string $a_filename=null, ?string $a_mime=null, ?bool $isInline=false, ?bool $removeAfterDelivery=false, ?bool $a_exit_after=true)
string $agree_date
setPasswordPolicyResetStatus(bool $status)
static findInterests(string $a_term, ?int $a_user_id=null, string $a_field_id=null)
array $user_defined_data
global $DIC
Definition: feed.php:28
setBirthday(?string $a_birthday)
bool $profile_incomplete
string $department
setSkin(string $a_str)
static _writeExternalAccount(int $a_usr_id, string $a_ext_id)
string $password_salt
static _getInstance()
Get singleton instance of this class.
string $last_login
bool $time_limit_unlimited
static _getExternalAccountsByAuthMode(string $a_auth_mode, bool $a_read_auth_default=false)
Get list of external account by authentication method Note: If login == ext_account for two user with...
static getUserIdByLogin(string $a_login)
writeAccepted()
write accept date of user agreement
static _getLastHistoryDataByUserId(int $a_usr_id)
Returns the last used loginname and the changedate of the passed user_id.
ilAppEventHandler $app_event_handler
string $auth_mode
setLogin(string $a_str)
setActive(bool $a_active, int $a_owner=0)
set user active state and updates system fields appropriately
const NO_AVATAR_RID
__construct(VocabulariesInterface $vocabularies)
string $phone_home
static userExists(array $a_usr_ids=[])
static _lookupClientIP(int $a_user_id)
setDepartment(string $a_str)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _lookupTitle(int $obj_id)
static deleteEntriesOfUser(int $a_user_id)
$GLOBALS["DIC"]
Definition: wac.php:31
string $last_update
setOfferingHelp(?array $value=null)
static getLoginFromAuth()
Gets the username from $ilAuth, and converts it into an ILIAS login name.
clipboardDeleteObjectsOfType(string $a_type)
static getUserLoginsByEmail(string $a_email)
getLoginByUserId(int $a_userid)
This describes how a letter or a picture avatar could be modified during construction of UI...
Definition: Avatar.php:28
A Date Format provides a format definition akin to PHP&#39;s date formatting options, but stores the sing...
Definition: DateFormat.php:26
static _getFeedPass(int $a_user_id)
Lookup news feed password for user.
static _exists(string $a_parent_type, int $a_id, string $a_lang="", bool $a_no_cache=false)
Checks whether page exists.
static _generateRegistrationHash(int $a_usr_id)
Generates a unique hashcode for activating a user profile after registration.
static styleExistsForSkinId(string $skin_id, string $style_id)
setApproveDate(?string $a_str)
set date the user account was activated null indicates that the user has not yet been activated ...
Mail Box class Base class for creating and handling mail boxes.
static _setUserInactive(int $a_usr_id)
ilLanguage $lng
setPhoneHome(string $a_str)
static _getNumberOfUsersPerAuthMode()
get number of users per auth mode
static _toggleActiveStatusOfUsers(array $a_usr_ids, bool $a_status)
static _loginExists(string $a_login, int $a_user_id=0)
check if a login name already exists You may exclude a user from the check by giving his user id as 2...
static removeForUser(int $user_id)
Remove all notifications for given user.
getPref(string $a_keyword)
static delDir(string $a_dir, bool $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
ilDBInterface $db
setInactivationDate(?string $inactivation_date)
syncActive()
synchronizes current and stored user active values for the owner value to be set correctly, this function should only be called when an admin is approving a user account
static _getUsersOnline(int $a_user_id=0, bool $a_no_anonymous=false)
reads all active sessions from db and returns users that are online OR returns only one active user i...
string $second_email
string $birthday
updateOwner()
update owner of object in db
static _deletePref(int $a_user_id, string $a_keyword)
static _getUserData(array $a_internalids)
return user data for given user ids
checkUserId()
check user id with login name
header include for all ilias files.
string $country
static _writeHistory(int $a_usr_id, string $a_login)
getLookingForHelpAsText()
Get help looking for as plain text.
setHobby(string $a_str)
setIsSelfRegistered(bool $status)
static getDir(string $a_dir, bool $a_rec=false, ?string $a_sub_dir="")
get directory
string $phone_office
static _lookupFields(int $a_user_id)
lookup fields (deprecated; use more specific methods instead)
bool $passwd_policy_reset
setPref(string $a_keyword, ?string $a_value)
Class ilUserAvatarResolver.
const UDF_TYPE_WYSIWYG
static _getUserIdsByInactivationPeriod(int $period)
get ids of all users that have been inactivated since at least the given period
setFirstLogin(string $a_str)
string $gender
setCountry(string $a_str)
setEmail(string $a_str)
setFax(string $a_str)
queryF(string $query, array $types, array $values)
getPCClipboardContent()
Add a page content item to PC clipboard (should go to another class)
static _isAnonymous(int $usr_id)
existsPref(string $a_keyword)
static _getPersonalPicturePath(int $a_usr_id, string $a_size="small", bool $a_force_pic=false, bool $a_prevent_no_photo_image=false, bool $html_export=false)
importPersonalData(array $a_file, bool $a_profile_data, bool $a_settings, bool $a_notes, bool $a_calendar)
const PASSWD_CRYPTED
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:70
int $time_limit_owner
setPhoneMobile(string $a_str)
string $first_login
getSelectedCountry()
Get selected country (selection drop down)
static deleteByUserId(int $a_user_id)
setLastPasswordChangeTS(int $a_last_password_change_ts)
setLastname(string $a_str)
setPasswordEncodingType(?string $password_encryption_type)
setStreet(string $a_str)
string $lastname
getPersonalPicturePath(string $a_size="small", bool $a_force_pic=false)
static _doesLoginnameExistInHistory(string $a_login)
Checks whether the passed loginname already exists in history.
static _getUsersForClipboadObject(string $a_type, int $a_id)
get all users, that have a certain object within their clipboard
static deleteUserPortfolios(int $a_user_id)
Delete all portfolio data for user.
Class ilObjAuthSettingsGUI.
bool $is_self_registered
static skinExists(string $skin_id, ?ilSystemStyleConfig $system_style_config=null)
Check whether a skin exists.
const IL_CAL_DATE
string $ext_account
static _incrementLoginAttempts(int $a_usr_id)
string $last_profile_prompt
static _lookupFeedHash(int $a_user_id, bool $a_create=false)
Lookup news feed hash for user.
static formatPeriod(ilDateTime $start, ilDateTime $end, bool $a_skip_starting_day=false)
Format a period of two dates Shows: 14.
setLastProfilePrompt(string $a_str)
static _getImportedUserId(string $i2_id)
static _getUsersForFolder(int $ref_id, int $active)
get users for a category or from system folder
setLanguage(string $a_str)
static _readUsersProfileData(array $a_user_ids)
global $ilSetting
Definition: privfeed.php:18
static _lookup(int $a_user_id, string $a_field)
static __extractId(string $ilias_id, int $inst_id)
extract ref id from role title, e.g.
string $org_units
static toUsernameWithoutDomain(string $a_login)
Static function removes Microsoft domain name from username webdav related.
setTimeLimitOwner(int $a_owner)
updateMultiTextFields(bool $a_create=false)
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
$q
Definition: shib_logout.php:21
setSecondEmail(?string $second_email)
string $password_encoding_type
static _writePref(int $a_usr_id, string $a_keyword, string $a_value)
setLongitude(?string $a_longitude)
array $interests_general
setLocationZoom(?int $a_locationzoom)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
ilLogger $log
DateFormatFactory $date_format_factory
setLastPasswordChangeToNow()
string $approve_date
setZipcode(string $a_str)
ilCronDeleteInactiveUserReminderMail $cron_delete_user_reminder_mail
setTimeLimitMessage(string $a_time_limit_message)
static _lookupFirstLogin(int $a_user_id)
debug(string $message, array $context=[])
Class for user related exception handling in ILIAS.
string $client_ip
setUserDefinedData(array $a_data)
static _lookupType(int $id, bool $reference=false)
string $zipcode
static setUseRelativeDates(bool $a_status)
set use relative dates
setGeneralInterests(?array $value=null)
setTimeLimitFrom(?int $a_from)
getClipboardChilds(int $a_parent, string $a_insert_time)
Get children of an item.
string $referral_comment
setFirstname(string $a_str)
string $inactivation_date
static _lookupEmail(int $a_user_id)
string $sel_country
static clear(string $a_var)
static _getInstance()
Get instance of ilSecuritySettings.
string $firstname
static getInstance()
Singleton method to reduce footprint (included files, created instances)
static set(string $a_var, $a_val)
Set a value.
static _getUsersForIds(array $a_mem_ids, int $active=-1, int $timelimitowner=-1)
return user data for given user id
setAuthMode(?string $a_str)
setCurrentLanguage(string $a_val)
Set current language.
static _lookupActive(int $a_usr_id)
hasPublicProfile()
returns true if public is profile, false otherwise
static _getAllUserAssignedStyles()
setLastUpdate(string $a_str)
static getUserIdsNeverLoggedIn(int $thresholdInDays)
Get ids of all users that have never logged in.
setOwner(int $usr_id)
static _removeTrackingDataForUser(int $user_id)
getClipboardObjects(string $a_type="", bool $a_top_nodes_only=false)
get all clipboard objects of user and specified type
static _getLocalAccountsForEmail(string $a_email)
clipboardHasObjectsOfType(string $a_type)
Check whether clipboard has objects of a certain type.
ilObjUser $user
$r
static _lookupLogin(int $a_user_id)
setLookingForHelp(?array $value=null)