ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
class.ilCourseXMLParser.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=0);
20 
22 
28 {
29  public const int MODE_SOAP = 1;
30  public const int MODE_EXPORT = 2;
31 
32  private int $mode = self::MODE_EXPORT;
33 
34  private bool $in_availability = false;
35  private bool $in_registration = false;
36  private bool $in_period = false;
37  private bool $in_period_with_time = false;
38 
41 
42  private string $cdata = '';
43 
44  private string $current_container_setting = ''; // current meta data object
46  private ?ilLogger $log;
47  protected ilSetting $setting;
53  protected array $course_members_array = [];
54 
55  public function __construct(ilObjCourse $a_course_obj, string $a_xml_file = '')
56  {
57  global $DIC;
58 
59  parent::__construct($a_xml_file);
60  $this->sax_controller = new ilSaxController();
61  $this->log = $DIC->logger()->crs();
62  $this->setting = $DIC->settings();
63  $this->course_obj = $a_course_obj;
64  $this->translations = $this->course_obj->getObjectProperties()->getPropertyTranslations();
65  $this->course_members = ilCourseParticipants::_getInstanceByObjId($this->course_obj->getId());
66  $this->course_waiting_list = new ilCourseWaitingList($this->course_obj->getId());
67  // flip the array so we can use array_key_exists
68  $this->course_members_array = array_flip($this->course_members->getParticipants());
69  }
70 
71  public function setMode(int $a_mode): void
72  {
73  $this->mode = $a_mode;
74  }
75 
76  public function getMode(): int
77  {
78  return $this->mode;
79  }
80 
84  public function setHandlers($a_xml_parser): void
85  {
86  $this->sax_controller->setHandlers($a_xml_parser);
87  $this->sax_controller->setDefaultElementHandler($this);
88  $this->sax_controller->setElementHandler(
89  $this->adv_md_handler = new ilAdvancedMDValueParser($this->course_obj->getId()),
90  'AdvancedMetaData'
91  );
92  }
93 
97  public function handlerBeginTag($a_xml_parser, string $a_name, array $a_attribs): void
98  {
99  $a_attribs = $this->trimAndStripAttribs($a_attribs);
100 
101  switch ($a_name) {
102  case 'Course':
103  if (strlen($a_attribs['importId'] ?? '')) {
104  $this->log->write("CourseXMLParser: importId = " . $a_attribs['importId']);
105  $this->course_obj->setImportId($a_attribs['importId']);
106  ilObject::_writeImportId($this->course_obj->getId(), $a_attribs['importId']);
107  }
108  if (strlen($a_attribs['showMembers'] ?? '')) {
109  $this->course_obj->setShowMembers(
110  $a_attribs['showMembers'] == 'Yes'
111  );
112  }
113  break;
114 
115  case 'Admin':
116  if ($id_data = $this->__parseId($a_attribs['id'] ?? '')) {
117  if ($id_data['local'] or $id_data['imported']) {
118  $this->handleAdmin($a_attribs, $id_data);
119  }
120  }
121  break;
122 
123  case 'Tutor':
124  if ($id_data = $this->__parseId($a_attribs['id'] ?? '')) {
125  if ($id_data['local'] or $id_data['imported']) {
126  $this->handleTutor($a_attribs, $id_data);
127  }
128  }
129  break;
130 
131  case 'Member':
132  if ($id_data = $this->__parseId($a_attribs['id'] ?? '')) {
133  if ($id_data['local'] or $id_data['imported']) {
134  $this->handleMember($a_attribs, $id_data);
135  }
136  }
137  break;
138 
139  case 'Subscriber':
140  if ($id_data = $this->__parseId($a_attribs['id'] ?? '')) {
141  if ($id_data['local'] or $id_data['imported']) {
142  $this->handleSubscriber($a_attribs, $id_data);
143  }
144  }
145  break;
146 
147  case 'WaitingList':
148  if ($id_data = $this->__parseId($a_attribs['id'] ?? '')) {
149  if ($id_data['local'] or $id_data['imported']) {
150  $this->handleWaitingList($a_attribs, $id_data);
151  }
152  }
153  break;
154 
155  case 'Owner':
156  if ($id_data = $this->__parseId($a_attribs['id'] ?? '')) {
157  if ($id_data['local'] or $id_data['imported']) {
158  $this->course_obj->setOwner((int) ($id_data['usr_id'] ?? 0));
159  $this->course_obj->updateOwner();
160  }
161  }
162  break;
163 
164  case 'Settings':
165  break;
166  case 'Availability':
167  $this->in_availability = true;
168  break;
169 
170  case 'NotAvailable':
171  if ($this->in_availability) {
172  $this->course_obj->setOfflineStatus(true);
173  } elseif ($this->in_registration) {
174  $this->course_obj->setSubscriptionLimitationType(ilCourseConstants::IL_CRS_SUBSCRIPTION_DEACTIVATED);
175  }
176 
177  break;
178 
179  case 'Unlimited':
180  if ($this->in_availability) {
181  $this->course_obj->setOfflineStatus(false);
182  } elseif ($this->in_registration) {
183  $this->course_obj->setSubscriptionLimitationType(ilCourseConstants::IL_CRS_SUBSCRIPTION_UNLIMITED);
184  }
185 
186  break;
187  case 'TemporarilyAvailable':
188  if ($this->in_availability) {
189  $this->course_obj->setOfflineStatus(false);
190  } elseif ($this->in_registration) {
191  $this->course_obj->setSubscriptionLimitationType(ilCourseConstants::IL_CRS_SUBSCRIPTION_LIMITED);
192  }
193  break;
194 
195  case 'Start':
196  break;
197 
198  case 'End':
199  break;
200 
201  case 'Syllabus':
202  break;
203 
204  case 'TargetGroup':
205  break;
206 
207  case 'Contact':
208  break;
209 
210  case 'Name':
211  case 'Responsibility':
212  case 'Phone':
213  case 'Email':
214  case 'Consultation':
215  break;
216 
217  case 'Registration':
218  $this->in_registration = true;
219 
220  switch ($a_attribs['registrationType'] ?? '') {
221  case 'Confirmation':
222  $this->course_obj->setSubscriptionType(ilCourseConstants::IL_CRS_SUBSCRIPTION_CONFIRMATION);
223  break;
224 
225  case 'Direct':
226  $this->course_obj->setSubscriptionType(ilCourseConstants::IL_CRS_SUBSCRIPTION_DIRECT);
227  break;
228 
229  case 'Password':
230  $this->course_obj->setSubscriptionType(ilCourseConstants::IL_CRS_SUBSCRIPTION_PASSWORD);
231  break;
232  }
233 
234  $this->course_obj->setSubscriptionMaxMembers((int) ($a_attribs['maxMembers'] ?? 0));
235  $this->course_obj->enableSubscriptionMembershipLimitation($this->course_obj->getSubscriptionMaxMembers() > 0);
236  $this->course_obj->enableWaitingList(($a_attribs['waitingList'] ?? null) == 'Yes' ? true : false);
237  break;
238 
239  case 'Sort':
240  ilContainerSortingSettings::_importContainerSortingSettings($a_attribs, $this->course_obj->getId());
241 
242  //#17837
243  $this->course_obj->setOrderType(
244  ilContainerSortingSettings::getInstanceByObjId($this->course_obj->getId())->getSortMode()
245  );
246  break;
247 
248  case 'Disabled':
249  $this->course_obj->setSubscriptionLimitationType(ilCourseConstants::IL_CRS_SUBSCRIPTION_DEACTIVATED);
250  break;
251 
252  case 'ContainerSetting':
253  $this->current_container_setting = ($a_attribs['id'] ?? '');
254  break;
255 
256  case 'Period':
257  $this->in_period = true;
258  $this->in_period_with_time = (bool) ($a_attribs['withTime'] ?? false);
259  break;
260 
261  case 'WaitingListAutoFill':
262  case 'CancellationEnd':
263  case 'MinMembers':
264  case 'StatusDetermination':
265  case 'MailToMembersType':
266  break;
267 
268  case 'WelcomeMail':
269  if (array_key_exists('status', $a_attribs)) {
270  $this->course_obj->setAutoNotification((bool) $a_attribs['status']);
271  }
272  break;
273 
274  case 'CourseMap':
275  $this->course_obj->setEnableCourseMap((bool) $a_attribs['enabled'] ?? false);
276  $this->course_obj->setLatitude((string) $a_attribs['latitude'] ?? '');
277  $this->course_obj->setLongitude((string) $a_attribs['longitude'] ?? '');
278  $this->course_obj->setLocationZoom((int) $a_attribs['location_zoom'] ?? 0);
279  break;
280 
281  case 'TutorialSupportBlock':
282  if (isset($a_attribs['active'])) {
283  $this->course_obj->setTutorialSupportBlockSettingValue((int) $a_attribs['active']);
284  }
285  break;
286 
287  case 'SessionLimit':
288  if (isset($a_attribs['active'])) {
289  $this->course_obj->enableSessionLimit((bool) $a_attribs['active']);
290  }
291  if (isset($a_attribs['previous'])) {
292  $this->course_obj->setNumberOfPreviousSessions((int) $a_attribs['previous']);
293  }
294  if (isset($a_attribs['next'])) {
295  $this->course_obj->setNumberOfNextSessions((int) $a_attribs['next']);
296  }
297  break;
298  }
299  }
300 
301  public function __parseId($a_id): array
302  {
303  $fields = explode('_', $a_id);
304 
305  if (!is_array($fields) or
306  $fields[0] != 'il' or
307  !is_numeric($fields[1]) or
308  $fields[2] != 'usr' or
309  !is_numeric($fields[3])) {
310  return [];
311  }
312  if ($id = ilObjUser::_getImportedUserId($a_id)) {
313  return array('imported' => true,
314  'local' => false,
315  'usr_id' => $id
316  );
317  }
318  if ($fields[1] == $this->setting->get('inst_id', '0') && strlen(ilObjUser::_lookupLogin((int) $fields[3]))) {
319  return array('imported' => false,
320  'local' => true,
321  'usr_id' => (int) $fields[3]
322  );
323  }
324  return [];
325  }
326 
330  private function handleAdmin(array $a_attribs, array $id_data): void
331  {
332  if (!isset($a_attribs['action']) || $a_attribs['action'] == 'Attach') {
333  // if action not set, or attach
334  if (!array_key_exists($id_data['usr_id'], $this->course_members_array)) {
335  // add only if member is not assigned yet
336  $this->course_members->add($id_data['usr_id'], ilParticipants::IL_CRS_ADMIN);
337  if (isset($a_attribs['notification']) && $a_attribs['notification'] == 'Yes') {
338  $this->course_members->updateNotification($id_data['usr_id'], true);
339  }
340  if (isset($a_attribs['passed']) && $a_attribs['passed'] == 'Yes') {
341  $this->course_members->updatePassed($id_data['usr_id'], true);
342  }
343  if (isset($a_attribs['contact']) && $a_attribs['contact'] == 'Yes') {
344  // default for new course admin/tutors is "no contact"
345  $this->course_members->updateContact($id_data['usr_id'], true);
346  }
347  $this->course_members_array[$id_data['usr_id']] = "added";
348  } else {
349  // update
350  if (isset($a_attribs['notification']) && $a_attribs['notification'] == 'Yes') {
351  $this->course_members->updateNotification($id_data['usr_id'], true);
352  }
353  if (isset($a_attribs['passed']) && $a_attribs['passed'] == 'Yes') {
354  $this->course_members->updatePassed($id_data['usr_id'], true);
355  }
356  if (isset($a_attribs['contact']) && $a_attribs['contact'] == 'Yes') {
357  $this->course_members->updateContact($id_data['usr_id'], true);
358  } elseif (isset($a_attribs['contact']) && $a_attribs['contact'] == 'No') {
359  $this->course_members->updateContact($id_data['usr_id'], false);
360  }
361  $this->course_members->updateBlocked($id_data['usr_id'], false);
362  }
363  } elseif (isset($a_attribs['action']) && $a_attribs['action'] == 'Detach' && $this->course_members->isAdmin($id_data['usr_id'])) {
364  // if action set and detach and is admin of course
365  $this->course_members->delete($id_data['usr_id']);
366  }
367  }
368 
369  private function handleTutor(array $a_attribs, array $id_data): void
370  {
371  if (!isset($a_attribs['action']) || $a_attribs['action'] == 'Attach') {
372  // if action not set, or attach
373  if (!array_key_exists($id_data['usr_id'], $this->course_members_array)) {
374  // add only if member is not assigned yet
375  $this->course_members->add($id_data['usr_id'], ilParticipants::IL_CRS_TUTOR);
376  if (isset($a_attribs['notification']) && $a_attribs['notification'] == 'Yes') {
377  $this->course_members->updateNotification($id_data['usr_id'], true);
378  }
379  if (isset($a_attribs['passed']) && $a_attribs['passed'] == 'Yes') {
380  $this->course_members->updatePassed($id_data['usr_id'], true);
381  }
382  if (isset($a_attribs['contact']) && $a_attribs['contact'] == 'Yes') {
383  // default for new course admin/tutors is "no contact"
384  $this->course_members->updateContact($id_data['usr_id'], true);
385  }
386  $this->course_members_array[$id_data['usr_id']] = "added";
387  } else {
388  if (isset($a_attribs['notification']) && $a_attribs['notification'] == 'Yes') {
389  $this->course_members->updateNotification($id_data['usr_id'], true);
390  }
391  if (isset($a_attribs['passed']) && $a_attribs['passed'] == 'Yes') {
392  $this->course_members->updatePassed($id_data['usr_id'], true);
393  }
394  if (isset($a_attribs['contact']) && $a_attribs['contact'] == 'Yes') {
395  $this->course_members->updateContact($id_data['usr_id'], true);
396  } elseif (isset($a_attribs['contact']) && $a_attribs['contact'] == 'No') {
397  $this->course_members->updateContact($id_data['usr_id'], false);
398  }
399  $this->course_members->updateBlocked($id_data['usr_id'], false);
400  }
401  } elseif (isset($a_attribs['action']) && $a_attribs['action'] == 'Detach' && $this->course_members->isTutor($id_data['usr_id'])) {
402  // if action set and detach and is tutor of course
403  $this->course_members->delete($id_data['usr_id']);
404  }
405  }
406 
410  private function handleMember(array $a_attribs, array $id_data): void
411  {
412  if (!isset($a_attribs['action']) || $a_attribs['action'] == 'Attach') {
413  // if action not set, or set and attach
414  if (!array_key_exists($id_data['usr_id'], $this->course_members_array)) {
415  // add only if member is not yet assigned as tutor or admin
416  $this->course_members->add($id_data['usr_id'], ilParticipants::IL_CRS_MEMBER);
417  if (isset($a_attribs['blocked']) && $a_attribs['blocked'] == 'Yes') {
418  $this->course_members->updateBlocked($id_data['usr_id'], true);
419  }
420  if (isset($a_attribs['passed']) && $a_attribs['passed'] == 'Yes') {
421  $this->course_members->updatePassed($id_data['usr_id'], true);
422  }
423  $this->course_members_array[$id_data['usr_id']] = "added";
424  } else {
425  // the member does exist. Now update status etc. only
426  if (isset($a_attribs['blocked']) && $a_attribs['blocked'] == 'Yes') {
427  $this->course_members->updateBlocked($id_data['usr_id'], true);
428  }
429  if (isset($a_attribs['passed']) && $a_attribs['passed'] == 'Yes') {
430  $this->course_members->updatePassed($id_data['usr_id'], true);
431  }
432  }
433  } elseif (isset($a_attribs['action']) && $a_attribs['action'] == 'Detach' && $this->course_members->isMember($id_data['usr_id'])) {
434  // if action set and detach and is member of course
435  $this->course_members->delete($id_data['usr_id']);
436  }
437  }
438 
442  private function handleSubscriber(array $a_attribs, array $id_data): void
443  {
444  if (!isset($a_attribs['action']) || $a_attribs['action'] == 'Attach') {
445  // if action not set, or attach
446  if (!$this->course_members->isSubscriber($id_data['usr_id'])) {
447  // add only if not exist
448  $this->course_members->addSubscriber($id_data['usr_id']);
449  }
450  $this->course_members->updateSubscriptionTime($id_data['usr_id'], (int) ($a_attribs['subscriptionTime'] ?? 0));
451  } elseif (isset($a_attribs['action']) && $a_attribs['action'] == 'Detach' && $this->course_members->isSubscriber($id_data['usr_id'])) {
452  // if action set and detach and is subscriber
453  $this->course_members->deleteSubscriber($id_data["usr_id"]);
454  }
455  }
456 
460  private function handleWaitingList(array $a_attribs, array $id_data): void
461  {
462  if (!isset($a_attribs['action']) || $a_attribs['action'] == 'Attach') {
463  // if action not set, or attach
464  if (!$this->course_waiting_list->isOnList($id_data['usr_id'])) {
465  // add only if not exists
466  $this->course_waiting_list->addToList($id_data['usr_id']);
467  }
468  $this->course_waiting_list->updateSubscriptionTime($id_data['usr_id'], (int) ($a_attribs['subscriptionTime'] ?? 0));
469  } elseif (isset($a_attribs['action']) && $a_attribs['action'] == 'Detach' && $this->course_waiting_list->isOnList($id_data['usr_id'])) {
470  // if action set and detach and is on list
471  $this->course_waiting_list->removeFromList($id_data['usr_id']);
472  }
473  }
474 
478  public function handlerEndTag($a_xml_parser, string $a_name): void
479  {
480  $this->cdata = $this->trimAndStrip($this->cdata);
481 
482  switch ($a_name) {
483  case 'Course':
484 
485  $this->log->write('CourseXMLParser: import_id = ' . $this->course_obj->getImportId());
486 
487  $this->course_obj->readContainerSettings();
488  // see #26169
489  $transl = $this->translations;
490  if ($transl->getDefaultTitle() !== "") {
491  $this->course_obj->setTitle($transl->getDefaultTitle());
492  }
493  if ($transl->getDefaultDescription() !== "") {
494  $this->course_obj->setDescription($transl->getDefaultDescription());
495  }
496  $this->course_obj->getObjectProperties()->storePropertyTranslations(
497  $this->translations
498  );
499  $this->course_obj->update();
500  break;
501 
502  case "Title":
503  $this->course_obj->setTitle(trim($this->cdata));
504  $this->translations = $this->translations->withDefaultTitle(trim($this->cdata));
505  break;
506 
507  case "Description":
508  $this->course_obj->setDescription(trim($this->cdata));
509  $this->translations = $this->translations->withDefaultDescription(trim($this->cdata));
510  break;
511 
512  case 'Settings':
513  break;
514 
515  case 'Availability':
516  $this->in_availability = false;
517  break;
518 
519  case 'Registration':
520  $this->in_registration = false;
521  break;
522 
523  case 'Start':
524  if ($this->in_availability) {
525  $this->course_obj->setActivationStart((int) trim($this->cdata));
526  }
527  if ($this->in_registration) {
528  $this->course_obj->setSubscriptionStart((int) trim($this->cdata));
529  }
530  if ($this->in_period) {
531  if ((int) $this->cdata) {
532  if ($this->in_period_with_time) {
533  $this->period_start = new \ilDateTime((int) $this->cdata, IL_CAL_UNIX);
534  } else {
535  $this->period_start = new \ilDate((int) $this->cdata, IL_CAL_UNIX);
536  }
537  }
538  }
539  break;
540 
541  case 'End':
542  if ($this->in_availability) {
543  $this->course_obj->setActivationEnd((int) trim($this->cdata));
544  }
545  if ($this->in_registration) {
546  $this->course_obj->setSubscriptionEnd((int) trim($this->cdata));
547  }
548  if ($this->in_period) {
549  if ((int) $this->cdata) {
550  if ($this->in_period_with_time) {
551  $this->period_end = new \ilDateTime((int) $this->cdata, IL_CAL_UNIX);
552  } else {
553  $this->period_end = new \ilDate((int) $this->cdata, IL_CAL_UNIX);
554  }
555  }
556  }
557  break;
558 
559  case 'Syllabus':
560  $this->course_obj->setSyllabus(trim($this->cdata));
561  break;
562 
563  case 'TargetGroup':
564  $this->course_obj->setTargetGroup(trim($this->cdata));
565  break;
566 
567  case 'ImportantInformation':
568  $this->course_obj->setImportantInformation(trim($this->cdata));
569  break;
570 
571  case 'ViewMode':
572  $this->course_obj->setViewMode((int) trim($this->cdata));
573  break;
574 
575  case 'Name':
576  $this->course_obj->setContactName(trim($this->cdata));
577  break;
578 
579  case 'Responsibility':
580  $this->course_obj->setContactResponsibility(trim($this->cdata));
581  break;
582 
583  case 'Phone':
584  $this->course_obj->setContactPhone(trim($this->cdata));
585  break;
586 
587  case 'Email':
588  $this->course_obj->setContactEmail(trim($this->cdata));
589  break;
590 
591  case 'Consultation':
592  $this->course_obj->setContactConsultation(trim($this->cdata));
593  break;
594 
595  case 'Password':
596  $this->course_obj->setSubscriptionPassword(trim($this->cdata));
597  break;
598 
599  case 'ContainerSetting':
600  if ($this->current_container_setting) {
602  $this->course_obj->getId(),
605  );
606  }
607  break;
608 
609  case 'Period':
610  $this->in_period = false;
611  try {
612  $this->course_obj->setCoursePeriod($this->period_start, $this->period_end);
613  } catch (Exception $e) {
614  $this->log->warning('invalid course period given');
615  }
616  break;
617 
618  case 'WaitingListAutoFill':
619  $this->course_obj->setWaitingListAutoFill((bool) $this->cdata);
620  break;
621 
622  case 'CancellationEnd':
623  if ((int) $this->cdata) {
624  $this->course_obj->setCancellationEnd(new ilDate((int) $this->cdata, IL_CAL_UNIX));
625  }
626  break;
627 
628  case 'MinMembers':
629  if ((int) $this->cdata) {
630  $this->course_obj->setSubscriptionMinMembers((int) $this->cdata);
631  }
632  break;
633 
634  case 'TimingMode':
635  $this->course_obj->setTimingMode((int) $this->cdata);
636  break;
637 
638  case 'StatusDetermination':
639  $this->course_obj->setStatusDetermination((int) $this->cdata);
640  break;
641 
642  case 'MailToMembersType':
643  $this->course_obj->setMailToMembersType((int) $this->cdata);
644  break;
645  }
646  $this->cdata = '';
647  }
648 
649  // PRIVATE
650 
651  public function handlerCharacterData($a_xml_parser, string $a_data): void
652  {
653  if ($a_data != "\n") {
654  // Replace multiple tabs with one space
655  $a_data = preg_replace("/\t+/", " ", $a_data);
656 
657  $this->cdata .= $a_data;
658  }
659  }
660 
661  protected function trimAndStripAttribs(array $attribs): array
662  {
663  $ret = [];
664  foreach ($attribs as $k => $v) {
665  $ret[$k] = $this->trimAndStrip((string) $v);
666  }
667  return $ret;
668  }
669 
670  protected function trimAndStrip(string $input): string
671  {
672  return ilUtil::stripSlashes(trim($input));
673  }
674 }
static _writeImportId(int $obj_id, string $import_id)
write import id to db (static)
handlerBeginTag($a_xml_parser, string $a_name, array $a_attribs)
handleWaitingList(array $a_attribs, array $id_data)
attach or detach members from waitinglist
handleAdmin(array $a_attribs, array $id_data)
attach or detach admin from course member
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
Class handles translation mode for an object.
ilCourseWaitingList $course_waiting_list
static _importContainerSortingSettings(array $attibs, int $obj_id)
sorting import for all container objects
const IL_CAL_UNIX
handleSubscriber(array $a_attribs, array $id_data)
attach or detach members from subscribers
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
static _getInstanceByObjId(int $a_obj_id)
ilSaxController $sax_controller
ilAdvancedMDValueParser $adv_md_handler
global $DIC
Definition: shib_login.php:26
handlerEndTag($a_xml_parser, string $a_name)
handleTutor(array $a_attribs, array $id_data)
static _writeContainerSetting(int $a_id, string $a_keyword, string $a_value)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _getImportedUserId(string $i2_id)
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
__construct(Container $dic, ilPlugin $plugin)
handleMember(array $a_attribs, array $id_data)
attach or detach user/member/admin from course member
trimAndStripAttribs(array $attribs)
ilCourseParticipants $course_members
__construct(ilObjCourse $a_course_obj, string $a_xml_file='')
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
handlerCharacterData($a_xml_parser, string $a_data)
Character data handler.
static _lookupLogin(int $a_user_id)