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