diff options
Diffstat (limited to 'lib/models/Course.class.php')
| -rw-r--r-- | lib/models/Course.class.php | 1173 |
1 files changed, 0 insertions, 1173 deletions
diff --git a/lib/models/Course.class.php b/lib/models/Course.class.php deleted file mode 100644 index 59f9b82..0000000 --- a/lib/models/Course.class.php +++ /dev/null @@ -1,1173 +0,0 @@ -<?php -/** - * Course.class.php - * model class for table seminare - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * @author André Noack <noack@data-quest.de> - * @copyright 2012 Stud.IP Core-Group - * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 - * @category Stud.IP - * - * @property string $id alias column for seminar_id - * @property string $seminar_id database column - * @property string|null $veranstaltungsnummer database column - * @property string $institut_id database column - * @property I18NString $name database column - * @property I18NString|null $untertitel database column - * @property int $status database column - * @property I18NString $beschreibung database column - * @property I18NString|null $ort database column - * @property string|null $sonstiges database column - * @property int $lesezugriff database column - * @property int $schreibzugriff database column - * @property int|null $start_time database column - * @property int|null $duration_time database column - * @property I18NString|null $art database column - * @property I18NString|null $teilnehmer database column - * @property I18NString|null $vorrausetzungen database column - * @property I18NString|null $lernorga database column - * @property I18NString|null $leistungsnachweis database column - * @property int $mkdate database column - * @property int $chdate database column - * @property string|null $ects database column - * @property int|null $admission_turnout database column - * @property int|null $admission_binding database column - * @property int $admission_prelim database column - * @property string|null $admission_prelim_txt database column - * @property int $admission_disable_waitlist database column - * @property int $visible database column - * @property int|null $showscore database column - * @property string|null $aux_lock_rule database column - * @property int $aux_lock_rule_forced database column - * @property string|null $lock_rule database column - * @property int $admission_waitlist_max database column - * @property int $admission_disable_waitlist_move database column - * @property int $completion database column - * @property string|null $parent_course database column - * @property SimpleORMapCollection|CourseTopic[] $topics has_many CourseTopic - * @property SimpleORMapCollection|CourseDate[] $dates has_many CourseDate - * @property SimpleORMapCollection|CourseExDate[] $ex_dates has_many CourseExDate - * @property SimpleORMapCollection|CourseMember[] $members has_many CourseMember - * @property SimpleORMapCollection|Deputy[] $deputies has_many Deputy - * @property SimpleORMapCollection|Statusgruppen[] $statusgruppen has_many Statusgruppen - * @property SimpleORMapCollection|AdmissionApplication[] $admission_applicants has_many AdmissionApplication - * @property SimpleORMapCollection|DatafieldEntryModel[] $datafields has_many DatafieldEntryModel - * @property SimpleORMapCollection|SeminarCycleDate[] $cycles has_many SeminarCycleDate - * @property SimpleORMapCollection|BlubberThread[] $blubberthreads has_many BlubberThread - * @property SimpleORMapCollection|ConsultationBlock[] $consultation_blocks has_many ConsultationBlock - * @property SimpleORMapCollection|RoomRequest[] $room_requests has_many RoomRequest - * @property SimpleORMapCollection|Course[] $children has_many Course - * @property SimpleORMapCollection|ToolActivation[] $tools has_many ToolActivation - * @property SimpleORMapCollection|CourseMemberNotification[] $member_notifications has_many CourseMemberNotification - * @property SimpleORMapCollection|Courseware\Unit[] $courseware_units has_many Courseware\Unit - * @property Institute $home_institut belongs_to Institute - * @property AuxLockRule|null $aux belongs_to AuxLockRule - * @property Course|null $parent belongs_to Course - * @property SimpleORMapCollection|Semester[] $semesters has_and_belongs_to_many Semester - * @property SimpleORMapCollection|StudipStudyArea[] $study_areas has_and_belongs_to_many StudipStudyArea - * @property SimpleORMapCollection|Institute[] $institutes has_and_belongs_to_many Institute - * @property SimpleORMapCollection|UserDomain[] $domains has_and_belongs_to_many UserDomain - * @property-read mixed $teachers additional field - * @property mixed $end_time additional field - * @property mixed $start_semester additional field - * @property mixed $end_semester additional field - * @property-read mixed $semester_text additional field - * @property-read mixed $config additional field - */ - -class Course extends SimpleORMap implements Range, PrivacyObject, StudipItem, FeedbackRange, Studip\Calendar\Owner -{ - protected static function configure($config = []) - { - $config['db_table'] = 'seminare'; - $config['has_many']['topics'] = [ - 'class_name' => CourseTopic::class, - 'on_delete' => 'delete', - 'on_store' => 'store', - ]; - $config['has_many']['dates'] = [ - 'class_name' => CourseDate::class, - 'assoc_foreign_key' => 'range_id', - 'on_delete' => 'delete', - 'on_store' => 'store', - 'order_by' => 'ORDER BY date' - ]; - $config['has_many']['ex_dates'] = [ - 'class_name' => CourseExDate::class, - 'assoc_foreign_key' => 'range_id', - 'on_delete' => 'delete', - 'on_store' => 'store', - ]; - $config['has_many']['members'] = [ - 'class_name' => CourseMember::class, - 'assoc_func' => 'findByCourse', - 'on_delete' => 'delete', - 'on_store' => 'store', - ]; - $config['has_many']['deputies'] = [ - 'class_name' => Deputy::class, - 'assoc_func' => 'findByRange_id', - 'on_delete' => 'delete', - 'on_store' => 'store', - ]; - $config['has_many']['statusgruppen'] = [ - 'class_name' => Statusgruppen::class, - 'on_delete' => 'delete', - 'on_store' => 'store', - ]; - $config['has_many']['admission_applicants'] = [ - 'class_name' => AdmissionApplication::class, - 'assoc_func' => 'findByCourse', - 'on_delete' => 'delete', - 'on_store' => 'store', - ]; - $config['has_many']['datafields'] = [ - 'class_name' => DatafieldEntryModel::class, - 'assoc_func' => 'findByModel', - 'assoc_foreign_key' => function ($model, $params) { - $model->setValue('range_id', $params[0]->id); - }, - 'foreign_key' => function ($course) { - return [$course]; - }, - 'on_delete' => 'delete', - 'on_store' => 'store', - ]; - $config['has_many']['cycles'] = [ - 'class_name' => SeminarCycleDate::class, - 'assoc_func' => 'findBySeminar', - 'on_delete' => 'delete', - 'on_store' => 'store', - ]; - $config['has_many']['blubberthreads'] = [ - 'class_name' => BlubberThread::class, - 'assoc_func' => 'findBySeminar', - 'on_delete' => 'delete', - 'on_store' => 'store', - ]; - $config['has_many']['consultation_blocks'] = [ - 'class_name' => ConsultationBlock::class, - 'assoc_foreign_key' => 'range_id', - 'on_delete' => 'delete', - ]; - - $config['has_and_belongs_to_many']['semesters'] = [ - 'class_name' => Semester::class, - 'thru_table' => 'semester_courses', - 'thru_key' => 'course_id', - 'thru_assoc_key' => 'semester_id', - 'order_by' => 'ORDER BY beginn ASC', - 'on_delete' => 'delete', - 'on_store' => 'store', - ]; - - $config['belongs_to']['home_institut'] = [ - 'class_name' => Institute::class, - 'foreign_key' => 'institut_id', - 'assoc_func' => 'find', - ]; - $config['belongs_to']['aux'] = [ - 'class_name' => AuxLockRule::class, - 'foreign_key' => 'aux_lock_rule', - ]; - $config['has_and_belongs_to_many']['study_areas'] = [ - 'class_name' => StudipStudyArea::class, - 'thru_table' => 'seminar_sem_tree', - 'on_delete' => 'delete', - 'on_store' => 'store', - ]; - $config['has_and_belongs_to_many']['institutes'] = [ - 'class_name' => Institute::class, - 'thru_table' => 'seminar_inst', - 'on_delete' => 'delete', - 'on_store' => 'store', - ]; - - $config['has_and_belongs_to_many']['domains'] = [ - 'class_name' => UserDomain::class, - 'thru_table' => 'seminar_userdomains', - 'on_delete' => 'delete', - 'on_store' => 'store', - 'order_by' => 'ORDER BY name', - ]; - - $config['has_many']['room_requests'] = [ - 'class_name' => RoomRequest::class, - 'assoc_foreign_key' => 'course_id', - 'on_delete' => 'delete', - ]; - $config['belongs_to']['parent'] = [ - 'class_name' => Course::class, - 'foreign_key' => 'parent_course' - ]; - $config['has_many']['children'] = [ - 'class_name' => Course::class, - 'assoc_foreign_key' => 'parent_course', - 'order_by' => 'GROUP BY seminar_id ORDER BY VeranstaltungsNummer, Name' - ]; - $config['has_many']['tools'] = [ - 'class_name' => ToolActivation::class, - 'assoc_foreign_key' => 'range_id', - 'order_by' => 'ORDER BY position', - 'on_delete' => 'delete', - ]; - $config['has_many']['member_notifications'] = [ - 'class_name' => CourseMemberNotification::class, - 'on_delete' => 'delete', - ]; - - $config['has_many']['courseware_units'] = [ - 'class_name' => \Courseware\Unit::class, - 'assoc_foreign_key' => 'range_id', - 'on_delete' => 'delete', - ]; - - $config['default_values']['lesezugriff'] = 1; - $config['default_values']['schreibzugriff'] = 1; - $config['default_values']['duration_time'] = 0; - - $config['additional_fields']['teachers'] = [ - 'get' => 'getTeachers' - ]; - $config['additional_fields']['end_time'] = true; - - $config['additional_fields']['start_semester'] = [ - 'get' => 'getStartSemester', - 'set' => '_set_semester' - ]; - $config['additional_fields']['end_semester'] = [ - 'get' => 'getEndSemester', - 'set' => '_set_semester' - ]; - $config['additional_fields']['semester_text'] = [ - 'get' => 'getTextualSemester' - ]; - - $config['additional_fields']['config'] = [ - 'get' => function (Course $course) { - return $course->getConfiguration(); - } - ]; - - $config['notification_map']['after_create'] = 'CourseDidCreateOrUpdate'; - $config['notification_map']['after_store'] = 'CourseDidCreateOrUpdate'; - - $config['i18n_fields']['name'] = true; - $config['i18n_fields']['untertitel'] = true; - $config['i18n_fields']['beschreibung'] = true; - $config['i18n_fields']['art'] = true; - $config['i18n_fields']['teilnehmer'] = true; - $config['i18n_fields']['vorrausetzungen'] = true; - $config['i18n_fields']['lernorga'] = true; - $config['i18n_fields']['leistungsnachweis'] = true; - $config['i18n_fields']['ort'] = true; - - $config['registered_callbacks']['before_update'][] = 'logStore'; - $config['registered_callbacks']['before_store'][] = 'cbSetStartAndDurationTime'; - $config['registered_callbacks']['after_create'][] = 'setDefaultTools'; - $config['registered_callbacks']['after_delete'][] = function ($course) { - CourseAvatar::getAvatar($course->id)->reset(); - FeedbackElement::deleteBySQL('course_id = ?', [$course->id]); - // Remove subcourse relations, leaving subcourses intact. - DBManager::get()->execute( - "UPDATE `seminare` SET `parent_course` = NULL WHERE `parent_course` = :course", - ['course' => $course->id] - ); - DBManager::get()->execute( - "DELETE FROM `forum_visits` WHERE `seminar_id` = ?", - [$course->id] - ); - }; - - parent::configure($config); - } - - - /** - * Returns the currently active course or false if none is active. - * - * @return Course object of currently active course, null otherwise - * @since 3.0 - */ - public static function findCurrent() - { - if (Context::isCourse()) { - return Context::get(); - } - - return null; - } - - /** - * Returns the associated mvv modules for a given course id. - * - * @param string $course_id - * @return Modul[] - */ - public static function getMVVModulesForCourseId(string $course_id): array - { - $query = "SELECT mvv_modul.* - FROM mvv_lvgruppe_seminar - JOIN `mvv_lvgruppe` on(`mvv_lvgruppe_seminar`.`lvgruppe_id` = `mvv_lvgruppe`.`lvgruppe_id`) - JOIN `mvv_lvgruppe_modulteil` on(`mvv_lvgruppe_seminar`.`lvgruppe_id` = `mvv_lvgruppe_modulteil`.`lvgruppe_id`) - JOIN `mvv_modulteil` on(`mvv_lvgruppe_modulteil`.`modulteil_id` = `mvv_modulteil`.`modulteil_id`) - JOIN `mvv_modul` on(`mvv_modulteil`.`modul_id` = `mvv_modul`.`modul_id`) - WHERE seminar_id = ?"; - return DBManager::get()->fetchAll($query, [$course_id], function ($row) { - return Modul::buildExisting($row); - }); - } - - public function getEnd_Time() - { - return $this->duration_time == -1 ? -1 : $this->start_time + $this->duration_time; - } - - public function setEnd_Time($value) - { - if ($value == -1) { - $this->duration_time = -1; - } elseif ($this->start_time > 0 && $value > $this->start_time) { - $this->duration_time = $value - $this->start_time; - } else { - $this->duration_time = 0; - } - } - - public function _set_semester($field, $value) - { - $method = 'set' . ($field === 'start_semester' ? 'StartSemester' : 'EndSemester'); - $this->$method($value); - } - - /** - * @param Semester $semester - */ - public function setStartSemester(Semester $semester) - { - $end_semester = $this->semesters->last(); - $start_semester = $this->semesters->first(); - if ($start_semester && $start_semester->id === $semester->id) { - return; - } - if ($end_semester) { - if (count($this->semesters) > 1 && $end_semester->beginn < $semester->beginn) { - throw new InvalidArgumentException('start-semester must start before end-semester'); - } - foreach ($this->semesters as $key => $one_semester) { - if ($one_semester->beginn < $semester->beginn) { - $this->semesters->offsetUnset($key); - } - } - } - $this->semesters[] = $semester; - $this->semesters->orderBy('beginn asc'); - //add possibly missing semesters between start_semester and end_semester - if (count($this->semesters) > 1 && $semester->beginn < $start_semester->beginn) { - $this->setEndSemester($end_semester); - } - } - - /** - * @param Semester|null $semester - */ - public function setEndSemester(?Semester $semester) - { - $end_semester = $this->semesters->last(); - $start_semester = $this->semesters->first(); - if ( - (is_null($end_semester) && is_null($semester)) - || ($end_semester && $semester && $end_semester->id === $semester->id)) { - return; - } - if ($start_semester) { - if ($semester && $start_semester->beginn > $semester->beginn) { - throw new InvalidArgumentException('end-semester must start after start-semester'); - } - $this->semesters = []; - if ($semester) { - $all_semester = SimpleCollection::createFromArray(Semester::getAll()); - $this->semesters = $all_semester->findBy('beginn', [$start_semester->beginn, $semester->beginn], '>=<='); - } - } else { - if ($semester) { - $this->semesters[] = $semester; - } - } - } - - /** - * Retrieves the first semester of a course, if applicable. - * - * @returns Semester|null Either the first semester of the course - * or null, if no semester could be found. - */ - public function getStartSemester() - { - if (count($this->semesters) > 0) { - return $this->semesters->first(); - } else { - return Semester::findCurrent(); - } - } - - /** - * Retrieves the last semester of a course, if applicable. - * - * @returns Semester|null Either the last semester of the course - * or null, if no semester could be found. - */ - public function getEndSemester() - { - if (count($this->semesters) > 0) { - return $this->semesters->last(); - } - } - - /** - * Returns the readable semester duration as as string - * @return string : readable semester - */ - public function getTextualSemester() - { - if (count($this->semesters) > 1) { - return $this->start_semester->short_name . ' - ' . $this->end_semester->short_name; - } elseif (count($this->semesters) === 1) { - return $this->start_semester->short_name; - } else { - return _('unbegrenzt'); - } - } - - /** - * Returns true if this course has no end-semester. Else false. - * @return bool : true if there is no end-semester - */ - public function isOpenEnded() - { - return count($this->semesters) === 0; - } - - /** - * Returns if this course is in the given semester - * @param Semester $semester : instance of the given semester - * @return bool : true if this course is part of this semester - */ - public function isInSemester(Semester $semester) - { - if (count($this->semesters) > 0) { - foreach ($this->semesters as $s) { - if ($s->id === $semester->id) { - return true; - } - } - return false; - } else { - return true; - } - } - - public function getTeachers() - { - return $this->members->filter(function ($m) { - return $m['status'] === 'dozent'; - }); - } - - public function getFreeSeats() - { - $free_seats = $this->admission_turnout - $this->getNumParticipants(); - return max($free_seats, 0); - } - - public function isWaitlistAvailable() - { - if ($this->admission_disable_waitlist) { - return false; - } - - if ($this->admission_waitlist_max) { - return $this->admission_waitlist_max - $this->getNumWaiting() > 0; - } - - return true; - } - - /** - * Retrieves all members of a status - * - * @param String|Array $status the status to filter with - * @param bool $as_collection return collection instead of array? - * @return Array|SimpleCollection an array of all those members. - */ - public function getMembersWithStatus($status, $as_collection = false) - { - $result = CourseMember::findByCourseAndStatus($this->id, $status); - return $as_collection - ? SimpleCollection::createFromArray($result) - : $result; - } - - /** - * Retrieves the number of all members of a status - * - * @param String|Array $status the status to filter with - * - * @return int the number of all those members. - */ - public function countMembersWithStatus($status) - { - return CourseMember::countByCourseAndStatus($this->id, $status); - } - - public function getNumParticipants() - { - return $this->countMembersWithStatus('user autor') + $this->getNumPrelimParticipants(); - } - - public function getNumPrelimParticipants() - { - return AdmissionApplication::countBySql( - "seminar_id = ? AND status = 'accepted'", - [$this->id] - ); - } - - public function getNumWaiting() - { - return AdmissionApplication::countBySql( - "seminar_id = ? AND status = 'awaiting'", - [$this->id] - ); - } - - public function getParticipantStatus($user_id) - { - $p_status = $this->members->findBy('user_id', $user_id)->val('status'); - if (!$p_status) { - $p_status = $this->admission_applicants->findBy('user_id', $user_id)->val('status'); - } - return $p_status; - } - - /** - * Returns the semType object that is defined for the course - * - * @return SemType The semTypeObject for the course - */ - public function getSemType() - { - $semTypes = SemType::getTypes(); - if (isset($semTypes[$this->status])) { - return $semTypes[$this->status]; - } - - Log::error(sprintf('SemType not found id:%s status:%s', $this->id, $this->status)); - return new SemType(['name' => 'Fehlerhafter Veranstaltungstyp']); - } - - /** - * Returns the SemClass object that is defined for the course - * - * @return SemClass The SemClassObject for the course - */ - public function getSemClass() - { - return $this->getSemType()->getClass(); - } - - /** - * Returns the full name of a course. If the important course numbers - * (IMPORTANT_SEMNUMBER) is set in global configs it will also display - * the coursenumber - * - * @param string formatting template name - * @return string Fullname - */ - public function getFullName($format = 'default') - { - $template = [ - 'name' => '%1$s', - 'name-semester' => '%1$s (%4$s)', - 'number-name' => '%3$s %1$s', - 'number-name-semester' => '%3$s %1$s (%4$s)', - 'number-type-name' => '%3$s %2$s: %1$s', - 'sem-duration-name' => '%4$s', - 'type-name' => '%2$s: %1$s', - 'type-number-name' => '%2$s: %3$s %1$s', - ]; - - if ($format === 'default' || !isset($template[$format])) { - $format = Config::get()->IMPORTANT_SEMNUMBER ? 'type-number-name' : 'type-name'; - } - $sem_type = $this->getSemType(); - $data[0] = $this->name; - $data[1] = $sem_type['name']; - $data[2] = $this->veranstaltungsnummer; - $data[3] = $this->getTextualSemester(); - return trim(vsprintf($template[$format], array_map('trim', $data))); - } - - - /** - * Retrieves the course dates including cancelled dates ("ex-dates"). - * The dates can be filtered by an optional time range. By default, - * all dates are retrieved. - * - * @param int $range_begin The begin timestamp of the time range. - * - * @param int $range_end The end timestamp of the time range. - * - * @returns SimpleCollection A collection of all retrieved dates and - * cancelled dates. - */ - public function getDatesWithExdates($range_begin = 0, $range_end = 0) - { - $dates = []; - if (($range_begin > 0) && ($range_end > 0) && ($range_end > $range_begin)) { - $ex_dates = $this->ex_dates->findBy('content', '', '<>') - ->findBy('date', $range_begin, '>=') - ->findBy('end_time', $range_end, '<='); - $dates = $this->dates->findBy('date', $range_begin, '>=') - ->findBy('end_time', $range_end, '<='); - $dates->merge($ex_dates); - } else { - $dates = $this->ex_dates->findBy('content', '', '<>'); - $dates->merge($this->dates); - } - $dates->uasort(function($a, $b) { - return $a->date - $b->date - ?: strnatcasecmp($a->getRoomName(), $b->getRoomName()); - }); - return $dates; - } - - /** - * Sets this courses study areas to the given values. - * - * @param array $ids the new study areas - * @return bool Changes successfully saved? - */ - public function setStudyAreas($ids) - { - $old = $this->study_areas->pluck('sem_tree_id'); - $added = array_diff($ids, $old); - $removed = array_diff($old, $ids); - $success = false; - if ($added || $removed) { - - $this->study_areas = SimpleCollection::createFromArray(StudipStudyArea::findMany($ids)); - - if ($this->store()) { - NotificationCenter::postNotification('CourseDidChangeStudyArea', $this); - $success = true; - - foreach ($added as $one) { - StudipLog::log('SEM_ADD_STUDYAREA', $this->id, $one); - - $area = $this->study_areas->find($one); - if ($area->isModule()) { - NotificationCenter::postNotification( - 'CourseAddedToModule', - $area, - ['module_id' => $one, 'course_id' => $this->id] - ); - } - } - - foreach ($removed as $one) { - StudipLog::log('SEM_DELETE_STUDYAREA', $this->id, $one); - - $area = StudipStudyArea::find($one); - if ($area->isModule()) { - NotificationCenter::postNotification( - 'CourseRemovedFromModule', - $area, - ['module_id' => $one, 'course_id' => $this->id] - ); - } - } - } - } - - return $success; - } - - /** - * Is the current course visible for the current user? - * @param string $user_id - * @return bool Visible? - */ - public function isVisibleForUser($user_id = null) - { - return $this->visible - || $GLOBALS['perm']->have_perm(Config::get()->SEM_VISIBILITY_PERM, $user_id) - || $GLOBALS['perm']->have_studip_perm('user', $this->id, $user_id); - } - - /** - * Returns a descriptive text for the range type. - * - * @return string - */ - public function describeRange() - { - return _('Veranstaltung'); - } - - /** - * Returns a unique identificator for the range type. - * - * @return string - */ - public function getRangeType() - { - return 'course'; - } - - /** - * Returns the id of the current range - * - * @return string - */ - public function getRangeId() - { - return $this->id; - } - - /** - * {@inheritdoc} - */ - public function getConfiguration() - { - return CourseConfig::get($this); - } - - /** - * Decides whether the user may access the range. - * - * @param string|null $user_id Optional id of a user, defaults to current user - * @return bool - * @todo Check permissions - */ - public function isAccessibleToUser($user_id = null) - { - if ($user_id === null) { - $user_id = $GLOBALS['user']->id; - } - return $GLOBALS['perm']->have_studip_perm('user', $this->id, $user_id); - } - - /** - * Decides whether the user may edit/alter the range. - * - * @param string|null $user_id Optional id of a user, defaults to current user - * @return bool - * @todo Check permissions - */ - public function isEditableByUser($user_id = null) - { - if ($user_id === null) { - $user_id = $GLOBALS['user']->id; - } - return $GLOBALS['perm']->have_studip_perm('tutor', $this->id, $user_id); - } - - /** - * Returns the appropriate icon for the completion status. - * - * Mapping (completion -> icon role): - * - 0 => status-red - * - 1 => status-yellow - * - 2 => status-green - * - * @return Icon class - */ - public function getCompletionIcon() - { - $role = Icon::ROLE_STATUS_RED; - if ($this->completion == 1) { - $role = Icon::ROLE_STATUS_YELLOW; - } elseif ($this->completion == 2) { - $role = Icon::ROLE_STATUS_GREEN; - } - return Icon::create('radiobutton-checked', $role); - } - - /** - * Returns the appropriate label for the completion status. - * - * @return string - */ - public function getCompetionLabel(): string - { - return [ - 0 => _('unvollständig'), - 1 => _('in Bearbeitung'), - 2 => _('fertig'), - ][$this->completion] ?? _('undefiniert'); - } - - /** - * Generates a general log entry if the course were changed. - * Furthermore, this method emits notifications when the - * start and/or the end semester has/have changed. - */ - protected function logStore() - { - if ($this->isFieldDirty('start_time')) { - //Log change of start semester: - StudipLog::log('SEM_SET_STARTSEMESTER', $this->id, isset($this->start_semester) ? $this->start_semester->name : _('unbegrenzt')); - NotificationCenter::postNotification('CourseDidChangeSchedule', $this); - } - if ($this->isFieldDirty('duration_time')) { - StudipLog::log('SEM_SET_ENDSEMESTER', $this->id, $this->getTextualSemester()); - NotificationCenter::postNotification('CourseDidChangeSchedule', $this); - } - - $log = []; - if ($this->isFieldDirty('admission_prelim')) { - $log[] = $this->admission_prelim ? _('Neuer Anmeldemodus: Vorläufiger Eintrag') : _('Neuer Anmeldemodus: Direkter Eintrag'); - } - - if ($this->isFieldDirty('admission_binding')) { - $log[] = $this->admission_binding? _('Anmeldung verbindlich') : _('Anmeldung unverbindlich'); - } - - if ($this->isFieldDirty('admission_turnout')) { - $log[] = sprintf(_('Neue Teilnehmerzahl: %s'), (int)$this->admission_turnout); - } - - if ($this->isFieldDirty('admission_disable_waitlist')) { - $log[] = $this->admission_disable_waitlist ? _('Warteliste aktiviert') : _('Warteliste deaktiviert'); - } - - if ($this->isFieldDirty('admission_waitlist_max')) { - $log[] = sprintf(_('Plätze auf der Warteliste geändert: %u'), (int)$this->admission_waitlist_max); - } - - if ($this->isFieldDirty('admission_disable_waitlist_move')) { - $log[] = $this->admission_disable_waitlist ? _('Nachrücken aktiviert') : _('Nachrücken deaktiviert'); - } - - if ($this->isFieldDirty('admission_prelim_txt')) { - if ($this->admission_prelim_txt) { - $log[] = sprintf(_('Neuer Hinweistext bei vorläufigen Eintragungen: %s'), strip_tags(kill_format($this->admission_prelim_txt))); - } else { - $log[] = _('Hinweistext bei vorläufigen Eintragungen wurde entfert'); - } - } - - if (!empty($log)) { - StudipLog::log( - 'SEM_CHANGED_ACCESS', - $this->id, - null, - '', - implode(' - ', $log) - ); - } - - if ($this->isFieldDirty('visible')) { - StudipLog::log($this->visible ? 'SEM_VISIBLE' : 'SEM_INVISIBLE', $this->id); - } - } - - /** - * Called directly before storing the object to edit the columns start_time and duration_time - * which are both deprecated but are still in use for older plugins. - */ - public function cbSetStartAndDurationTime() - { - if ($this->isFieldDirty('start_time')) { - $this->setStartSemester(Semester::findByTimestamp($this->start_time)); - } - if ($this->isFieldDirty('duration_time')) { - $this->setEndSemester($this->duration_time == -1 ? null : Semester::findByTimestamp($this->start_time + $this->duration_time)); - } - if ($this->isOpenEnded()) { - $this->start_time = $this->start_time ?: Semester::findCurrent()->beginn ?? time(); - $this->duration_time = -1; - } else { - $this->start_time = $this->getStartSemester()->beginn; - $this->duration_time = $this->getEndSemester()->beginn - $this->start_time; - } - } - - - //StudipItem interface implementation: - - public function getItemName($long_format = true) - { - if ($long_format) { - return $this->getFullName(); - } else { - return $this->name; - } - } - - public function getItemURL() - { - return URLHelper::getURL( - 'dispatch.php/course/details/index', - [ - 'cid' => $this->id - ] - ); - } - - public function getItemAvatarURL() - { - $avatar = CourseAvatar::getAvatar($this->id); - if ($avatar) { - return $avatar->getURL(Avatar::NORMAL); - } - return ''; - } - - - /** - * Export available data of a given user into a storage object - * (an instance of the StoredUserData class) for that user. - * - * @param StoredUserData $storage object to store data into - */ - public static function exportUserData(StoredUserData $storage) - { - $sorm = self::findThru($storage->user_id, [ - 'thru_table' => 'seminar_user', - 'thru_key' => 'user_id', - 'thru_assoc_key' => 'Seminar_id', - 'assoc_foreign_key' => 'Seminar_id', - ]); - if ($sorm) { - $field_data = []; - foreach ($sorm as $row) { - $field_data[] = $row->toRawArray(); - } - if ($field_data) { - $storage->addTabularData(_('Seminare'), 'seminare', $field_data); - } - } - } - public function getRangeName() - { - return $this->name; - } - - public function getRangeIcon($role) - { - return Icon::create('seminar', $role); - } - - public function getRangeUrl() - { - return 'course/overview'; - } - - public function getRangeCourseId() - { - return $this->Seminar_id; - } - - public function isRangeAccessible(string $user_id = null): bool - { - $user_id = $user_id ?? $GLOBALS['user']->id; - return $GLOBALS['perm']->have_studip_perm('autor', $this->Seminar_id, $user_id); - } - - - public function getLink() : StudipLink - { - return new StudipLink($this->getItemURL(), $this->name, Icon::create('seminar')); - } - - - /** - * Returns a list of courses for the specified user. - * Permission levels may be supplied to limit the course list. - * - * @param string $user_id The ID of the user whose courses shall be retrieved. - * - * @param string[] $perms The permission levels of the user that shall be - * regarded when retrieving courses. - * - * @param bool $with_deputies Whether to include courses where the user is - * a deputy (true) or not (false). Defaults to true. - * - * @return Course[] A list of courses. - */ - public static function findByUser($user_id, $perms = [], $with_deputies = true) - { - if (!$user_id) { - return []; - } - - $db = DBManager::get(); - $sql = "SELECT `seminar_id` - FROM `seminar_user` - WHERE `user_id` = :user_id"; - $sql_params = ['user_id' => $user_id]; - if (is_array($perms) && count($perms)) { - $sql .= ' AND `status` IN (:perms)'; - $sql_params['perms'] = $perms; - } - $seminar_ids = $db->fetchFirst($sql, $sql_params); - if (Config::get()->DEPUTIES_ENABLE && $with_deputies) { - $sql = 'SELECT range_id FROM `deputies` WHERE `deputies`.`user_id` = :user_id'; - $seminar_ids = array_merge($seminar_ids, $db->fetchFirst($sql, $sql_params)); - } - - $name_sort = Config::get()->IMPORTANT_SEMNUMBER ? 'VeranstaltungsNummer, Name' : 'Name'; - - return Course::findBySQL( - "LEFT JOIN semester_courses ON (semester_courses.course_id = seminare.Seminar_id) - WHERE Seminar_id IN (?) - GROUP BY seminare.Seminar_id - ORDER BY semester_courses.semester_id IS NULL DESC, start_time DESC, {$name_sort}", - [$seminar_ids] - ); - } - - /** - * Returns whether this course is a studygroup - * @return bool - */ - public function isStudygroup() - { - return in_array($this->status, studygroup_sem_types()); - } - - /** - * - */ - public function setDefaultTools() - { - $this->tools = []; - foreach (array_values($this->getSemClass()->getActivatedModuleObjects()) as $module) { - PluginManager::getInstance()->setPluginActivated($module->getPluginId(), $this->id, true); - $this->tools[] = ToolActivation::find([$this->id, $module->getPluginId()]); - } - } - - /** - * @param $name string name of tool / plugin - * @return bool - */ - public function isToolActive($name) - { - $plugin = PluginEngine::getPlugin($name); - return $plugin && $this->tools->findOneby('plugin_id', $plugin->getPluginId()); - } - - /** - * returns all activated plugins/modules for this course - * @return StudipModule[] - */ - public function getActivatedTools() - { - return array_filter($this->tools->getStudipModule()); - } - - /** - * @see Range::__toString() - */ - public function __toString() : string - { - return $this->getFullName(); - } - - /** - * @inheritDoc - */ - public static function getCalendarOwner(string $owner_id): ?\Studip\Calendar\Owner - { - return self::find($owner_id); - } - - /** - * @inheritDoc - */ - public function isCalendarReadable(?string $user_id = null): bool - { - if ($user_id === null) { - $user_id = User::findCurrent()->id; - } - - //Calendar read permissions are granted for all participants - //that have at least user permissions. - return $GLOBALS['perm']->have_studip_perm('user', $this->id, $user_id); - } - - /** - * @inheritDoc - */ - public function isCalendarWritable(string $user_id = null): bool - { - if ($user_id === null) { - $user_id = User::findCurrent()->id; - } - - //Calendar write permissions are granted for all participants - //that have autor permissions or higher. - return $GLOBALS['perm']->have_studip_perm('autor', $this->id, $user_id); - } - - /** - * Get user information for all users in this course - * - */ - public function getMembersData(?string $status = ''): array - { - $result = []; - - if (!$status) { - foreach ($this->members->orderBy('position, nachname') as $member) { - $result[$member->user_id] = $member->getExportData(); - } - foreach ($this->admission_applicants->findBy('status', 'accepted')->orderBy('position') as $member) { - $result[$member->user_id] = $member->getExportData(); - } - } elseif ($status === 'awaiting') { - foreach ($this->admission_applicants->findBy('status', $status)->orderBy('position') as $member) { - $result[$member->user_id] = $member->getExportData(); - } - } elseif ($status === 'claiming') { - $cs = CourseSet::getSetForCourse($this->id); - if (is_object($cs) && !$cs->hasAlgorithmRun()) { - $claiming_users = User::findFullMany(array_keys(AdmissionPriority::getPrioritiesByCourse($cs->getId(), $this->id)), 'ORDER BY nachname'); - foreach ($claiming_users as $claiming_user) { - $studycourse = []; - $claiming_user->studycourses->map(function($sc) use (&$studycourse) { - $studycourse[]= $sc->studycourse->name . ',' . $sc->degree->name . ',' . $sc->semester; - }); - $export_data = [ - 'status' => $status, - 'salutation' => $claiming_user->salutation, - 'Titel' => $claiming_user->title_front, - 'Vorname' => $claiming_user->vorname, - 'Nachname' => $claiming_user->nachname, - 'Titel2' => $claiming_user->title_rear, - 'username' => $claiming_user->username, - 'privadr' => $claiming_user->privadr, - 'privatnr' => $claiming_user->privatnr, - 'Email' => $claiming_user->email, - 'Anmeldedatum' => '', - 'Matrikelnummer' => $claiming_user->matriculation_number, - 'studiengaenge' => implode(';', $studycourse), - 'position' => 0, - ]; - $result[$claiming_user->user_id] = $export_data; - } - } - } - - return $result; - } - -} |
