ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilObjCourse.php
Go to the documentation of this file.
1 <?php
2 
24 {
25  public const CAL_REG_START = 1;
26  public const CAL_REG_END = 2;
27  public const CAL_ACTIVATION_START = 3;
28  public const CAL_ACTIVATION_END = 4;
29  public const CAL_COURSE_START = 5;
30  public const CAL_COURSE_END = 6;
31  public const CAL_COURSE_TIMING_START = 7;
32  public const CAL_COURSE_TIMING_END = 8;
33 
34  public const STATUS_DETERMINATION_LP = 1;
35  public const STATUS_DETERMINATION_MANUAL = 2;
36 
37  private string $contact_consultation = '';
38  private string $contact_phone = '';
39  private string $contact_email = '';
40  private string $contact_name = '';
41  private string $contact_responsibility = '';
43  private int $subscription_start = 0;
44  private int $subscription_end = 0;
45  private int $subscription_type = 0;
46  private string $subscription_password = '';
47  private int $view_mode = 0;
48  private bool $waiting_list = false;
50  private int $subscription_max_members = 0;
51  private bool $abo = true;
52  private bool $show_members = true;
53  private string $message = '';
54  private bool $course_start_time_indication = true;
56  private string $important = '';
57  private string $syllabus = '';
59  private string $latitude = '';
60  private string $longitude = '';
61  private int $locationzoom = 0;
62  private bool $enablemap = false;
63 
64  private int $session_limit = 0;
65  private int $session_prev = -1;
66  private int $session_next = -1;
67 
68  private string $reg_access_code = '';
69  private bool $reg_access_code_enabled = false;
70  private int $status_dt = 0;
71 
73 
74  private bool $crs_start_time_indication = false;
75 
76  private ?ilDateTime $crs_start = null;
77  private ?ilDateTime $crs_end = null;
78  private ?ilDate $leave_end = null;
79  private int $min_members = 0;
80  private bool $auto_fill_from_waiting = false;
81  private bool $member_export = false;
83  private bool $auto_notification = true;
84  private ?string $target_group = null;
85  private int $activation_start = 0;
86  private int $activation_end = 0;
87  private bool $activation_visibility = false;
88 
91 
92  private array $local_roles = [];
93 
94  public function __construct(int $a_id = 0, bool $a_call_by_reference = true)
95  {
96  global $DIC;
97 
98  $this->setStatusDetermination(self::STATUS_DETERMINATION_LP);
99 
100  $this->type = "crs";
101  $this->course_logger = $DIC->logger()->crs();
102  parent::__construct($a_id, $a_call_by_reference);
103  }
104 
105  public static function lookupShowMembersEnabled(int $a_obj_id): bool
106  {
107  $query = 'SELECT show_members FROM crs_settings ' .
108  'WHERE obj_id = ' . $GLOBALS['DIC']['ilDB']->quote($a_obj_id, 'integer');
109  $res = $GLOBALS['DIC']['ilDB']->query($query);
110  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
111  return (bool) $row->show_members;
112  }
113  return false;
114  }
115 
116  public function getShowMembersExport(): bool
117  {
118  return $this->member_export;
119  }
120 
121  public function setShowMembersExport(bool $a_mem_export): void
122  {
123  $this->member_export = $a_mem_export;
124  }
125 
126  public function getRegistrationAccessCode(): string
127  {
128  return $this->reg_access_code;
129  }
130 
131  public function setRegistrationAccessCode(string $a_code): void
132  {
133  $this->reg_access_code = $a_code;
134  }
135 
136  public function isRegistrationAccessCodeEnabled(): bool
137  {
139  }
140 
141  public function enableRegistrationAccessCode(bool $a_status): void
142  {
143  $this->reg_access_code_enabled = $a_status;
144  }
145 
146  public function getImportantInformation(): string
147  {
148  return $this->important;
149  }
150 
151  public function setImportantInformation(string $a_info): void
152  {
153  $this->important = $a_info;
154  }
155 
156  public function getSyllabus(): string
157  {
158  return $this->syllabus;
159  }
160 
161  public function setSyllabus(string $a_syllabus): void
162  {
163  $this->syllabus = $a_syllabus;
164  }
165 
166  public function getTargetGroup(): ?string
167  {
168  return $this->target_group;
169  }
170 
171  public function setTargetGroup(?string $a_tg): void
172  {
173  $this->target_group = $a_tg;
174  }
175 
176  public function getContactName(): string
177  {
178  return $this->contact_name;
179  }
180 
181  public function setContactName(string $a_cn): void
182  {
183  $this->contact_name = $a_cn;
184  }
185 
186  public function getContactConsultation(): string
187  {
189  }
190 
191  public function setContactConsultation(string $a_value): void
192  {
193  $this->contact_consultation = $a_value;
194  }
195 
196  public function getContactPhone(): string
197  {
198  return $this->contact_phone;
199  }
200 
201  public function setContactPhone(string $a_value): void
202  {
203  $this->contact_phone = $a_value;
204  }
205 
206  public function getContactEmail(): string
207  {
208  return $this->contact_email;
209  }
210 
211  public function setContactEmail(string $a_value): void
212  {
213  $this->contact_email = $a_value;
214  }
215 
216  public function getContactResponsibility(): string
217  {
219  }
220 
221  public function setContactResponsibility(string $a_value): void
222  {
223  $this->contact_responsibility = $a_value;
224  }
225 
226  public function getActivationUnlimitedStatus(): bool
227  {
228  return !$this->getActivationStart() || !$this->getActivationEnd();
229  }
230 
231  public function getActivationStart(): int
232  {
234  }
235 
236  public function setActivationStart(int $a_value): void
237  {
238  $this->activation_start = $a_value;
239  }
240 
241  public function getActivationEnd(): int
242  {
243  return $this->activation_end;
244  }
245 
246  public function setActivationEnd(int $a_value): void
247  {
248  $this->activation_end = $a_value;
249  }
250 
251  public function setActivationVisibility(bool $a_value): void
252  {
253  $this->activation_visibility = $a_value;
254  }
255 
256  public function getActivationVisibility(): bool
257  {
259  }
260 
262  {
264  }
265 
266  public function setSubscriptionLimitationType(int $a_type): void
267  {
268  $this->subscription_limitation_type = $a_type;
269  }
270 
271  public function getSubscriptionUnlimitedStatus(): bool
272  {
273  return $this->subscription_limitation_type == ilCourseConstants::IL_CRS_SUBSCRIPTION_UNLIMITED;
274  }
275 
276  public function getSubscriptionStart(): int
277  {
279  }
280 
281  public function setSubscriptionStart(int $a_value): void
282  {
283  $this->subscription_start = $a_value;
284  }
285 
286  public function getSubscriptionEnd(): int
287  {
289  }
290 
291  public function setSubscriptionEnd(int $a_value): void
292  {
293  $this->subscription_end = $a_value;
294  }
295 
296  public function getSubscriptionType(): int
297  {
298  return $this->subscription_type ?: ilCourseConstants::IL_CRS_SUBSCRIPTION_DIRECT;
299  }
300 
301  public function setSubscriptionType(int $a_value): void
302  {
303  $this->subscription_type = $a_value;
304  }
305 
306  public function getSubscriptionPassword(): string
307  {
309  }
310 
311  public function setSubscriptionPassword(string $a_value): void
312  {
313  $this->subscription_password = $a_value;
314  }
315 
316  public function enabledObjectiveView(): bool
317  {
318  return $this->view_mode == ilCourseConstants::IL_CRS_VIEW_OBJECTIVE;
319  }
320 
321  public function enabledWaitingList(): bool
322  {
323  return $this->waiting_list;
324  }
325 
326  public function enableWaitingList(bool $a_status): void
327  {
328  $this->waiting_list = $a_status;
329  }
330 
331  public function inSubscriptionTime(): bool
332  {
333  if ($this->getSubscriptionUnlimitedStatus()) {
334  return true;
335  }
336  if (time() > $this->getSubscriptionStart() and time() < $this->getSubscriptionEnd()) {
337  return true;
338  }
339  return false;
340  }
341 
342  public function enableSessionLimit(int $a_status): void
343  {
344  $this->session_limit = $a_status;
345  }
346 
347  public function isSessionLimitEnabled(): bool
348  {
349  return (bool) $this->session_limit;
350  }
351 
352  public function enableSubscriptionMembershipLimitation(bool $a_status): void
353  {
354  $this->subscription_membership_limitation = $a_status;
355  }
356 
357  public function setNumberOfPreviousSessions(int $a_num): void
358  {
359  $this->session_prev = $a_num;
360  }
361 
362  public function getNumberOfPreviousSessions(): int
363  {
364  return $this->session_prev;
365  }
366 
367  public function setNumberOfNextSessions(int $a_num): void
368  {
369  $this->session_next = $a_num;
370  }
371 
372  public function getNumberOfNextSessions(): int
373  {
374  return $this->session_next;
375  }
376 
377  public function isSubscriptionMembershipLimited(): bool
378  {
380  }
381 
382  public function getSubscriptionMaxMembers(): int
383  {
385  }
386 
387  public function setSubscriptionMaxMembers(int $a_value): void
388  {
389  $this->subscription_max_members = $a_value;
390  }
391 
392  public static function _isSubscriptionNotificationEnabled(int $a_course_id): bool
393  {
394  global $DIC;
395 
396  $ilDB = $DIC->database();
397  $query = "SELECT * FROM crs_settings " .
398  "WHERE obj_id = " . $ilDB->quote($a_course_id, 'integer') . " " .
399  "AND sub_notify = 1";
400  $res = $ilDB->query($query);
401  return (bool) $res->numRows();
402  }
403 
404  public function getSubscriptionNotify(): bool
405  {
406  return true;
407  }
408 
409  public function setViewMode(int $a_mode): void
410  {
411  $this->view_mode = $a_mode;
412  }
413 
414  public function getViewMode(): int
415  {
416  return $this->view_mode;
417  }
418 
419  public static function lookupTimingMode(int $a_obj_id): int
420  {
421  global $DIC;
422 
423  $ilDB = $DIC['ilDB'];
424 
425  $query = 'SELECT timing_mode FROM crs_settings ' .
426  'WHERE obj_id = ' . $ilDB->quote($a_obj_id, 'integer');
427  $res = $ilDB->query($query);
428 
429  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
430  return (int) $row->timing_mode;
431  }
433  }
434 
435  public function setTimingMode(int $a_mode): void
436  {
437  $this->timing_mode = $a_mode;
438  }
439 
440  public function getTimingMode(): int
441  {
442  return $this->timing_mode;
443  }
444 
445  public static function _lookupViewMode(int $a_id): int
446  {
447  global $DIC;
448 
449  $ilDB = $DIC['ilDB'];
450 
451  $query = "SELECT view_mode FROM crs_settings WHERE obj_id = " . $ilDB->quote($a_id, 'integer') . " ";
452  $res = $ilDB->query($query);
453  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
454  return $row->view_mode;
455  }
456  return false;
457  }
458 
459  public static function _lookupAboStatus(int $a_id): bool
460  {
461  global $DIC;
462 
463  $ilDB = $DIC['ilDB'];
464 
465  $query = "SELECT abo FROM crs_settings WHERE obj_id = " . $ilDB->quote($a_id, 'integer') . " ";
466  $res = $ilDB->query($query);
467  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
468  return $row->abo;
469  }
470  return false;
471  }
472 
473  public function setAboStatus(bool $a_status): void
474  {
475  $this->abo = $a_status;
476  }
477 
478  public function getAboStatus(): bool
479  {
480  return $this->abo;
481  }
482 
483  public function setShowMembers(bool $a_status): void
484  {
485  $this->show_members = $a_status;
486  }
487 
488  public function getShowMembers(): bool
489  {
490  return $this->show_members;
491  }
492 
493  public function setMailToMembersType(int $a_type): void
494  {
495  $this->mail_members = $a_type;
496  }
497 
498  public function getMailToMembersType(): int
499  {
500  return $this->mail_members;
501  }
502 
503  public function getMessage(): string
504  {
505  return $this->message;
506  }
507 
508  public function setMessage(string $a_message): void
509  {
510  $this->message = $a_message;
511  }
512 
513  public function appendMessage(string $a_message): void
514  {
515  if ($this->getMessage()) {
516  $this->message .= "<br /> ";
517  }
518  $this->message .= $a_message;
519  }
520 
521  public function isActivated(): bool
522  {
523  if ($this->getOfflineStatus()) {
524  return false;
525  }
526  if ($this->getActivationUnlimitedStatus()) {
527  return true;
528  }
529  if (time() < $this->getActivationStart() or
530  time() > $this->getActivationEnd()) {
531  return false;
532  }
533  return true;
534  }
535 
539  public static function _isActivated(int $a_obj_id): bool
540  {
541  return ilObjCourseAccess::_isActivated($a_obj_id);
542  }
543 
547  public static function _registrationEnabled(int $a_obj_id): bool
548  {
549  return ilObjCourseAccess::_registrationEnabled($a_obj_id);
550  }
551 
552  public function read(): void
553  {
554  parent::read();
556  $this->__readSettings();
557  }
558 
559  public function create($a_upload = false): int
560  {
561  global $DIC;
562 
563  $ilAppEventHandler = $DIC['ilAppEventHandler'];
564 
565  $id = parent::create($a_upload);
566 
567  if (!$a_upload) {
568  $this->createMetaData();
569  }
570  $this->__createDefaultSettings();
571  $this->app_event_handler->raise(
572  'Modules/Course',
573  'create',
574  array('object' => $this,
575  'obj_id' => $this->getId(),
576  'appointments' => $this->prepareAppointments('create')
577  )
578  );
579 
580  return $id;
581  }
582 
583  public function setLatitude(string $a_latitude): void
584  {
585  $this->latitude = $a_latitude;
586  }
587 
588  public function getLatitude(): string
589  {
590  return $this->latitude;
591  }
592 
593  public function setLongitude(string $a_longitude): void
594  {
595  $this->longitude = $a_longitude;
596  }
597 
598  public function getLongitude(): string
599  {
600  return $this->longitude;
601  }
602 
603  public function setLocationZoom(int $a_locationzoom): void
604  {
605  $this->locationzoom = $a_locationzoom;
606  }
607 
608  public function getLocationZoom(): int
609  {
610  return $this->locationzoom;
611  }
612 
613  public function setEnableCourseMap(bool $a_enablemap): void
614  {
615  $this->enablemap = $a_enablemap;
616  }
617 
618  public function getEnableMap(): bool
619  {
620  return $this->getEnableCourseMap();
621  }
622 
623  public function getEnableCourseMap(): bool
624  {
625  return $this->enablemap;
626  }
627 
628  public function setCoursePeriod(?ilDateTime $start = null, ?ilDateTime $end = null): void
629  {
630  if (
631  ($start instanceof \ilDate && !$end instanceof ilDate) ||
632  ($end instanceof \ilDate && !$start instanceof ilDate)
633  ) {
634  throw new InvalidArgumentException('Different date types not supported.');
635  }
636 
637  if ($start instanceof \ilDate) {
638  $this->toggleCourseStartTimeIndication(false);
639  } else {
640  $this->toggleCourseStartTimeIndication(true);
641  }
642  $this->setCourseStart($start);
643  $this->setCourseEnd($end);
644  }
645 
646  protected function toggleCourseStartTimeIndication(bool $time_indication): void
647  {
648  $this->course_start_time_indication = $time_indication;
649  }
650 
651  public function getCourseStartTimeIndication(): bool
652  {
654  }
655 
656  protected function setCourseStart(?ilDateTime $a_value = null): void
657  {
658  $this->crs_start = $a_value;
659  }
660 
661  public function getCourseStart(): ?ilDateTime
662  {
663  return $this->crs_start;
664  }
665 
666  protected function setCourseEnd(?ilDateTime $a_value = null): void
667  {
668  $this->crs_end = $a_value;
669  }
670 
671  public function getCourseEnd(): ?ilDateTime
672  {
673  return $this->crs_end;
674  }
675 
676  public function setCancellationEnd(?ilDate $a_value = null): void
677  {
678  $this->leave_end = $a_value;
679  }
680 
681  public function getCancellationEnd(): ?ilDate
682  {
683  return $this->leave_end;
684  }
685 
686  public function setSubscriptionMinMembers(int $a_value): void
687  {
688  if ($a_value !== null) {
689  $a_value = $a_value;
690  }
691  $this->min_members = $a_value;
692  }
693 
694  public function getSubscriptionMinMembers(): int
695  {
696  return $this->min_members;
697  }
698 
699  public function setWaitingListAutoFill(bool $a_value): void
700  {
701  $this->auto_fill_from_waiting = $a_value;
702  }
703 
704  public function hasWaitingListAutoFill(): bool
705  {
707  }
708 
717  public function cloneObject(int $a_target_id, int $a_copy_id = 0, bool $a_omit_tree = false): ?ilObject
718  {
719  global $DIC;
720 
721  $new_obj = parent::cloneObject($a_target_id, $a_copy_id, $a_omit_tree);
722 
723  $this->cloneAutoGeneratedRoles($new_obj);
724  $this->cloneMetaData($new_obj);
725 
726  $new_obj->getMemberObject()->add($this->user->getId(), ilParticipants::IL_CRS_ADMIN);
727  $new_obj->getMemberObject()->updateContact($this->user->getId(), 1);
728 
729  $cwo = ilCopyWizardOptions::_getInstance($a_copy_id);
730  if ($cwo->isRootNode($this->getRefId())) {
731  $this->setOfflineStatus(true);
732  }
733 
734  $this->cloneSettings($new_obj);
735  ilCourseDefinedFieldDefinition::_clone($this->getId(), $new_obj->getId());
736  ilCourseFile::_cloneFiles($this->getId(), $new_obj->getId());
737  $obj_settings = new ilLPObjSettings($this->getId());
738  $obj_settings->cloneSettings($new_obj->getId());
739  unset($obj_settings);
740  $pathFactory = new ilCertificatePathFactory();
741  $templateRepository = new ilCertificateTemplateDatabaseRepository($this->db);
742 
743  $cloneAction = new ilCertificateCloneAction(
744  $this->db,
745  $pathFactory,
746  $templateRepository,
748  $DIC->filesystem()->web(),
750  );
751  $cloneAction->cloneCertificate($this, $new_obj);
752 
753  $book_service = new ilBookingService();
754  $book_service->cloneSettings($this->getId(), $new_obj->getId());
755 
756  $badges = ilBadge::getInstancesByParentId($this->getId());
757  foreach ($badges as $badge) {
758  $badge->clone($new_obj->getId());
759  }
760 
761  return $new_obj;
762  }
763 
767  public function cloneDependencies(int $a_target_id, int $a_copy_id): bool
768  {
769  parent::cloneDependencies($a_target_id, $a_copy_id);
770 
771  // Clone course start objects
772  $start = new ilContainerStartObjects($this->getRefId(), $this->getId());
773  $start->cloneDependencies($a_target_id, $a_copy_id);
774 
775  // Clone course item settings
776  ilObjectActivation::cloneDependencies($this->getRefId(), $a_target_id, $a_copy_id);
777 
778  // clone objective settings
779  ilLOSettings::cloneSettings($a_copy_id, $this->getId(), ilObject::_lookupObjId($a_target_id));
780 
781  // Clone course learning objectives
782  $crs_objective = new ilCourseObjective($this);
783  $crs_objective->ilClone($a_target_id, $a_copy_id);
784 
785  // clone membership limitation
786  foreach (\ilObjCourseGrouping::_getGroupings($this->getId()) as $grouping_id) {
787  $this->course_logger->info('Handling grouping id: ' . $grouping_id);
788  $grouping = new \ilObjCourseGrouping($grouping_id);
789  $grouping->cloneGrouping($a_target_id, $a_copy_id);
790  }
791  return true;
792  }
793 
797  public function cloneAutoGeneratedRoles(ilObject $new_obj): void
798  {
799  $admin = $this->getDefaultAdminRole();
800  $new_admin = $new_obj->getDefaultAdminRole();
801 
802  if (!$admin || !$new_admin || !$this->getRefId() || !$new_obj->getRefId()) {
803  $this->course_logger->debug('Error cloning auto generated role: il_crs_admin');
804  }
805  $this->rbac_admin->copyRolePermissions($admin, $this->getRefId(), $new_obj->getRefId(), $new_admin, true);
806  $this->course_logger->debug('Finished copying of role crs_admin.');
807 
808  $tutor = $this->getDefaultTutorRole();
809  $new_tutor = $new_obj->getDefaultTutorRole();
810  if (!$tutor || !$new_tutor) {
811  $this->course_logger->info('Error cloning auto generated role: il_crs_tutor');
812  }
813  $this->rbac_admin->copyRolePermissions($tutor, $this->getRefId(), $new_obj->getRefId(), $new_tutor, true);
814  $this->course_logger->info('Finished copying of role crs_tutor.');
815 
816  $member = $this->getDefaultMemberRole();
817  $new_member = $new_obj->getDefaultMemberRole();
818  if (!$member || !$new_member) {
819  $this->course_logger->debug('Error cloning auto generated role: il_crs_member');
820  }
821  $this->rbac_admin->copyRolePermissions($member, $this->getRefId(), $new_obj->getRefId(), $new_member, true);
822  $this->course_logger->debug('Finished copying of role crs_member.');
823  }
824 
825  public function validate(): bool
826  {
827  $this->setMessage('');
828 
830  $this->getSubscriptionStart() > $this->getSubscriptionEnd()) {
831  $this->appendMessage($this->lng->txt("subscription_times_not_valid"));
832  }
834  $this->appendMessage($this->lng->txt("crs_password_required"));
835  }
836  if ($this->isSubscriptionMembershipLimited()) {
837  if ($this->getSubscriptionMinMembers() <= 0 && $this->getSubscriptionMaxMembers() <= 0) {
838  $this->appendMessage($this->lng->txt("crs_max_and_min_members_needed"));
839  }
840  if ($this->getSubscriptionMaxMembers() <= 0 && $this->enabledWaitingList()) {
841  $this->appendMessage($this->lng->txt("crs_max_members_needed"));
842  }
843  if ($this->getSubscriptionMaxMembers() > 0 && $this->getSubscriptionMinMembers() > $this->getSubscriptionMaxMembers()) {
844  $this->appendMessage($this->lng->txt("crs_max_and_min_members_invalid"));
845  }
846  }
847  if (!$this->getTitle() || !$this->getStatusDetermination()) {
848  $this->appendMessage($this->lng->txt('err_check_input'));
849  }
850  if (($this->getCourseStart() && !$this->getCourseEnd()) ||
851  (!$this->getCourseStart() && $this->getCourseEnd()) ||
852  ($this->getCourseStart() && $this->getCourseEnd() && $this->getCourseStart()->get(IL_CAL_UNIX) > $this->getCourseEnd()->get(IL_CAL_UNIX))) {
853  $this->appendMessage($this->lng->txt("crs_course_period_not_valid"));
854  }
855 
856  return strlen($this->getMessage()) > 0;
857  }
858 
859  public function validateInfoSettings(): bool
860  {
861  $error = false;
862  if ($this->getContactEmail()) {
863  $emails = explode(",", $this->getContactEmail());
864 
865  foreach ($emails as $email) {
866  $email = trim($email);
867  if (!ilUtil::is_email($email) && !ilObjUser::getUserIdByLogin($email)) {
868  $this->error->appendMessage($this->lng->txt('contact_email_not_valid') . " '" . $email . "'");
869  $error = true;
870  }
871  }
872  }
873  return !$error;
874  }
875 
876  public function hasContactData(): bool
877  {
878  return strlen($this->getContactName()) || strlen($this->getContactResponsibility()) || strlen($this->getContactEmail()) || strlen($this->getContactPhone()) || strlen($this->getContactConsultation());
879  }
880 
887  public function delete(): bool
888  {
889  // always call parent delete function first!!
890  if (!parent::delete()) {
891  return false;
892  }
893 
894  // delete meta data
895  $this->deleteMetaData();
896 
897  // put here course specific stuff
898 
899  $this->__deleteSettings();
900 
902 
904 
906 
908 
910 
911  $this->app_event_handler->raise(
912  'Modules/Course',
913  'delete',
914  array('object' => $this,
915  'obj_id' => $this->getId(),
916  'appointments' => $this->prepareAppointments('delete')
917  )
918  );
919  return true;
920  }
921 
925  public function update(): bool
926  {
927  $sorting = new ilContainerSortingSettings($this->getId());
928  $sorting->setSortMode($this->getOrderType());
929  $sorting->update();
930 
931  $this->updateMetaData();
932  $this->updateSettings();
933  parent::update();
934 
935  $this->app_event_handler->raise(
936  'Modules/Course',
937  'update',
938  array('object' => $this,
939  'obj_id' => $this->getId(),
940  'appointments' => $this->prepareAppointments('update')
941  )
942  );
943  return true;
944  }
945 
948  public function updateSettings(): void
949  {
950  $query = "SELECT * FROM crs_settings WHERE obj_id = " . $this->db->quote($this->getId(), 'integer') . " ";
951  $res = $this->db->query($query);
952 
953  if (!$res->numRows()) {
954  $this->__createDefaultSettings();
955  }
956 
957  $query = "UPDATE crs_settings SET " .
958  "syllabus = " . $this->db->quote($this->getSyllabus(), 'text') . ", " .
959  "contact_name = " . $this->db->quote($this->getContactName(), 'text') . ", " .
960  "contact_responsibility = " . $this->db->quote($this->getContactResponsibility(), 'text') . ", " .
961  "contact_phone = " . $this->db->quote($this->getContactPhone(), 'text') . ", " .
962  "contact_email = " . $this->db->quote($this->getContactEmail(), 'text') . ", " .
963  "contact_consultation = " . $this->db->quote($this->getContactConsultation(), 'text') . ", " .
964  "activation_type = " . $this->db->quote(!$this->getOfflineStatus(), 'integer') . ", " .
965  "sub_limitation_type = " . $this->db->quote($this->getSubscriptionLimitationType(), 'integer') . ", " .
966  "sub_start = " . $this->db->quote($this->getSubscriptionStart(), 'integer') . ", " .
967  "sub_end = " . $this->db->quote($this->getSubscriptionEnd(), 'integer') . ", " .
968  "sub_type = " . $this->db->quote($this->getSubscriptionType(), 'integer') . ", " .
969  "sub_password = " . $this->db->quote($this->getSubscriptionPassword(), 'text') . ", " .
970  "sub_mem_limit = " . $this->db->quote((int) $this->isSubscriptionMembershipLimited(), 'integer') . ", " .
971  "sub_max_members = " . $this->db->quote($this->getSubscriptionMaxMembers(), 'integer') . ", " .
972  "sub_notify = " . $this->db->quote($this->getSubscriptionNotify(), 'integer') . ", " .
973  "view_mode = " . $this->db->quote($this->getViewMode(), 'integer') . ", " .
974  'timing_mode = ' . $this->db->quote($this->getTimingMode(), 'integer') . ', ' .
975  "abo = " . $this->db->quote($this->getAboStatus(), 'integer') . ", " .
976  "waiting_list = " . $this->db->quote($this->enabledWaitingList(), 'integer') . ", " .
977  "important = " . $this->db->quote($this->getImportantInformation(), 'text') . ", " .
978  'target_group = ' . $this->db->quote($this->getTargetGroup(), \ilDBConstants::T_TEXT) . ', ' .
979  "show_members = " . $this->db->quote($this->getShowMembers(), 'integer') . ", " .
980  "show_members_export = " . $this->db->quote($this->getShowMembersExport(), 'integer') . ", " .
981  "latitude = " . $this->db->quote($this->getLatitude(), 'text') . ", " .
982  "longitude = " . $this->db->quote($this->getLongitude(), 'text') . ", " .
983  "location_zoom = " . $this->db->quote($this->getLocationZoom(), 'integer') . ", " .
984  "enable_course_map = " . $this->db->quote((int) $this->getEnableCourseMap(), 'integer') . ", " .
985  'session_limit = ' . $this->db->quote($this->isSessionLimitEnabled(), 'integer') . ', ' .
986  'session_prev = ' . $this->db->quote($this->getNumberOfPreviousSessions(), 'integer') . ', ' .
987  'session_next = ' . $this->db->quote($this->getNumberOfNextSessions(), 'integer') . ', ' .
988  'reg_ac_enabled = ' . $this->db->quote($this->isRegistrationAccessCodeEnabled(), 'integer') . ', ' .
989  'reg_ac = ' . $this->db->quote($this->getRegistrationAccessCode(), 'text') . ', ' .
990  'auto_notification = ' . $this->db->quote((int) $this->getAutoNotification(), 'integer') . ', ' .
991  'status_dt = ' . $this->db->quote($this->getStatusDetermination(), ilDBConstants::T_INTEGER) . ', ' .
992  'mail_members_type = ' . $this->db->quote($this->getMailToMembersType(), 'integer') . ', ' .
993  'period_start = ' . $this->db->quote(
996  ) . ', ' .
997  'period_end = ' . $this->db->quote(
1000  ) . ', ' .
1001  'period_time_indication = ' . $this->db->quote(
1002  $this->getCourseStartTimeIndication() ? 1 : 0,
1004  ) . ', ' .
1005  'auto_wait = ' . $this->db->quote((int) $this->hasWaitingListAutoFill(), 'integer') . ', ' .
1006  'leave_end = ' . $this->db->quote(
1007  ($this->getCancellationEnd() && !$this->getCancellationEnd()->isNull()) ? $this->getCancellationEnd()->get(IL_CAL_UNIX) : null,
1008  'integer'
1009  ) . ', ' .
1010  'min_members = ' . $this->db->quote($this->getSubscriptionMinMembers(), 'integer') . ' ' .
1011  "WHERE obj_id = " . $this->db->quote($this->getId(), 'integer') . "";
1012 
1013  $res = $this->db->manipulate($query);
1014 
1015  // moved activation to ilObjectActivation
1016  if ($this->ref_id ?? false) {
1017  ilObjectActivation::getItem($this->ref_id);
1018 
1019  $item = new ilObjectActivation();
1020  if (!$this->getActivationStart() || !$this->getActivationEnd()) {
1021  $item->setTimingType(ilObjectActivation::TIMINGS_DEACTIVATED);
1022  } else {
1023  $item->setTimingType(ilObjectActivation::TIMINGS_ACTIVATION);
1024  $item->setTimingStart($this->getActivationStart());
1025  $item->setTimingEnd($this->getActivationEnd());
1026  $item->toggleVisible($this->getActivationVisibility());
1027  }
1028  $item->update($this->ref_id);
1029  }
1030  }
1031 
1032  public function cloneSettings(ilObject $new_obj): void
1033  {
1034  $new_obj->setSyllabus($this->getSyllabus());
1035  $new_obj->setContactName($this->getContactName());
1036  $new_obj->setContactResponsibility($this->getContactResponsibility());
1037  $new_obj->setContactPhone($this->getContactPhone());
1038  $new_obj->setContactEmail($this->getContactEmail());
1039  $new_obj->setContactConsultation($this->getContactConsultation());
1040  $new_obj->setOfflineStatus($this->getOfflineStatus()); // #9914
1041  $new_obj->setActivationStart($this->getActivationStart());
1042  $new_obj->setActivationEnd($this->getActivationEnd());
1043  $new_obj->setActivationVisibility($this->getActivationVisibility());
1044  $new_obj->setSubscriptionLimitationType($this->getSubscriptionLimitationType());
1045  $new_obj->setSubscriptionStart($this->getSubscriptionStart());
1046  $new_obj->setSubscriptionEnd($this->getSubscriptionEnd());
1047  $new_obj->setSubscriptionType($this->getSubscriptionType());
1048  $new_obj->setSubscriptionPassword($this->getSubscriptionPassword());
1049  $new_obj->enableSubscriptionMembershipLimitation($this->isSubscriptionMembershipLimited());
1050  $new_obj->setSubscriptionMaxMembers($this->getSubscriptionMaxMembers());
1051  $new_obj->setViewMode($this->getViewMode());
1052  $new_obj->setTimingMode($this->getTimingMode());
1053  $new_obj->setOrderType($this->getOrderType());
1054  $new_obj->setAboStatus($this->getAboStatus());
1055  $new_obj->enableWaitingList($this->enabledWaitingList());
1056  $new_obj->setImportantInformation($this->getImportantInformation());
1057  $new_obj->setTargetGroup($this->getTargetGroup());
1058  $new_obj->setShowMembers($this->getShowMembers());
1059  // patch mem_exp
1060  $new_obj->setShowMembersExport($this->getShowMembersExport());
1061  // patch mem_exp
1062  $new_obj->enableSessionLimit($this->isSessionLimitEnabled());
1063  $new_obj->setNumberOfPreviousSessions($this->getNumberOfPreviousSessions());
1064  $new_obj->setNumberOfNextSessions($this->getNumberOfNextSessions());
1065  $new_obj->setAutoNotification($this->getAutoNotification());
1066  $new_obj->enableRegistrationAccessCode($this->isRegistrationAccessCodeEnabled());
1067  $new_obj->setRegistrationAccessCode(ilMembershipRegistrationCodeUtils::generateCode());
1068  $new_obj->setStatusDetermination($this->getStatusDetermination());
1069  $new_obj->setMailToMembersType($this->getMailToMembersType());
1070  $new_obj->setCoursePeriod(
1071  $this->getCourseStart(),
1072  $this->getCourseEnd()
1073  );
1074  $new_obj->setCancellationEnd($this->getCancellationEnd());
1075  $new_obj->setWaitingListAutoFill($this->hasWaitingListAutoFill());
1076  $new_obj->setSubscriptionMinMembers($this->getSubscriptionMinMembers());
1077 
1078  // #10271
1079  $new_obj->setEnableCourseMap($this->getEnableCourseMap());
1080  $new_obj->setLatitude($this->getLatitude());
1081  $new_obj->setLongitude($this->getLongitude());
1082  $new_obj->setLocationZoom($this->getLocationZoom());
1083 
1084  $new_obj->update();
1085  }
1086 
1087  public function __createDefaultSettings(): void
1088  {
1090 
1091  $query = "INSERT INTO crs_settings (obj_id,syllabus,contact_name,contact_responsibility," .
1092  "contact_phone,contact_email,contact_consultation," .
1093  "sub_limitation_type,sub_start,sub_end,sub_type,sub_password,sub_mem_limit," .
1094  "sub_max_members,sub_notify,view_mode,timing_mode,abo," .
1095  "latitude,longitude,location_zoom,enable_course_map,waiting_list,show_members,show_members_export, " .
1096  "session_limit,session_prev,session_next, reg_ac_enabled, reg_ac, auto_notification, status_dt,mail_members_type) " .
1097  "VALUES( " .
1098  $this->db->quote($this->getId(), 'integer') . ", " .
1099  $this->db->quote($this->getSyllabus(), 'text') . ", " .
1100  $this->db->quote($this->getContactName(), 'text') . ", " .
1101  $this->db->quote($this->getContactResponsibility(), 'text') . ", " .
1102  $this->db->quote($this->getContactPhone(), 'text') . ", " .
1103  $this->db->quote($this->getContactEmail(), 'text') . ", " .
1104  $this->db->quote($this->getContactConsultation(), 'text') . ", " .
1105  $this->db->quote(ilCourseConstants::IL_CRS_SUBSCRIPTION_DEACTIVATED, 'integer') . ", " .
1106  $this->db->quote($this->getSubscriptionStart(), 'integer') . ", " .
1107  $this->db->quote($this->getSubscriptionEnd(), 'integer') . ", " .
1108  $this->db->quote(ilCourseConstants::IL_CRS_SUBSCRIPTION_DIRECT, 'integer') . ", " .
1109  $this->db->quote($this->getSubscriptionPassword(), 'text') . ", " .
1110  "0, " .
1111  $this->db->quote($this->getSubscriptionMaxMembers(), 'integer') . ", " .
1112  "1, " .
1113  "0, " .
1114  $this->db->quote(ilCourseConstants::IL_CRS_VIEW_TIMING_ABSOLUTE, 'integer') . ', ' .
1115  $this->db->quote($this->getAboStatus(), 'integer') . ", " .
1116  $this->db->quote($this->getLatitude(), 'text') . ", " .
1117  $this->db->quote($this->getLongitude(), 'text') . ", " .
1118  $this->db->quote($this->getLocationZoom(), 'integer') . ", " .
1119  $this->db->quote($this->getEnableCourseMap(), 'integer') . ", " .
1120  #"objective_view = '0', ".
1121  "1, " .
1122  "1," .
1123  '0,' .
1124  $this->db->quote($this->isSessionLimitEnabled(), 'integer') . ', ' .
1125  $this->db->quote($this->getNumberOfPreviousSessions(), 'integer') . ', ' .
1126  $this->db->quote($this->getNumberOfPreviousSessions(), 'integer') . ', ' .
1127  $this->db->quote($this->isRegistrationAccessCodeEnabled(), 'integer') . ', ' .
1128  $this->db->quote($this->getRegistrationAccessCode(), 'text') . ', ' .
1129  $this->db->quote((int) $this->getAutoNotification(), 'integer') . ', ' .
1130  $this->db->quote($this->getStatusDetermination(), 'integer') . ', ' .
1131  $this->db->quote($this->getMailToMembersType(), 'integer') . ' ' .
1132  ")";
1133 
1134  $res = $this->db->manipulate($query);
1135  $this->__readSettings();
1136 
1137  $sorting = new ilContainerSortingSettings($this->getId());
1138  $sorting->setSortMode(ilContainer::SORT_MANUAL);
1139  $sorting->update();
1140  }
1141 
1142  public function __readSettings(): void
1143  {
1144  $query = "SELECT * FROM crs_settings WHERE obj_id = " . $this->db->quote($this->getId(), 'integer');
1145  $res = $this->db->query($query);
1146  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
1147  $this->setSyllabus((string) $row->syllabus);
1148  $this->setTargetGroup($row->target_group);
1149  $this->setContactName((string) $row->contact_name);
1150  $this->setContactResponsibility((string) $row->contact_responsibility);
1151  $this->setContactPhone((string) $row->contact_phone);
1152  $this->setContactEmail((string) $row->contact_email);
1153  $this->setContactConsultation((string) $row->contact_consultation);
1154  $this->setSubscriptionLimitationType((int) $row->sub_limitation_type);
1155  $this->setSubscriptionStart((int) $row->sub_start);
1156  $this->setSubscriptionEnd((int) $row->sub_end);
1157  $this->setSubscriptionType((int) $row->sub_type);
1158  $this->setSubscriptionPassword((string) $row->sub_password);
1159  $this->enableSubscriptionMembershipLimitation((bool) $row->sub_mem_limit);
1160  $this->setSubscriptionMaxMembers((int) $row->sub_max_members);
1161  $this->setViewMode((int) $row->view_mode);
1162  $this->setTimingMode((int) $row->timing_mode);
1163  $this->setAboStatus((bool) $row->abo);
1164  $this->enableWaitingList((bool) $row->waiting_list);
1165  $this->setImportantInformation((string) $row->important);
1166  $this->setShowMembers((bool) $row->show_members);
1167 
1168  if (\ilPrivacySettings::getInstance()->participantsListInCoursesEnabled()) {
1169  $this->setShowMembersExport((bool) $row->show_members_export);
1170  } else {
1171  $this->setShowMembersExport(false);
1172  }
1173  $this->setLatitude((string) $row->latitude);
1174  $this->setLongitude((string) $row->longitude);
1175  $this->setLocationZoom((int) $row->location_zoom);
1176  $this->setEnableCourseMap((bool) $row->enable_course_map);
1177  $this->enableSessionLimit((int) $row->session_limit);
1178  $this->setNumberOfPreviousSessions((int) $row->session_prev);
1179  $this->setNumberOfNextSessions((int) $row->session_next);
1180  $this->enableRegistrationAccessCode((bool) $row->reg_ac_enabled);
1181  $this->setRegistrationAccessCode((string) $row->reg_ac);
1182  $this->setAutoNotification((bool) $row->auto_notification);
1183  $this->setStatusDetermination((int) $row->status_dt);
1184  $this->setMailToMembersType((int) $row->mail_members_type);
1185 
1186  if ($row->period_time_indication) {
1187  $this->setCoursePeriod(
1188  new \ilDateTime($row->period_start, IL_CAL_DATETIME, \ilTimeZone::UTC),
1189  new \ilDateTime($row->period_end, IL_CAL_DATETIME, \ilTimeZone::UTC)
1190  );
1191  } elseif (!is_null($row->period_start) && !is_null($row->period_end)) {
1192  $this->setCoursePeriod(
1193  new \ilDate($row->period_start, IL_CAL_DATE),
1194  new \ilDate($row->period_end, IL_CAL_DATE)
1195  );
1196  }
1197  $this->toggleCourseStartTimeIndication((bool) $row->period_time_indication);
1198  $this->setCancellationEnd($row->leave_end ? new ilDate($row->leave_end, IL_CAL_UNIX) : null);
1199  $this->setWaitingListAutoFill((bool) $row->auto_wait);
1200  $this->setSubscriptionMinMembers((int) $row->min_members);
1201  }
1202 
1203  // moved activation to ilObjectActivation
1204  if ($this->ref_id ?? false) {
1205  $activation = ilObjectActivation::getItem($this->ref_id);
1206  switch ($activation["timing_type"]) {
1208  $this->setActivationStart((int) $activation["timing_start"]);
1209  $this->setActivationEnd((int) $activation["timing_end"]);
1210  $this->setActivationVisibility((bool) $activation["visible"]);
1211  break;
1212  }
1213  }
1214  }
1215 
1216  public function initWaitingList(): void
1217  {
1218  if (!$this->waiting_list_obj instanceof ilCourseWaitingList) {
1219  $this->waiting_list_obj = new ilCourseWaitingList($this->getId());
1220  }
1221  }
1222 
1223  protected function initCourseMemberObject(): void
1224  {
1225  $this->member_obj = ilCourseParticipant::_getInstanceByObjId($this->getId(), $this->user->getId());
1226  }
1227 
1228  protected function initCourseMembersObject(): void
1229  {
1230  $this->members_obj = ilCourseParticipants::_getInstanceByObjId($this->getId());
1231  }
1232 
1234  {
1235  if (!$this->member_obj instanceof ilCourseParticipant) {
1236  $this->initCourseMemberObject();
1237  }
1238  return $this->member_obj;
1239  }
1240 
1242  {
1243  if (!$this->members_obj instanceof ilCourseParticipants) {
1244  $this->initCourseMembersObject();
1245  }
1246  return $this->members_obj;
1247  }
1248 
1249 
1250  // RBAC METHODS
1251  public function initDefaultRoles(): void
1252  {
1254  'il_crs_admin_' . $this->getRefId(),
1255  "Admin of crs obj_no." . $this->getId(),
1256  'il_crs_admin',
1257  $this->getRefId()
1258  );
1260  'il_crs_tutor_' . $this->getRefId(),
1261  "Tutor of crs obj_no." . $this->getId(),
1262  'il_crs_tutor',
1263  $this->getRefId()
1264  );
1266  'il_crs_member_' . $this->getRefId(),
1267  "Member of crs obj_no." . $this->getId(),
1268  'il_crs_member',
1269  $this->getRefId()
1270  );
1271  }
1272 
1280  public function setParentRolePermissions(int $a_parent_ref): bool
1281  {
1282  $parent_roles = $this->rbac_review->getParentRoleIds($a_parent_ref);
1283  foreach ($parent_roles as $parent_role) {
1284  $this->rbac_admin->initIntersectionPermissions(
1285  $this->getRefId(),
1286  $parent_role['obj_id'],
1287  $parent_role['parent'],
1288  $this->__getCrsNonMemberTemplateId(),
1290  );
1291  }
1292  return true;
1293  }
1294 
1296  {
1297  $q = "SELECT obj_id FROM object_data WHERE type='rolt' AND title='il_crs_non_member'";
1298  $res = $this->ilias->db->query($q);
1299  $row = $res->fetchRow(ilDBConstants::FETCHMODE_ASSOC);
1300  return (int) $row["obj_id"];
1301  }
1302 
1303  public static function lookupCourseNonMemberTemplatesId(): int
1304  {
1305  global $DIC;
1306 
1307  $ilDB = $DIC->database();
1308 
1309  $query = 'SELECT obj_id FROM object_data WHERE type = ' . $ilDB->quote(
1310  'rolt',
1311  'text'
1312  ) . ' AND title = ' . $ilDB->quote('il_crs_non_member', 'text');
1313  $res = $ilDB->query($query);
1314  $row = $res->fetchRow(ilDBConstants::FETCHMODE_ASSOC);
1315  return (int) $row['obj_id'];
1316  }
1317 
1324  public function getLocalCourseRoles($a_translate = false): array
1325  {
1326  if (empty($this->local_roles)) {
1327  $this->local_roles = array();
1328  $role_arr = $this->rbac_review->getRolesOfRoleFolder($this->getRefId());
1329 
1330  foreach ($role_arr as $role_id) {
1331  if ($this->rbac_review->isAssignable($role_id, $this->getRefId()) == true) {
1332  $role_Obj = ilObjectFactory::getInstanceByObjId($role_id);
1333  if ($a_translate) {
1334  $role_name = ilObjRole::_getTranslation($role_Obj->getTitle());
1335  } else {
1336  $role_name = $role_Obj->getTitle();
1337  }
1338  $this->local_roles[$role_name] = $role_Obj->getId();
1339  }
1340  }
1341  }
1342  return $this->local_roles;
1343  }
1344 
1353  public function getDefaultCourseRoles(string $a_crs_id = ""): array
1354  {
1355  if (strlen($a_crs_id) > 0) {
1356  $crs_id = $a_crs_id;
1357  } else {
1358  $crs_id = $this->getRefId();
1359  }
1360 
1361  $role_arr = $this->rbac_review->getRolesOfRoleFolder($crs_id);
1362 
1363  $arr_crsDefaultRoles = [];
1364  foreach ($role_arr as $role_id) {
1365  $role_Obj = &$this->ilias->obj_factory->getInstanceByObjId($role_id);
1366 
1367  $crs_Member = "il_crs_member_" . $crs_id;
1368  $crs_Admin = "il_crs_admin_" . $crs_id;
1369  $crs_Tutor = "il_crs_tutor_" . $crs_id;
1370 
1371  if (strcmp($role_Obj->getTitle(), $crs_Member) == 0) {
1372  $arr_crsDefaultRoles["crs_member_role"] = $role_Obj->getId();
1373  }
1374 
1375  if (strcmp($role_Obj->getTitle(), $crs_Admin) == 0) {
1376  $arr_crsDefaultRoles["crs_admin_role"] = $role_Obj->getId();
1377  }
1378 
1379  if (strcmp($role_Obj->getTitle(), $crs_Tutor) == 0) {
1380  $arr_crsDefaultRoles["crs_tutor_role"] = $role_Obj->getId();
1381  }
1382  }
1383 
1384  return $arr_crsDefaultRoles;
1385  }
1386 
1390  public function __getLocalRoles(): array
1391  {
1392  return $this->rbac_review->getRolesOfRoleFolder($this->getRefId(), false);
1393  }
1394 
1395  public function __deleteSettings(): void
1396  {
1397  $query = "DELETE FROM crs_settings " .
1398  "WHERE obj_id = " . $this->db->quote($this->getId(), 'integer') . " ";
1399  $this->db->manipulate($query);
1400  }
1401 
1402  public function getDefaultMemberRole(): int
1403  {
1404  $local_roles = $this->__getLocalRoles();
1405  foreach ($local_roles as $role_id) {
1406  $title = ilObject::_lookupTitle($role_id);
1407  if (substr($title, 0, 8) == 'il_crs_m') {
1408  return $role_id;
1409  }
1410  }
1411  return 0;
1412  }
1413 
1414  public function getDefaultTutorRole(): int
1415  {
1416  $local_roles = $this->__getLocalRoles();
1417  foreach ($local_roles as $role_id) {
1418  if ($tmp_role = ilObjectFactory::getInstanceByObjId($role_id, false)) {
1419  if (!strcmp($tmp_role->getTitle(), "il_crs_tutor_" . $this->getRefId())) {
1420  return $role_id;
1421  }
1422  }
1423  }
1424  return 0;
1425  }
1426 
1427  public function getDefaultAdminRole(): int
1428  {
1429  $local_roles = $this->__getLocalRoles();
1430  foreach ($local_roles as $role_id) {
1431  if ($tmp_role = ilObjectFactory::getInstanceByObjId($role_id, false)) {
1432  if (!strcmp($tmp_role->getTitle(), "il_crs_admin_" . $this->getRefId())) {
1433  return $role_id;
1434  }
1435  }
1436  }
1437  return 0;
1438  }
1439 
1440  public static function _deleteUser(int $a_usr_id): void
1441  {
1442  ilCourseLMHistory::_deleteUser($a_usr_id);
1445  }
1446 
1447  protected function doMDUpdateListener(string $a_element): void
1448  {
1449  switch ($a_element) {
1450  case 'General':
1451  // Update ecs content
1452  $ecs = new ilECSCourseSettings($this);
1453  $ecs->handleContentUpdate();
1454  break;
1455  }
1456  }
1457 
1458  public function addAdditionalSubItemInformation(array &$object): void
1459  {
1461  }
1462 
1466  protected function prepareAppointments(string $a_mode = 'create'): array
1467  {
1468  switch ($a_mode) {
1469  case 'create':
1470  case 'update':
1471  $apps = [];
1472  if (!$this->getActivationUnlimitedStatus() && !$this->getOfflineStatus()) {
1473  $app = new ilCalendarAppointmentTemplate(self::CAL_ACTIVATION_START);
1474  $app->setTitle($this->getTitle());
1475  $app->setSubtitle('crs_cal_activation_start');
1476  $app->setTranslationType(ilCalendarEntry::TRANSLATION_SYSTEM);
1477  $app->setDescription($this->getLongDescription());
1478  $app->setStart(new ilDateTime($this->getActivationStart(), IL_CAL_UNIX));
1479  $apps[] = $app;
1480 
1481  $app = new ilCalendarAppointmentTemplate(self::CAL_ACTIVATION_END);
1482  $app->setTitle($this->getTitle());
1483  $app->setSubtitle('crs_cal_activation_end');
1484  $app->setTranslationType(ilCalendarEntry::TRANSLATION_SYSTEM);
1485  $app->setDescription($this->getLongDescription());
1486  $app->setStart(new ilDateTime($this->getActivationEnd(), IL_CAL_UNIX));
1487  $apps[] = $app;
1488  }
1490  $app = new ilCalendarAppointmentTemplate(self::CAL_REG_START);
1491  $app->setTitle($this->getTitle());
1492  $app->setSubtitle('crs_cal_reg_start');
1493  $app->setTranslationType(ilCalendarEntry::TRANSLATION_SYSTEM);
1494  $app->setDescription($this->getLongDescription());
1495  $app->setStart(new ilDateTime($this->getSubscriptionStart(), IL_CAL_UNIX));
1496  $apps[] = $app;
1497 
1498  $app = new ilCalendarAppointmentTemplate(self::CAL_REG_END);
1499  $app->setTitle($this->getTitle());
1500  $app->setSubtitle('crs_cal_reg_end');
1501  $app->setTranslationType(ilCalendarEntry::TRANSLATION_SYSTEM);
1502  $app->setDescription($this->getLongDescription());
1503  $app->setStart(new ilDateTime($this->getSubscriptionEnd(), IL_CAL_UNIX));
1504  $apps[] = $app;
1505  }
1506  if ($this->getCourseStart() && $this->getCourseEnd()) {
1507  $app = new ilCalendarAppointmentTemplate(self::CAL_COURSE_START);
1508  $app->setTitle($this->getTitle());
1509  $app->setSubtitle('crs_cal_start');
1510  $app->setTranslationType(ilCalendarEntry::TRANSLATION_SYSTEM);
1511  $app->setDescription($this->getLongDescription());
1512  $app->setStart($this->getCourseStart());
1513  $app->setFullday(!$this->getCourseStartTimeIndication());
1514  $apps[] = $app;
1515 
1516  $app = new ilCalendarAppointmentTemplate(self::CAL_COURSE_END);
1517  $app->setTitle($this->getTitle());
1518  $app->setSubtitle('crs_cal_end');
1519  $app->setTranslationType(ilCalendarEntry::TRANSLATION_SYSTEM);
1520  $app->setDescription($this->getLongDescription());
1521  $app->setStart($this->getCourseEnd());
1522  $app->setFullday(!$this->getCourseStartTimeIndication());
1523  $apps[] = $app;
1524  }
1525  if (
1527  ) {
1528  $active = ilObjectActivation::getTimingsItems($this->getRefId());
1529  foreach ($active as $null => $item) {
1530  if ($item['timing_type'] == ilObjectActivation::TIMINGS_PRESETTING) {
1531  // create calendar entry for fixed types
1532  $app = new ilCalendarAppointmentTemplate(self::CAL_COURSE_TIMING_START);
1533  $app->setContextInfo($item['ref_id']);
1534  $app->setTitle($item['title']);
1535  $app->setSubtitle('cal_crs_timing_start');
1536  $app->setTranslationType(ilCalendarEntry::TRANSLATION_SYSTEM);
1537  $app->setStart(new ilDate($item['suggestion_start'], IL_CAL_UNIX));
1538  $app->setFullday(true);
1539  $apps[] = $app;
1540 
1541  $app = new ilCalendarAppointmentTemplate(self::CAL_COURSE_TIMING_END);
1542  $app->setContextInfo($item['ref_id']);
1543  $app->setTitle($item['title']);
1544  $app->setSubtitle('cal_crs_timing_end');
1545  $app->setTranslationType(ilCalendarEntry::TRANSLATION_SYSTEM);
1546  $app->setStart(new ilDate($item['suggestion_end'], IL_CAL_UNIX));
1547  $app->setFullday(true);
1548  $apps[] = $app;
1549  }
1550  }
1551  }
1552  return $apps;
1553 
1554  case 'delete':
1555  // Nothing to do: The category and all assigned appointments will be deleted.
1556  return array();
1557  }
1558  return [];
1559  }
1560 
1565  public static function lookupObjectsByCode(string $a_code): array
1566  {
1567  global $DIC;
1568 
1569  $ilDB = $DIC->database();
1570 
1571  $query = "SELECT obj_id FROM crs_settings " .
1572  "WHERE reg_ac_enabled = " . $ilDB->quote(1, 'integer') . " " .
1573  "AND reg_ac = " . $ilDB->quote($a_code, 'text');
1574  $res = $ilDB->query($query);
1575 
1576  $obj_ids = array();
1577  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
1578  $obj_ids[] = (int) $row->obj_id;
1579  }
1580  return $obj_ids;
1581  }
1582 
1587  public function register(
1588  int $a_user_id,
1589  int $a_role = ilCourseConstants::CRS_MEMBER,
1590  bool $a_force_registration = false
1591  ): void {
1592  if ($this->getMembersObject()->isAssigned($a_user_id)) {
1593  return;
1594  }
1595 
1596  if (!$a_force_registration) {
1597  // offline
1598  if (ilObjCourseAccess::_isOffline($this->getId())) {
1600  "Can't register to course, course is offline.",
1602  );
1603  }
1604  // activation
1605  if (!ilObjCourseAccess::_isActivated($this->getId())) {
1607  "Can't register to course, course is not activated.",
1609  );
1610  }
1611 
1615  'Cant registrate to course ' . $this->getId() .
1616  ', course subscription is deactivated.',
1618  );
1619  }
1620  }
1621 
1622  // Time Limitation
1624  if (!$this->inSubscriptionTime()) {
1626  'Cant registrate to course ' . $this->getId() .
1627  ', course is out of registration time.',
1629  );
1630  }
1631  }
1632 
1633  // Max members
1634  if ($this->isSubscriptionMembershipLimited()) {
1635  $free = max(0, $this->getSubscriptionMaxMembers() - $this->getMembersObject()->getCountMembers());
1636  $waiting_list = new ilCourseWaitingList($this->getId());
1637  if ($this->enabledWaitingList() && (!$free || $waiting_list->getCountUsers())) {
1638  $waiting_list->addToList($a_user_id);
1639  $this->lng->loadLanguageModule("crs");
1640  $info = sprintf(
1641  $this->lng->txt('crs_added_to_list'),
1642  $waiting_list->getPosition($a_user_id)
1643  );
1644  $participants = ilCourseParticipants::_getInstanceByObjId($this->getId());
1645  $participants->sendNotification(
1647  $a_user_id
1648  );
1649 
1651  $info,
1653  );
1654  }
1655 
1656  if (!$this->enabledWaitingList() && !$free) {
1657  throw new ilMembershipRegistrationException('Cant registrate to course ' . $this->getId() .
1658  ', membership is limited.', ilMembershipRegistrationException::OBJECT_IS_FULL);
1659  }
1660  }
1661  }
1662 
1663  $this->getMembersObject()->add($a_user_id, $a_role);
1664  $this->getMembersObject()->sendNotification(ilCourseMembershipMailNotification::TYPE_ADMISSION_MEMBER, $a_user_id);
1667  }
1668 
1673  public function getAutoNotification(): bool
1674  {
1675  return $this->auto_notification;
1676  }
1677 
1682  public function setAutoNotification(bool $value): void
1683  {
1684  $this->auto_notification = $value;
1685  }
1686 
1690  public function setStatusDetermination(int $a_value): void
1691  {
1692  $a_value = $a_value;
1693 
1694  // #13905
1695  if ($a_value == self::STATUS_DETERMINATION_LP) {
1697  $a_value = self::STATUS_DETERMINATION_MANUAL;
1698  }
1699  }
1700 
1701  $this->status_dt = $a_value;
1702  }
1703 
1707  public function getStatusDetermination(): int
1708  {
1709  return $this->status_dt;
1710  }
1711 
1712  public function syncMembersStatusWithLP(): void
1713  {
1714  foreach ($this->getMembersObject()->getParticipants() as $user_id) {
1715  // #15529 - force raise on sync
1716  ilLPStatusWrapper::_updateStatus($this->getId(), $user_id, null, false, true);
1717  }
1718  }
1719 
1724  public function checkLPStatusSync(int $a_member_id): void
1725  {
1726  // #11113
1729  // #13811 - we need to suppress creation if status entry
1730  $has_completed = (ilLPStatus::_lookupStatus(
1731  $this->getId(),
1732  $a_member_id,
1733  false
1735  $this->getMembersObject()->updatePassed($a_member_id, $has_completed, false, true);
1736  }
1737  }
1738 
1739  public function getOrderType(): int
1740  {
1741  if ($this->enabledObjectiveView()) {
1742  return ilContainer::SORT_MANUAL;
1743  }
1744  return parent::getOrderType();
1745  }
1746 
1750  public function handleAutoFill(): void
1751  {
1752  if (
1753  !$this->enabledWaitingList() || !$this->hasWaitingListAutoFill()
1754  ) {
1755  $this->course_logger->debug('Waiting list or auto fill disabled.');
1756  return;
1757  }
1758 
1759  $max = $this->getSubscriptionMaxMembers();
1761 
1762  $this->course_logger->debug('Max members: ' . $max);
1763  $this->course_logger->debug('Current members: ' . $now);
1764 
1765  if ($max <= $now) {
1766  return;
1767  }
1768 
1769  // see assignFromWaitingListObject()
1770  $waiting_list = new ilCourseWaitingList($this->getId());
1771 
1772  foreach ($waiting_list->getUserIds() as $user_id) {
1773  if (!$tmp_obj = ilObjectFactory::getInstanceByObjId($user_id, false)) {
1774  $this->course_logger->warning('Cannot create user instance for id: ' . $user_id);
1775  continue;
1776  }
1777  if ($this->getMembersObject()->isAssigned($user_id)) {
1778  $this->course_logger->warning('User is already assigned to course. uid: ' . $user_id . ' course_id: ' . $this->getRefId());
1779  continue;
1780  }
1781  $this->getMembersObject()->add($user_id, ilParticipants::IL_CRS_MEMBER);
1782  $this->getMembersObject()->sendNotification(ilCourseMembershipMailNotification::TYPE_ADMISSION_MEMBER, $user_id, true);
1783  $waiting_list->removeFromList($user_id);
1784  $this->checkLPStatusSync($user_id);
1785 
1786  $this->course_logger->info('Assigned user from waiting list to course: ' . $this->getTitle());
1787  $now++;
1788  if ($now >= $max) {
1789  break;
1790  }
1791  }
1792  }
1793 
1794  public static function mayLeave(int $a_course_id, int $a_user_id = 0, &$a_date = null): bool
1795  {
1796  global $DIC;
1797 
1798  $ilUser = $DIC['ilUser'];
1799  $ilDB = $DIC['ilDB'];
1800 
1801  if (!$a_user_id) {
1802  $a_user_id = $ilUser->getId();
1803  }
1804 
1805  $set = $ilDB->query("SELECT leave_end" .
1806  " FROM crs_settings" .
1807  " WHERE obj_id = " . $ilDB->quote($a_course_id, "integer"));
1808  $row = $ilDB->fetchAssoc($set);
1809  if ($row && $row["leave_end"]) {
1810  // timestamp to date
1811  $limit = date("Ymd", $row["leave_end"]);
1812  if ($limit < date("Ymd")) {
1813  $a_date = new ilDate(date("Y-m-d", $row["leave_end"]), IL_CAL_DATE);
1814  return false;
1815  }
1816  }
1817  return true;
1818  }
1819 
1820  public static function findCoursesWithNotEnoughMembers(): array
1821  {
1822  $ilDB = $GLOBALS['DIC']->database();
1823  $tree = $GLOBALS['DIC']->repositoryTree();
1824 
1825  $res = array();
1826 
1827  $before = new ilDateTime(time(), IL_CAL_UNIX);
1828  $now = $before->get(IL_CAL_UNIX);
1829  $now_dt = $before->get(IL_CAL_DATETIME, '', ilTimeZone::UTC);
1830 
1831  $set = $ilDB->query("SELECT obj_id, min_members" .
1832  " FROM crs_settings" .
1833  " WHERE min_members > " . $ilDB->quote(0, "integer") .
1834  " AND sub_mem_limit = " . $ilDB->quote(1, "integer") . // #17206
1835  " AND ((leave_end IS NOT NULL" .
1836  " AND leave_end < " . $ilDB->quote($now, "text") . ")" .
1837  " OR (leave_end IS NULL" .
1838  " AND sub_end IS NOT NULL" .
1839  " AND sub_end < " . $ilDB->quote($now, "text") . "))" .
1840  " AND (period_start IS NULL OR period_start > " . $ilDB->quote($now_dt, ilDBConstants::T_TEXT) . ")");
1841  while ($row = $ilDB->fetchAssoc($set)) {
1842  $refs = ilObject::_getAllReferences((int) $row['obj_id']);
1843  $ref = end($refs);
1844 
1845  if ($tree->isDeleted($ref)) {
1846  continue;
1847  }
1848 
1849  $part = new ilCourseParticipants((int) $row["obj_id"]);
1850  $reci = $part->getNotificationRecipients();
1851  if ($reci !== []) {
1852  $missing = (int) $row["min_members"] - $part->getCountMembers();
1853  if ($missing > 0) {
1854  $res[(int) $row["obj_id"]] = array($missing, $reci);
1855  }
1856  }
1857  }
1858 
1859  return $res;
1860  }
1861 } //END class.ilObjCourse
const LP_STATUS_COMPLETED_NUM
$app
Definition: cli.php:39
string $title
static lookupTimingMode(int $a_obj_id)
$res
Definition: ltiservices.php:69
string $contact_consultation
setSubscriptionLimitationType(int $a_type)
setSubscriptionStart(int $a_value)
prepareAppointments(string $a_mode='create')
Prepare calendar appointments.
setLongitude(string $a_longitude)
const IL_CAL_DATETIME
setActivationEnd(int $a_value)
static convertDateToUtcDBTimestamp(\ilDateTime $date=null)
setAboStatus(bool $a_status)
static is_email(string $a_email, ilMailRfc822AddressParserFactory $mailAddressParserFactory=null)
This preg-based function checks whether an e-mail address is formally valid.
setActivationVisibility(bool $a_value)
appendMessage(string $a_message)
setContactResponsibility(string $a_value)
cloneObject(int $a_target_id, int $a_copy_id=0, bool $a_omit_tree=false)
Clone course (no member data)
static lookupShowMembersEnabled(int $a_obj_id)
setCoursePeriod(?ilDateTime $start=null, ?ilDateTime $end=null)
bool $reg_access_code_enabled
static lookupCourseNonMemberTemplatesId()
static _isActivated(int $a_obj_id)
Is activated.
setNumberOfNextSessions(int $a_num)
static _getInstanceByObjId(int $a_obj_id, int $a_usr_id)
static _getAllReferences(int $id)
get all reference ids for object ID
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
ilTree $tree
isDeleted(int $a_node_id)
This is a wrapper for isSaved() with a more useful name.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
enableRegistrationAccessCode(bool $a_status)
setNumberOfPreviousSessions(int $a_num)
setSubscriptionMinMembers(int $a_value)
setShowMembers(bool $a_status)
setViewMode(int $a_mode)
Apointment templates are used for automatic generated apointments.
setTimingMode(int $a_mode)
setLocationZoom(int $a_locationzoom)
setActivationStart(int $a_value)
getStatusDetermination()
Get status determination mode.
setStatusDetermination(int $a_value)
Set status determination mode.
static createDefaultRole(string $a_title, string $a_description, string $a_tpl_name, int $a_ref_id)
string $subscription_password
cloneDependencies(int $a_target_id, int $a_copy_id)
const IL_CAL_UNIX
static cloneDependencies(int $ref_id, int $target_id, int $copy_id)
const STATUS_DETERMINATION_LP
setOrderType(int $a_value)
static mayLeave(int $a_course_id, int $a_user_id=0, &$a_date=null)
setCancellationEnd(?ilDate $a_value=null)
static _deleteUser(int $a_usr_id)
handleAutoFill()
Handle course auto fill.
setEnableCourseMap(bool $a_enablemap)
static _lookupViewMode(int $a_id)
setSubscriptionMaxMembers(int $a_value)
static _lookupObjId(int $ref_id)
ilDateTime $crs_end
global $DIC
Definition: feed.php:28
static _deleteUser(int $a_usr_id)
Delete user data.
checkLPStatusSync(int $a_member_id)
sync course status from lp as lp data is not deleted on course exit new members may already have lp c...
static getUserIdByLogin(string $a_login)
static _deleteAll(int $course_id)
setSyllabus(string $a_syllabus)
const CAL_ACTIVATION_END
static _deleteByCourse(int $a_course_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const CAL_ACTIVATION_START
cloneMetaData(ilObject $target_obj)
Copy meta data.
__construct(VocabulariesInterface $vocabularies)
static _deleteAll(int $a_course_id)
string $contact_responsibility
static _lookupTitle(int $obj_id)
static _getInstanceByObjId(int $a_obj_id)
setContactConsultation(string $a_value)
$GLOBALS["DIC"]
Definition: wac.php:31
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
bool $activation_visibility
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setCourseStart(?ilDateTime $a_value=null)
cloneSettings(ilObject $new_obj)
setSubscriptionType(int $a_value)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
enableSessionLimit(int $a_status)
enableSubscriptionMembershipLimitation(bool $a_status)
ilDateTime $crs_start
setSubscriptionEnd(int $a_value)
setContactEmail(string $a_value)
setImportantInformation(string $a_info)
static _getTranslation(string $a_role_title)
string $reg_access_code
static getTimingsItems(int $container_ref_id)
Get (sub) item data for timings view (no session material, no side blocks)
int $subscription_max_members
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _clone(int $a_source_id, int $a_target_id)
static getInstancesByParentId(int $a_parent_id, array $a_filter=null)
setMailToMembersType(int $a_type)
int $subscription_limitation_type
const CAL_COURSE_TIMING_END
getDefaultCourseRoles(string $a_crs_id="")
get default course roles, returns the defaultlike create roles il_crs_tutor, il_crs_admin and il_crs_...
ilCourseWaitingList $waiting_list_obj
header include for all ilias files.
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 _isOffline(int $obj_id)
const CLIENT_WEB_DIR
Definition: constants.php:47
setWaitingListAutoFill(bool $a_value)
setOfflineStatus(bool $status)
const STATUS_DETERMINATION_MANUAL
static _lookupStatus(int $a_obj_id, int $a_user_id, bool $a_create=true)
Lookup status.
bool $auto_fill_from_waiting
ilCourseParticipant $member_obj
const ROLE_FOLDER_ID
Definition: constants.php:34
static _cloneFiles(int $a_source_id, int $a_target_id)
static _getGroupings(int $a_course_id)
static _isActivated(int $a_obj_id, ?bool &$a_visible_flag=null, bool $a_mind_member_view=true)
static _deleteAllEntries(int $a_obj_id)
Delete all entries Normally called in case of object deletion.
getLocalCourseRoles($a_translate=false)
get ALL local roles of course, also those created and defined afterwards only fetch data once from da...
doMDUpdateListener(string $a_element)
getAutoNotification()
Returns automatic notification status from $this->auto_notification.
bool $crs_start_time_indication
static _registrationEnabled(int $a_obj_id)
setSubscriptionPassword(string $a_value)
bool $course_start_time_indication
static getInstanceByObjId(?int $obj_id, bool $stop_on_error=true)
get an instance of an Ilias object by object id
bool $subscription_membership_limitation
static _registrationEnabled(int $a_obj_id)
Registration enabled? Method is in Access class, since it is needed by Access/ListGUI.
setTargetGroup(?string $a_tg)
setContactName(string $a_cn)
const IL_CAL_DATE
setCourseEnd(?ilDateTime $a_value=null)
static generateCode()
Generate new registration key.
static getItem(int $ref_id)
ilCourseParticipants $members_obj
const CAL_COURSE_TIMING_START
static lookupNumberOfMembers(int $a_ref_id)
Lookup number of members.
ilLogger $course_logger
enableWaitingList(bool $a_status)
static findCoursesWithNotEnoughMembers()
static addAdditionalSubItemInformation(array &$item)
Parse item data for list entries.
__construct(int $a_id=0, bool $a_call_by_reference=true)
ilErrorHandling $error
create($a_upload=false)
static deleteResultsForUser(int $a_user_id)
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
$q
Definition: shib_logout.php:21
getLongDescription()
get object long description (stored in object_description)
static _deleteUser(int $a_usr_id)
toggleCourseStartTimeIndication(bool $time_indication)
setRegistrationAccessCode(string $a_code)
static _lookupAboStatus(int $a_id)
static _getInstance(int $a_copy_id)
setShowMembersExport(bool $a_mem_export)
setContactPhone(string $a_value)
setParentRolePermissions(int $a_parent_ref)
This method is called before "initDefaultRoles".
cloneAutoGeneratedRoles(ilObject $new_obj)
Clone automatic genrated roles (permissions and template permissions)
Class ilObjectActivation.
static cloneSettings(int $a_copy_id, int $a_container_id, int $a_new_container_id)
setMessage(string $a_message)
static lookupObjectsByCode(string $a_code)
setLatitude(string $a_latitude)
addAdditionalSubItemInformation(array &$object)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _isSubscriptionNotificationEnabled(int $a_course_id)
static _updateStatus(int $a_obj_id, int $a_usr_id, ?object $a_obj=null, bool $a_percentage=false, bool $a_force_raise=false)
static checkForumsExistsInsert(int $ref_id, int $user_id)
setAutoNotification(bool $value)
Sets automatic notification status in $this->auto_notification, using given $status.