ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilECSCmsCourseMemberCommandQueueHandler.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
26{
27 protected ilLogger $log;
28
30 private int $mid = 0;
31
32 private ?ilECSnodeMappingSettings $mapping = null;
33
38 {
39 global $DIC;
40 $this->log = $DIC->logger()->wsrv();
41 $this->server = $server;
42 }
43
47 public function getServer(): \ilECSSetting
48 {
49 return $this->server;
50 }
51
55 public function getMid(): int
56 {
57 return $this->mid;
58 }
59
63 public function checkAllocationActivation(ilECSSetting $server, $a_content_id): bool
64 {
65 try {
66 $crsm_reader = new ilECSCourseMemberConnector($server);
67 $details = $crsm_reader->getCourseMember($a_content_id, true);
68 $this->mid = $details->getMySender();
69
70 // Check if import is enabled
71 $part = ilECSParticipantSetting::getInstance($this->getServer()->getServerId(), $this->getMid());
72 if (!$part->isImportEnabled()) {
73 $this->log->warning('Import disabled for mid ' . $this->getMid());
74 return false;
75 }
76 // Check course allocation setting
78 $this->getServer()->getServerId(),
79 $this->getMid()
80 );
81 return $this->mapping->isCourseAllocationEnabled();
82 } catch (ilECSConnectorException $e) {
83 $this->log->error('Reading course member details failed with message ' . $e->getMessage());
84 return false;
85 }
86 }
87
88
92 public function handleCreate(ilECSSetting $server, $a_content_id): bool
93 {
94 if (!$this->checkAllocationActivation($server, $a_content_id)) {
95 return true;
96 }
97 try {
98 //$course = $this->readCourse($server, $a_content_id);
99 $course_member = $this->readCourseMember($server, $a_content_id);
100 $this->doUpdate($a_content_id, $course_member);
101 return true;
102 } catch (ilECSConnectorException $e) {
103 $this->log->error('Course member creation failed with mesage ' . $e->getMessage());
104 return false;
105 }
106 return true;
107 }
108
112 public function handleDelete(ilECSSetting $server, $a_content_id): bool
113 {
114 // nothing todo
115 return true;
116 }
117
121 public function handleUpdate(ilECSSetting $server, $a_content_id): bool
122 {
123 if (!$this->checkAllocationActivation($server, $a_content_id)) {
124 return true;
125 }
126
127 try {
128 $course_member = $this->readCourseMember($server, $a_content_id);
129 $this->doUpdate($a_content_id, $course_member);
130 return true;
131 } catch (ilECSConnectorException $e) {
132 $this->log->error('Course member update failed with mesage ' . $e->getMessage());
133 return false;
134 }
135 return true;
136 }
137
138
142 protected function doUpdate($a_content_id, $course_member): bool
143 {
144 $this->log->debug('Starting ecs member update');
145
146 if (is_array($course_member) && !isset($course_member["lectureID"])) {
147 $this->log->warning('Missing course id in course_member');
148 return false;
149 }
150
151 $course_id = (int) $course_member->lectureID;
152 if (!$course_id) {
153 $this->log->warning('Missing course id');
154 return false;
155 }
156 $this->log->debug('sid: ' . $this->getServer()->getServerId() . ' course_id: ' . $course_id . ' mid: ' . $this->mid);
157 //$crs_obj_id = ilECSImportManager::getInstance()->_lookupObjId($this->getServer()->getServerId(), $course_id, $this->mid);
158 $crs_obj_id = ilECSImportManager::getInstance()->lookupObjIdByContentId($this->getServer()->getServerId(), $this->mid, $course_id);
159
160 if (!$crs_obj_id) {
161 $this->log->info('No main course created. Group scenario >= 3 ?');
162 }
163
164 $course = $this->readCourse($course_member);
165 if (is_null($course)) {
166 $this->log->info('No course found, skip processing' . print_r($course_member, true));
167 return true;
168 }
169 // Lookup already imported users and update their status
170 $assignments = $this->readAssignments($course, $course_member);
171
172 $this->log->debug('Parallel group assignments');
173 $this->log->dump($assignments, ilLogLevel::DEBUG);
174 $this->log->debug('------------------ End assignemtns');
175
176 // iterate through all parallel groups
177 foreach ($assignments as $cms_id => $assigned) {
178 $sub_id = ($cms_id === $course_id) ? null : (string) $cms_id;
179
180 $this->log->debug('sub id is ' . is_null($sub_id) ? "<null>" : $sub_id . ' for ' . $cms_id);
181
182 $obj_id = ilECSImportManager::getInstance()->lookupObjIdByContentId(
183 $this->getServer()->getServerId(),
184 $this->getMid(),
185 $course_id,
186 $sub_id
187 );
188
189 $this->refreshAssignmentStatus($course_member, $obj_id, $sub_id, $assigned);
190 }
191 return true;
192 }
193
197 protected function readAssignments($course, $course_member): array
198 {
199 //TODO check if this switch is still needed
200 if (!property_exists($course, 'groupScenario')) {
201 $course->groupScenario = ilECSMappingUtils::PARALLEL_ONE_COURSE;
202 }
203
204 switch ((int) $course->groupScenario) {
206 $this->log->debug('Parallel group scenario one course.');
207 break;
208
210 $this->log->debug('Parallel group scenario groups in courses.');
211 break;
212
214 $this->log->debug('Parallel group scenario only courses.');
215 break;
216
217 default:
218 $this->log->debug('Parallel group scenario undefined.');
219 break;
220 }
221
222 $course_id = $course_member->lectureID;
223 $assigned = array();
224 foreach ((array) $course_member->members as $member) {
225 $assigned[$course_id][$member->personID] = array(
226 'id' => $member->personID,
227 'role' => $member->role
228 );
229 if ((int) $course->groupScenario === ilECSMappingUtils::PARALLEL_ONE_COURSE) {
230 $this->log->debug('Group scenarion "one course". Ignoring group assignments');
231 continue;
232 }
233
234 if (property_exists($member, 'groups')) {
235 foreach ((array) $member->groups as $pgroup) {
236 // the sequence number in the course ressource
237 $sequence_number = (int) $pgroup->num;
238 // find parallel group with by sequence number
239 if (property_exists($course, 'groups')) {
240 $tmp_pgroup = $course->groups[$sequence_number] ?? null;
241
242 if (is_object($tmp_pgroup) && $tmp_pgroup->id !== '') {
243 $this->log->debug('Found parallel group with id: ' . $tmp_pgroup->id . ': for sequence number: ' . $sequence_number);
244
245 // @todo check hierarchy of roles
246 $assigned[$tmp_pgroup->id][$member->personID] = array(
247 'id' => $member->personID,
248 'role' => $pgroup->role
249 );
250 } else {
251 $this->log->warning('Cannot find parallel group with sequence id: ' . $sequence_number);
252 }
253 } else {
254 $this->log->error('Invalid course/group-configuration found, ignoring}');
255 }
256
257 }
258 }
259 }
260 $this->log->debug('ECS member assignments ' . print_r($assigned, true));
261 return $assigned;
262 }
263
264
265
269 protected function refreshAssignmentStatus(object $course_member, int $obj_id, ?string $sub_id, $assigned): bool
270 {
271 $this->log->debug('Currrent sub_id = ' . $sub_id . ', obj_id = ' . $obj_id);
272
273 $type = ilObject::_lookupType($obj_id);
274 if ($type === 'crs') {
276 } elseif ($type === 'grp') {
278 } else {
279 $this->log->warning('Invalid object type given for obj_id: ' . $obj_id);
280 return false;
281 }
282
283 $course_id = (int) $course_member->lectureID;
285 $course_id,
286 is_null($sub_id) ? $sub_id : (int) $sub_id,
287 $obj_id
288 );
289 $this->log->debug('Current coursemember assignments:');
290 $this->log->dump($usr_ids, ilLogLevel::DEBUG);
291
292 // Delete remote deleted
293 foreach ($usr_ids as $usr_id) {
294 if (!isset($assigned[$usr_id])) {
295 $ass = ilECSCourseMemberAssignment::lookupAssignment($course_id, is_null($sub_id) ? $sub_id : (int) $sub_id, $obj_id, $usr_id);
296 if ($ass instanceof ilECSCourseMemberAssignment) {
298 $this->mapping->getAuthMode(),
299 (string) $usr_id
300 );
301
302 $this->log->debug('Local user assignment: ' . $usr_id . ' <-> ' . $login);
303
304 if ($il_usr_id = ilObjUser::_lookupId($login)) {
305 // this removes also admin, tutor roles
306 $part->delete($il_usr_id);
307 $this->log->info('Deassigning user ' . $usr_id . ' ' . 'from course ' . ilObject::_lookupTitle($obj_id));
308 } else {
309 $this->log->notice('Deassigning unknown ILIAS user ' . $usr_id . ' ' . 'from course ' . ilObject::_lookupTitle($obj_id));
310 }
311
312 $ass->delete();
313 }
314 }
315 }
316
317 $this->log->debug('Handled assignmnent...');
318
319 // Assign new participants
320 foreach ((array) $assigned as $person_id => $person) {
321 $role = $this->lookupRole((string) $person['role'], $type);
322 $role_info = ilECSMappingUtils::getRoleMappingInfo($role);
323
324 $this->log->debug('Using role info...');
326 $this->mapping->getAuthMode(),
327 (string) $person_id
328 );
329 $this->log->info('Handling user ' . $person_id);
330
331 if (in_array($person_id, $usr_ids, true)) {
332 if ($il_usr_id = ilObjUser::_lookupId($login)) {
333 $this->log->info('Update user assignment for: ' . $person_id);
334 $part->updateRoleAssignments($il_usr_id, array($part->getAutoGeneratedRoleId($role)));
335 } elseif ($role_info['create']) {
336 $this->createMember($person_id);
337 $this->log->info('Added new user ' . $person_id);
339 $this->mapping->getAuthMode(),
340 (string) $person_id
341 );
342 if ($role && $il_usr_id = ilObjUser::_lookupId($login)) {
343 $part->add($il_usr_id, $role);
344 $part->sendNotification(ilCourseMembershipMailNotification::TYPE_ADMISSION_MEMBER, $il_usr_id);
345 }
346 }
347 } else {
348 if ($il_usr_id = ilObjUser::_lookupId($login)) {
349 // user exists => assign to course/group
350 if ($role) {
351 // Assign user
352 $this->log->info('Assigning new user ' . $person_id . ' ' . 'to ' . ilObject::_lookupTitle($obj_id) . ' using role: ' . $role);
353 $part->add($il_usr_id, $role);
354 $part->sendNotification(ilCourseMembershipMailNotification::TYPE_ADMISSION_MEMBER, $il_usr_id);
355 }
356 } else {
357 // no local user exists
358 if ($role_info['create']) {
359 $this->createMember($person_id);
360 $this->log->info('Added new user ' . $person_id);
362 $this->mapping->getAuthMode(),
363 (string) $person_id
364 );
365 }
366 // Assign to role
367 if ($role && $il_usr_id = ilObjUser::_lookupId($login)) {
368 $this->log->info('Assigning new role to existing user ' . $person_id . ' ' . 'to ' . ilObject::_lookupTitle($obj_id) . ' using role: ' . $role);
369 $part->add($il_usr_id, $role);
370 $part->sendNotification(ilCourseMembershipMailNotification::TYPE_ADMISSION_MEMBER, $il_usr_id);
371 }
372 }
373
374 $assignment = new ilECSCourseMemberAssignment();
375 $assignment->setServer($this->getServer()->getServerId());
376 $assignment->setMid($this->mid);
377 $assignment->setCmsId($course_id);
378 $assignment->setCmsSubId(is_null($sub_id) ? $sub_id : (int) $sub_id);
379 $assignment->setObjId($obj_id);
380 $assignment->setUid((string) $person_id);
381 $assignment->save();
382 }
383 }
384 return true;
385 }
386
390 protected function lookupRole(string $role_value, $a_obj_type): int
391 {
392 $role_mappings = $this->mapping->getRoleMappings();
393
394 /* Zero is an allowed value */
395 if (!$role_value) {
396 $this->log->debug('No role assignment attribute: role');
397 }
398 foreach ($role_mappings as $name => $map) {
399 $this->log->debug('Role "name" is ' . $name);
400
401 // map is a string of ids seperated by ","
402 $exploded_map = (array) explode(',', $map);
403 if (in_array($role_value, $exploded_map, true)) {
404 switch ($name) {
408 if ($a_obj_type === 'crs') {
409 $this->log->debug('Role: ' . $role_value . ' maps: ' . $map);
410 return $name;
411 }
412 break;
413
416 if ($a_obj_type === 'grp') {
417 $this->log->debug('Role: ' . $role_value . ' maps: ' . $map);
418 return $name;
419 }
420 break;
421 }
422 }
423 }
424 $this->log->info('No role assignment mapping for role ' . $role_value);
425 return 0;
426 }
427
431 private function createMember($a_person_id): void
432 {
433 if (!$this->mapping instanceof ilECSNodeMappingSettings) {
434 $this->log->warning('Node mapping settings not initialized.');
435 }
436 $auth_mode = $this->mapping->getAuthMode();
437
438 if (
439 $this->mapping->getAuthMode() ===
441 ) {
442 $this->log->info('Not handling direct user creation for auth mode: ' . $auth_mode);
443 return;
444 }
445 if (strpos($auth_mode, 'ldap') !== 0) {
446 $this->log->info('Not handling direct user creation for auth mode: ' . $auth_mode);
447 return;
448 }
449
450 try {
452 $server->doConnectionCheck();
453
454 $query = new ilLDAPQuery($server);
455 $query->bind(ilLDAPQuery::LDAP_BIND_DEFAULT);
456
457 $users = $query->fetchUser((string) $a_person_id);
458 if ($users) {
460
461 $xml = new ilLDAPAttributeToUser($server);
462 $xml->setNewUserAuthMode($server->getAuthenticationMappingKey());
463 $xml->setUserData($users);
464 $xml->refresh();
465 }
466 } catch (ilLDAPQueryException $exc) {
467 $this->log->error($exc->getMessage());
468 }
469 }
470
471
475 private function readCourseMember(ilECSSetting $server, $a_content_id)
476 {
477 return (new ilECSCourseMemberConnector($server))->getCourseMember($a_content_id);
478 }
479
483 private function readCourse($course_member)
484 {
485 $ecs_id = ilECSImportManager::getInstance()->lookupEContentIdByContentId(
486 $this->getServer()->getServerId(),
487 $this->getMid(),
488 $course_member->lectureID
489 );
490 if (0 === $ecs_id) {
491 return null;
492 }
493 return (new ilECSCourseConnector($this->getServer()))->getCourse($ecs_id);
494 }
495}
const int AUTH_SHIBBOLETH
static _getAuthModeName($a_auth_key)
static _getInstanceByObjId(int $a_obj_id)
handleCreate(ilECSSetting $server, $a_content_id)
Handle create.
refreshAssignmentStatus(object $course_member, int $obj_id, ?string $sub_id, $assigned)
Refresh status of course member assignments.
readCourseMember(ilECSSetting $server, $a_content_id)
Read course from ecs.
readAssignments($course, $course_member)
Read assignments for all parallel groups.
lookupRole(string $role_value, $a_obj_type)
Lookup local role by assignment.
checkAllocationActivation(ilECSSetting $server, $a_content_id)
Check if course allocation is activated for one recipient of the.
handleUpdate(ilECSSetting $server, $a_content_id)
Handle update.
handleDelete(ilECSSetting $server, $a_content_id)
Handle delete.
Storage of ecs course assignments.
static lookupAssignment(int $a_cms_id, ?int $a_cms_sub_id, int $a_obj_id, string $a_usr_id)
Lookup assignment of user.
static lookupUserIds(int $a_cms_id, ?int $a_cms_sub_id, int $a_obj_id)
Lookup user ids.
Connector for course member ressource.
static getInstance()
Get the singleton instance of this ilECSImportManager.
static getRoleMappingInfo($a_role_type_info=0)
Get role mapping info.
static getInstanceByServerMid(int $a_server_id, int $a_mid)
Get instance.
static getInstance(int $a_server_id, int $mid)
Get instance by server id and mid.
static _getInstanceByObjId(int $a_obj_id)
Get singleton instance.
Update/create ILIAS user account by given LDAP attributes according to user attribute mapping setting...
static getInstanceByServerId(int $a_server_id)
Get instance by server id.
static _getFirstActiveServer()
Get first active server.
Component logger with individual log levels by component id.
static _lookupId(string|array $a_user_str)
static _checkExternalAuthAccount(string $a_auth, string $a_account, bool $tryFallback=true)
check whether external account and authentication method matches with a user
static _lookupType(int $id, bool $reference=false)
static _lookupTitle(int $obj_id)
Interface for all command queue handler classes.
if(!file_exists('../ilias.ini.php'))
global $DIC
Definition: shib_login.php:26