ILIAS  trunk Revision v12.0_alpha-33-ge186251a14d
DatabaseDataRepository.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
21namespace ILIAS\User\Profile;
22
28use ILIAS\User\Profile\Fields\ConfigurationRepository as ProfileFieldsConfigurationRepository;
31use ILIAS\User\Settings\DataRepository as SettingsDataRepository;
32use ILIAS\ResourceStorage\Services as ResourceStorage;
33
35{
36 private const string USER_BASE_TABLE = 'usr_data';
37 public const string USER_VALUES_TABLE = 'usr_profile_data';
38
39 private const string NO_AVATAR_RID = '-';
40
41 private const array SEARCH_FIELDS = [
42 'login' => true,
43 'firstname' => false,
44 'lastname' => false,
45 'email' => false,
46 'second_email' => false
47 ];
48
49 public function __construct(
50 private readonly \ilDBInterface $db,
51 private readonly ResourceStorage $irss
52 ) {
53 }
54
55 public function getDefault(): Data
56 {
57 return new Data();
58 }
59
60 public function getSingle(int $id): Data
61 {
62 $base_query = $this->db->query(
63 'SELECT * FROM ' . self::USER_BASE_TABLE . " WHERE usr_id={$id}"
64 );
65
66 $additional_query = $this->db->query(
67 'SELECT field_id, value FROM ' . self::USER_VALUES_TABLE . " WHERE usr_id = {$id}"
68 );
69
70 return $this->buildFromData(
71 $this->db->fetchObject($base_query),
72 $this->db->fetchAll(
73 $additional_query,
75 )
76 );
77
78 }
79
80 public function getMultiple(array $user_ids): \Generator
81 {
82 $query = $this->db->query(
83 'SELECT * FROM ' . self::USER_BASE_TABLE
84 . " WHERE {$this->db->in('usr_id', $user_ids, false, \ilDBConstants::T_INTEGER)}"
85 );
86
87 $prepared_query = $this->db->prepare('SELECT field_id, value FROM '
88 . self::USER_VALUES_TABLE . ' WHERE usr_id = ?');
89
90 while (($base_data = $this->db->fetchObject($query)) !== null) {
91 yield $this->buildFromData(
92 $base_data,
93 $this->db->fetchAll(
94 $this->db->execute($prepared_query, [$base_data->usr_id]),
96 )
97 );
98 }
99
100 $this->db->free($prepared_query);
101 }
102
103 public function store(Data $user_data): void
104 {
105 $system_information = $user_data->getSystemInformation();
106 $this->db->replace(
107 self::USER_BASE_TABLE,
108 [
109 'usr_id' => [
111 $user_data->getId()
112 ]
113 ],
114 [
115 'login' => [\ilDBConstants::T_TEXT, $user_data->getAlias()],
116 'firstname' => [\ilDBConstants::T_TEXT, $user_data->getFirstname()],
117 'lastname' => [\ilDBConstants::T_TEXT, $user_data->getLastname()],
118 'title' => [\ilDBConstants::T_TEXT, $user_data->getTitle()],
119 'gender' => [\ilDBConstants::T_TEXT, $user_data->getGender()?->value],
120 'rid' => [\ilDBConstants::T_TEXT, $user_data->getAvatarRid()?->serialize() ?? self::NO_AVATAR_RID],
121 'email' => [\ilDBConstants::T_TEXT, $user_data->getEmail()],
122 'second_email' => [\ilDBConstants::T_TEXT, $user_data->getSecondEmail()],
123 'hobby' => [\ilDBConstants::T_TEXT, $user_data->getHobby()],
124 'institution' => [\ilDBConstants::T_TEXT, $user_data->getInstitution()],
125 'department' => [\ilDBConstants::T_TEXT, $user_data->getDepartment()],
126 'street' => [\ilDBConstants::T_TEXT, $user_data->getStreet()],
127 'city' => [\ilDBConstants::T_TEXT, $user_data->getCity()],
128 'zipcode' => [\ilDBConstants::T_TEXT, $user_data->getZipcode()],
129 'country' => [\ilDBConstants::T_TEXT, $user_data->getCountry()],
130 'phone_office' => [\ilDBConstants::T_TEXT, $user_data->getPhoneOffice()],
131 'phone_home' => [\ilDBConstants::T_TEXT, $user_data->getPhoneHome()],
132 'phone_mobile' => [\ilDBConstants::T_TEXT, $user_data->getPhoneMobile()],
133 'fax' => [\ilDBConstants::T_TEXT, $user_data->getFax()],
134 'birthday' => [\ilDBConstants::T_DATE, $user_data->getBirthday()?->format('Y-m-d')],
135 'referral_comment' => [\ilDBConstants::T_TEXT, $user_data->getReferralComment()],
136 'matriculation' => [\ilDBConstants::T_TEXT, $user_data->getMatriculation()],
137 'latitude' => [\ilDBConstants::T_TEXT, $user_data->getGeoCoordinates()['latitude'] ?? null],
138 'longitude' => [\ilDBConstants::T_TEXT, $user_data->getGeoCoordinates()['longitude'] ?? null],
139 'loc_zoom' => [\ilDBConstants::T_INTEGER, $user_data->getGeoCoordinates()['zoom'] ?? 0],
140 'last_password_change' => [\ilDBConstants::T_INTEGER, $system_information['last_password_change']],
141 'passwd' => [\ilDBConstants::T_TEXT, $system_information['passwd']],
142 'passwd_salt' => [\ilDBConstants::T_TEXT, $system_information['passwd_salt']],
143 'passwd_enc_type' => [\ilDBConstants::T_TEXT, $system_information['passwd_enc_type']],
144 'passwd_policy_reset' => [\ilDBConstants::T_INTEGER, $system_information['passwd_policy_reset'] ? 1 : 0],
145 'client_ip' => [\ilDBConstants::T_TEXT, $system_information['client_ip']],
146 'last_login' => [
148 $system_information['last_login'] !== '' ? $system_information['last_login'] : null
149 ],
150 'first_login' => [
152 $system_information['first_login'] !== '' ? $system_information['first_login'] : null
153 ],
154 'last_profile_prompt' => [
156 $system_information['last_profile_prompt'] !== '' ? $system_information['last_profile_prompt'] : null
157 ],
158 'active' => [\ilDBConstants::T_INTEGER, $system_information['active']],
159 'approve_date' => [\ilDBConstants::T_TIMESTAMP, $system_information['approve_date']],
160 'agree_date' => [\ilDBConstants::T_TIMESTAMP, $system_information['agree_date']],
161 'inactivation_date' => [\ilDBConstants::T_TIMESTAMP, $system_information['inactivation_date']],
162 'time_limit_owner' => [\ilDBConstants::T_INTEGER, $system_information['time_limit_owner']],
163 'time_limit_unlimited' => [\ilDBConstants::T_INTEGER, $system_information['time_limit_unlimited'] ? 1 : 0],
164 'time_limit_from' => [\ilDBConstants::T_INTEGER, $system_information['time_limit_from']],
165 'time_limit_until' => [\ilDBConstants::T_INTEGER, $system_information['time_limit_until']],
166 'profile_incomplete' => [\ilDBConstants::T_INTEGER, $system_information['profile_incomplete']],
167 'auth_mode' => [\ilDBConstants::T_TEXT, $system_information['auth_mode']],
168 'ext_account' => [\ilDBConstants::T_TEXT, $system_information['ext_account']],
169 'is_self_registered' => [\ilDBConstants::T_INTEGER, $system_information['is_self_registered'] ? 1 : 0],
170 'last_update' => [\ilDBConstants::T_TIMESTAMP, date('Y-m-d H:i:s')],
171 'create_date' => [\ilDBConstants::T_TIMESTAMP, $system_information['create_date']],
172 'last_visited' => [
174 $system_information['last_visited'] === [] ? null : serialize($system_information['last_visited'])
175 ]
176 ]
177 );
178
179 $this->storeAdditionalFields($user_data);
180 }
181
182 public function deleteForFieldIdentifier(string $identifier): void
183 {
184 $this->db->manipulateF(
185 'DELETE FROM ' . self::USER_VALUES_TABLE
186 . " WHERE field_id='{$this->db->quote($identifier, \ilDBConstants::T_TEXT)}'"
187 );
188 }
189
190 public function deleteForUser(int $usr_id): void
191 {
192 $this->db->manipulate(
193 'DELETE FROM ' . self::USER_BASE_TABLE
194 . " WHERE usr_id='{$this->db->quote($usr_id, \ilDBConstants::T_INTEGER)}'"
195 );
196 $this->db->manipulate(
197 'DELETE FROM ' . self::USER_VALUES_TABLE
198 . " WHERE usr_id='{$this->db->quote($usr_id, \ilDBConstants::T_INTEGER)}'"
199 );
200 }
201
202 public function storePasswordFor(
203 int $usr_id,
204 string $password,
205 string $encoding_type,
206 ?string $salt
207 ): void {
208 $this->db->manipulateF(
209 'UPDATE ' . self::USER_BASE_TABLE . ' SET passwd = %s,' . PHP_EOL
210 . 'passwd_enc_type = %s, passwd_salt = %s WHERE usr_id = %s',
211 [\ilDBConstants::T_TEXT, \ilDBConstants::T_TEXT, \ilDBConstants::T_TEXT, \ilDBConstants::T_INTEGER],
212 [$password, $encoding_type, $salt, $usr_id]
213 );
214 }
215
216 public function storeLoginFor(
217 int $usr_id,
218 string $login
219 ): void {
220 $this->db->manipulateF(
221 'UPDATE ' . self::USER_BASE_TABLE . ' SET login = %s WHERE usr_id = %s',
222 [\ilDBConstants::T_TEXT, \ilDBConstants::T_INTEGER],
223 [$login, $usr_id]
224 );
225 }
226
227 public function storeLastVisitedFor(
228 int $usr_id,
229 array $last_visited
230 ): void {
231 $this->db->manipulateF(
232 'UPDATE ' . self::USER_BASE_TABLE . ' SET last_visited = %s WHERE usr_id = %s',
233 [\ilDBConstants::T_TEXT, \ilDBConstants::T_INTEGER],
234 [
235 $last_visited === [] ? null : serialize($last_visited),
236 $usr_id
237 ]
238 );
239 }
240
244 public function searchUsers(
245 SettingsDataRepository $settings_data_repository,
246 ProfileFieldsConfigurationRepository $profile_fields_config_repo,
247 AutocompleteQuery $autocomplete_query
248 ): array {
249 $where = $this->buildSearchUsersWhereString(
250 $profile_fields_config_repo,
251 $autocomplete_query
252 );
253
254 if ($where === null) {
255 return [];
256 }
257
258 $query = $this->db->query(
259 $settings_data_repository->getSearchSelectConditionalOnVisibility(
260 self::USER_BASE_TABLE,
261 ...array_keys(self::SEARCH_FIELDS)
262 ) . PHP_EOL
263 . $where
264 );
265
266 $results = [];
267 while (($row = $this->db->fetchObject($query)) !== null) {
269 $row->login,
270 $row->lastname ?? '',
271 $row->firstname ?? '',
272 $autocomplete_query->getUnprocessedSearchTerm()
273 );
274 }
275 return $results;
276 }
277
278 private function buildFromData(
279 \stdClass $base_data,
280 array $additional_data
281 ): Data {
282 return (new Data(
283 $base_data->usr_id,
284 $base_data->login,
285 $base_data->rid !== null && $base_data->rid !== self::NO_AVATAR_RID
286 ? $this->irss->manage()->find($base_data->rid)
287 : null,
288 $base_data->firstname ?? '',
289 $base_data->lastname ?? '',
290 $base_data->title ?? '',
291 Genders::tryFrom($base_data->gender ?? ''),
292 $base_data->birthday !== null
293 ? new \DateTimeImmutable($base_data->birthday, new \DateTimeZone('UTC'))
294 : null,
295 $base_data->institution ?? '',
296 $base_data->department ?? '',
297 $base_data->street ?? '',
298 $base_data->city ?? '',
299 $base_data->zipcode ?? '',
300 $base_data->country ?? '',
301 $base_data->email ?? '',
302 $base_data->second_email,
303 $base_data->phone_office ?? '',
304 $base_data->phone_home ?? '',
305 $base_data->phone_mobile ?? '',
306 $base_data->fax ?? '',
307 $base_data->matriculation ?? '',
308 $base_data->hobby ?? '',
309 $base_data->referral_comment ?? '',
310 [
311 'latitude' => $base_data->latitude,
312 'longitude' => $base_data->longitude,
313 'zoom' => $base_data->loc_zoom
314 ],
315 array_reduce(
316 $additional_data,
317 static function (array $c, \stdClass $v): array {
318 if (!array_key_exists($v->field_id, $c)) {
319 $c[$v->field_id] = [];
320 }
321 $c[$v->field_id][] = $v->value;
322 return $c;
323 },
324 []
325 )
326 ))->withSystemInformation([
327 'last_password_change' => $base_data->last_password_change,
328 'login_attempts' => $base_data->login_attempts,
329 'passwd' => $base_data->passwd,
330 'passwd_salt' => $base_data->passwd_salt,
331 'passwd_enc_type' => $base_data->passwd_enc_type,
332 'passwd_policy_reset' => $base_data->passwd_policy_reset === 1,
333 'client_ip' => $base_data->client_ip ?? '',
334 'last_login' => $base_data->last_login ?? '',
335 'first_login' => $base_data->first_login ?? '',
336 'last_profile_prompt' => $base_data->last_profile_prompt ?? '',
337 'active' => $base_data->active,
338 'approve_date' => $base_data->approve_date,
339 'agree_date' => $base_data->agree_date,
340 'inactivation_date' => $base_data->inactivation_date,
341 'time_limit_owner' => $base_data->time_limit_owner,
342 'time_limit_unlimited' => $base_data->time_limit_unlimited === 1,
343 'time_limit_from' => $base_data->time_limit_from,
344 'time_limit_until' => $base_data->time_limit_until,
345 'profile_incomplete' => $base_data->profile_incomplete === 1,
346 'auth_mode' => $base_data->auth_mode,
347 'ext_account' => $base_data->ext_account,
348 'is_self_registered' => $base_data->is_self_registered === 1,
349 'last_update' => $base_data->last_update ?? '',
350 'create_date' => $base_data->create_date ?? '',
351 'last_visited' => $base_data->last_visited === null
352 ? []
353 : unserialize($base_data->last_visited, ['allowed_classes' => false])
354 ]);
355 }
356
357 private function storeAdditionalFields(Data $user_data): void
358 {
359 $this->db->manipulate(
360 'DELETE FROM ' . self::USER_VALUES_TABLE
361 . " WHERE usr_id = {$user_data->getId()}"
362 );
363
364 $values_for_storage = $user_data->getAdditionalFieldsStorageValues($this->db);
365 if ($values_for_storage === '') {
366 return;
367 }
368
369 $this->db->manipulate(
370 'INSERT INTO ' . self::USER_VALUES_TABLE . ' (usr_id, field_id, value) '
371 . 'VALUES ' . $values_for_storage
372 );
373 }
374
376 ProfileFieldsConfigurationRepository $profile_fields_config_repo,
377 AutocompleteQuery $autocomplete_query
378 ): ?string {
379 $available_fields = array_filter(
380 $this->getSearchFieldsWithAvailability(
381 $profile_fields_config_repo,
382 $autocomplete_query
383 )
384 );
385
386 if ($available_fields === []) {
387 return null;
388 }
389
390 $outer_conditions = [];
391 $outer_conditions[] = 'usr_data.usr_id != ' . $this->db->quote(ANONYMOUS_USER_ID, \ilDBConstants::T_INTEGER);
392 $outer_conditions[] = 'usr_data.active != ' . $this->db->quote(0, \ilDBConstants::T_INTEGER);
393
394 if (\ilUserAccountSettings::getInstance()->isUserAccessRestricted()) {
395 $outer_conditions[] = $this->db->in(
396 'time_limit_owner',
397 \ilUserFilter::getInstance()->getFolderIds(),
398 false,
399 'integer'
400 );
401 }
402
403 $outer_conditions[] = '(' . implode(
404 ' OR ',
405 array_map(
406 fn(string $v) => $this->db->like($v, \ilDBConstants::T_TEXT, "%{$available_fields[$v]}%"),
407 array_keys($available_fields)
408 )
409 ) . ')';
410
411 return ' WHERE ' . implode(' AND ', $outer_conditions);
412 }
413
415 ProfileFieldsConfigurationRepository $profile_fields_config_repo,
416 AutocompleteQuery $autocomplete_query
417 ): array {
418 $search_term = $autocomplete_query->getSearchTermQueryString();
419 $search_term_long_enough = $autocomplete_query->checkSearchTermLength($search_term);
420 $firstname_term = $autocomplete_query->getFirstnameQueryString();
421 $lastname_term = $autocomplete_query->getLastnameQueryString();
422
423 return array_merge(
424 self::SEARCH_FIELDS,
425 [
426 'login' => $search_term_long_enough ? $search_term : null,
427 'firstname' => $profile_fields_config_repo->getByClass(FirstName::class)->isSearchable()
428 && $autocomplete_query->checkSearchTermLength($firstname_term)
429 ? $firstname_term : null,
430 'lastname' => $profile_fields_config_repo->getByClass(LastName::class)->isSearchable()
431 && $autocomplete_query->checkSearchTermLength($lastname_term)
432 ? $autocomplete_query->getLastnameQueryString() : null,
433 'email' => $profile_fields_config_repo->getByClass(Email::class)->isSearchable()
434 && $search_term_long_enough
435 ? $autocomplete_query->getSearchTermQueryString() : null,
436 'second_email' => $profile_fields_config_repo->getByClass(SecondEmail::class)->isSearchable()
437 && $search_term_long_enough
438 ? $autocomplete_query->getSearchTermQueryString() : null
439 ]
440 );
441 }
442}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
getAdditionalFieldsStorageValues(\ilDBInterface $db)
Definition: Data.php:359
searchUsers(SettingsDataRepository $settings_data_repository, ProfileFieldsConfigurationRepository $profile_fields_config_repo, AutocompleteQuery $autocomplete_query)
__construct(private readonly \ilDBInterface $db, private readonly ResourceStorage $irss)
getSearchFieldsWithAvailability(ProfileFieldsConfigurationRepository $profile_fields_config_repo, AutocompleteQuery $autocomplete_query)
buildSearchUsersWhereString(ProfileFieldsConfigurationRepository $profile_fields_config_repo, AutocompleteQuery $autocomplete_query)
storeLastVisitedFor(int $usr_id, array $last_visited)
buildFromData(\stdClass $base_data, array $additional_data)
storePasswordFor(int $usr_id, string $password, string $encoding_type, ?string $salt)
This class provides some pre-processing for search terms provided by a user when searching for users.
getUnprocessedSearchTerm()
The returned search term might contain wild cards or any other input.
checkSearchTermLength(?string $search_term)
Class ilDBConstants.
const ANONYMOUS_USER_ID
Definition: constants.php:27
$c
Definition: deliver.php:25
return['delivery_method'=> 'php',]
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Interface ilDBInterface.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$results
if(!file_exists('../ilias.ini.php'))