diff options
| author | Rasmus Fuhse <fuhse@data-quest.de> | 2022-03-31 14:17:41 +0000 |
|---|---|---|
| committer | André Noack <noack@data-quest.de> | 2022-03-31 14:17:41 +0000 |
| commit | b7802baa589843f44f5cbed5a04dd522bd54daa0 (patch) | |
| tree | 5129c94b428c3b1dbf9aaccc12b64e38b3d6bff7 /lib | |
| parent | 8073d9c7cb2e8e187cbfb776b865ec9ba2623c25 (diff) | |
Resolve "Unbegrenzte Veranstaltungen haben Startzeitpunkt!"
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/classes/AdminCourseFilter.class.php | 2 | ||||
| -rw-r--r-- | lib/classes/MyRealmModel.php | 4 | ||||
| -rw-r--r-- | lib/classes/coursewizardsteps/BasicDataWizardStep.php | 6 | ||||
| -rw-r--r-- | lib/classes/searchtypes/StandardSearch.class.php | 21 | ||||
| -rw-r--r-- | lib/models/Course.class.php | 160 | ||||
| -rw-r--r-- | lib/models/Semester.class.php | 16 |
6 files changed, 104 insertions, 105 deletions
diff --git a/lib/classes/AdminCourseFilter.class.php b/lib/classes/AdminCourseFilter.class.php index ea0de9a..6fa4724 100644 --- a/lib/classes/AdminCourseFilter.class.php +++ b/lib/classes/AdminCourseFilter.class.php @@ -171,7 +171,7 @@ class AdminCourseFilter 'join' => "LEFT JOIN", 'on' => "semester_courses.course_id = seminare.Seminar_id" ]; - $this->settings['query']['where']['semester'] = "(seminare.start_time <= :semester_beginn AND (semester_courses.semester_id IS NULL OR semester_courses.semester_id = :semester_id))"; + $this->settings['query']['where']['semester'] = "(semester_courses.semester_id IS NULL OR semester_courses.semester_id = :semester_id)"; $this->settings['parameter']['semester_beginn'] = $semester['beginn']; $this->settings['parameter']['semester_id'] = $semester['id']; return $this; diff --git a/lib/classes/MyRealmModel.php b/lib/classes/MyRealmModel.php index 5703389..a68a0c1 100644 --- a/lib/classes/MyRealmModel.php +++ b/lib/classes/MyRealmModel.php @@ -347,8 +347,8 @@ class MyRealmModel $_course['temp_name'] = $course->name; $_course['number'] = $course->veranstaltungsnummer; $_course['is_deputy'] = $is_deputy; - if ($show_semester_name && count($course->semesters) !== 0 && !$course->getSemClass()['studygroup_mode']) { - $_course['name'] .= ' (' . $course->getFullname('sem-duration-name') . ')'; + if ($show_semester_name && count($course->semesters) !== 1 && !$course->getSemClass()['studygroup_mode']) { + $_course['name'] .= ' (' . $course->getTextualSemester() . ')'; } if ($course->parent_course) { $_course['parent_course'] = $course->parent_course; diff --git a/lib/classes/coursewizardsteps/BasicDataWizardStep.php b/lib/classes/coursewizardsteps/BasicDataWizardStep.php index f9d3c7f..0f0a3a9 100644 --- a/lib/classes/coursewizardsteps/BasicDataWizardStep.php +++ b/lib/classes/coursewizardsteps/BasicDataWizardStep.php @@ -401,8 +401,6 @@ class BasicDataWizardStep implements CourseWizardStep } $course->status = $values['coursetype']; - $course->start_time = $values['start_time']; - $course->duration_time = 0; $course->name = new I18NString($values['name'], $values['name_i18n'] ?? []); $course->veranstaltungsnummer = $values['number']; $course->beschreibung = new I18NString($values['description'], $values['description_i18n'] ?? []); @@ -439,9 +437,7 @@ class BasicDataWizardStep implements CourseWizardStep $institutes = array_merge($institutes, array_keys($values['participating'])); } $seminar->setInstitutes($institutes); - $course->setSemesters([ - Semester::findByTimestamp($values['start_time']) - ]); + $course->start_semester = Semester::findByTimestamp($values['start_time']); if (isset($values['lecturers']) && is_array($values['lecturers'])) { foreach (array_keys($values['lecturers']) as $user_id) { $seminar->addMember($user_id, 'dozent'); diff --git a/lib/classes/searchtypes/StandardSearch.class.php b/lib/classes/searchtypes/StandardSearch.class.php index 539da99..34ae3b2 100644 --- a/lib/classes/searchtypes/StandardSearch.class.php +++ b/lib/classes/searchtypes/StandardSearch.class.php @@ -88,6 +88,7 @@ class StandardSearch extends SQLSearch */ private function getSQL() { + $semester = " CONCAT('(',IFNULL(GROUP_CONCAT(DISTINCT sem1.name ORDER BY sem1.beginn SEPARATOR '-'),'" . _('unbegrenzt') . "'),')')"; switch ($this->search) { case "username": $this->extendedLayout = true; @@ -110,14 +111,10 @@ class StandardSearch extends SQLSearch "OR auth_user_md5.username LIKE :input) AND " . get_vis_query('auth_user_md5', 'search') . " ORDER BY Nachname ASC, Vorname ASC"; case "Seminar_id": - $semester = "CONCAT(' (', - IF(semester_courses.semester_id IS NULL, '" . _('unbegrenzt') . "', - IF(COUNT(DISTINCT semester_courses.semester_id) > 1, CONCAT_WS(' - ', (SELECT start_semester.name FROM `semester_data` AS start_semester WHERE start_semester.semester_id = semester_courses.semester_id ORDER BY `beginn` ASC LIMIT 1), (SELECT end_semester.name FROM `semester_data` AS end_semester WHERE end_semester.semester_id = semester_courses.semester_id ORDER BY `beginn` DESC LIMIT 1)), sem1.name)), - ')')"; - return "SELECT DISTINCT seminare.Seminar_id, CONCAT_WS(' ', seminare.VeranstaltungsNummer, seminare.Name, ".$semester.") " . + return "SELECT seminare.Seminar_id, CONCAT_WS(' ', seminare.VeranstaltungsNummer, seminare.Name, ".$semester.") " . "FROM seminare " . "LEFT JOIN semester_courses ON (semester_courses.course_id = seminare.Seminar_id) " . - "JOIN `semester_data` sem1 ON (seminare.`start_time` = sem1.`beginn`) " . + "LEFT JOIN `semester_data` sem1 ON ON (semester_courses.semester_id = sem1.semester_id) " . "LEFT JOIN seminar_user ON (seminar_user.Seminar_id = seminare.Seminar_id AND seminar_user.status = 'dozent') " . "LEFT JOIN auth_user_md5 ON (auth_user_md5.user_id = seminar_user.user_id) " . "WHERE (seminare.Name LIKE :input " . @@ -129,18 +126,14 @@ class StandardSearch extends SQLSearch "OR seminare.Sonstiges LIKE :input) " . "AND seminare.visible = 1 " . "AND seminare.status NOT IN ('".implode("', '", studygroup_sem_types())."') " . - " ORDER BY sem1.`beginn` DESC, " . + " GROUP BY seminare.seminar_id ORDER BY sem1.`beginn` DESC, " . (Config::get()->IMPORTANT_SEMNUMBER ? "seminare.`VeranstaltungsNummer`, " : "") . "seminare.`Name`"; case "AnySeminar_id": - $semester = "CONCAT(' (', - IF(semester_courses.semester_id IS NULL, '" . _('unbegrenzt') . "', - IF(COUNT(DISTINCT semester_courses.semester_id) > 1, CONCAT_WS(' - ', (SELECT start_semester.name FROM `semester_data` AS start_semester WHERE start_semester.semester_id = semester_courses.semester_id ORDER BY `beginn` ASC LIMIT 1), (SELECT end_semester.name FROM `semester_data` AS end_semester WHERE end_semester.semester_id = semester_courses.semester_id ORDER BY `beginn` DESC LIMIT 1)), sem1.name)), - ')')"; - return "SELECT DISTINCT seminare.Seminar_id, CONCAT_WS(' ', seminare.VeranstaltungsNummer, seminare.Name, ".$semester.") " . + return "SELECT seminare.Seminar_id, CONCAT_WS(' ', seminare.VeranstaltungsNummer, seminare.Name, ".$semester.") " . "FROM seminare " . "LEFT JOIN semester_courses ON (semester_courses.course_id = seminare.Seminar_id) " . - "JOIN `semester_data` sem1 ON (seminare.`start_time` = sem1.`beginn`) " . + "LEFT JOIN `semester_data` sem1 ON (semester_courses.semester_id = sem1.semester_id) " . "LEFT JOIN seminar_user ON (seminar_user.Seminar_id = seminare.Seminar_id AND seminar_user.status = 'dozent') " . "LEFT JOIN auth_user_md5 ON (auth_user_md5.user_id = seminar_user.user_id) " . "WHERE (seminare.Name LIKE :input " . @@ -152,7 +145,7 @@ class StandardSearch extends SQLSearch "OR seminare.Beschreibung LIKE :input " . "OR seminare.Ort LIKE :input " . "OR seminare.Sonstiges LIKE :input) " . - " ORDER BY sem1.`beginn` DESC, " . + " GROUP BY seminare.seminar_id ORDER BY sem1.`beginn` DESC, " . (Config::get()->IMPORTANT_SEMNUMBER ? "seminare.`VeranstaltungsNummer`, " : "") . "seminare.`Name`"; case "Arbeitsgruppe_id": diff --git a/lib/models/Course.class.php b/lib/models/Course.class.php index b078c0c..5a41e02 100644 --- a/lib/models/Course.class.php +++ b/lib/models/Course.class.php @@ -236,10 +236,12 @@ class Course extends SimpleORMap implements Range, PrivacyObject, StudipItem, Fe $config['additional_fields']['end_time'] = true; $config['additional_fields']['start_semester'] = [ - 'get' => 'getStartSemester' + 'get' => 'getStartSemester', + 'set' => '_set_semester' ]; $config['additional_fields']['end_semester'] = [ - 'get' => 'getEndSemester' + 'get' => 'getEndSemester', + 'set' => '_set_semester' ]; $config['additional_fields']['semester_text'] = [ 'get' => 'getTextualSemester' @@ -264,11 +266,8 @@ class Course extends SimpleORMap implements Range, PrivacyObject, StudipItem, Fe $config['i18n_fields']['leistungsnachweis'] = true; $config['i18n_fields']['ort'] = true; - $config['additional_fields']['config']['get'] = function ($course) { - return CourseConfig::get($course->id); - }; - $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(); @@ -285,73 +284,71 @@ class Course extends SimpleORMap implements Range, PrivacyObject, StudipItem, Fe public function getEnd_Time() { - if (!$this->semesters) { - return -1; - } - - return $this->semesters->last()->ende; + return $this->duration_time == -1 ? -1 : $this->start_time + $this->duration_time; } public function setEnd_Time($value) { - throw new Exception("This function is unavailable."); + 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; + } } - /** - * Sets the start semester of the course. - */ - public function setStartSemester(Semester $semester) + public function _set_semester($field, $value) { - $this->start_semester = $semester; + $method = 'set' . ($field === 'start_semester' ? 'StartSemester' : 'EndSemester'); + $this->$method($value); } /** - * Sets the end semester of the course. + * @param Semester $semester */ - public function setEndSemester(Semester $semester) + public function setStartSemester(Semester $semester) { - $this->end_semester = $semester; + $end_semester = $this->semesters->last(); + $start_semester = $this->semesters->first(); + 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); + } } - public function setSemesters($semesters) + /** + * @param Semester|null $semester + */ + public function setEndSemester(?Semester $semester) { - $semester_ids = array_map(function ($s) { - return $s->id; - }, $semesters); - - if (count($semester_ids) > 0) { - $delete = DBManager::get()->prepare(" - DELETE FROM semester_courses - WHERE semester_id NOT IN (:semester_ids) - AND course_id = :course_id - "); - $delete->execute([ - 'semester_ids' => $semester_ids, - 'course_id' => $this->id, - ]); + $start_semester = $this->semesters->first(); + 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 { - $delete = DBManager::get()->prepare(" - DELETE FROM semester_courses - WHERE course_id = :course_id - "); - $delete->execute([ - 'course_id' => $this->id, - ]); - } - $insert = DBManager::get()->prepare(" - INSERT IGNORE INTO semester_courses - SET course_id = :course_id, - semester_id = :semester_id, - mkdate = UNIX_TIMESTAMP(), - chdate = UNIX_TIMESTAMP() - "); - foreach ($semesters as $semester) { - $insert->execute([ - 'course_id' => $this->id, - 'semester_id' => $semester->id, - ]); - } - $this->resetRelation('semesters'); + if ($semester) { + $this->semesters[] = $semester; + } + } } /** @@ -365,7 +362,7 @@ class Course extends SimpleORMap implements Range, PrivacyObject, StudipItem, Fe if (count($this->semesters) > 0) { return $this->semesters->first(); } else { - return Semester::findByTimestamp($this['start_time']); + return Semester::findCurrent(); } } @@ -380,7 +377,6 @@ class Course extends SimpleORMap implements Range, PrivacyObject, StudipItem, Fe if (count($this->semesters) > 0) { return $this->semesters->last(); } - return null; } /** @@ -394,7 +390,7 @@ class Course extends SimpleORMap implements Range, PrivacyObject, StudipItem, Fe } elseif (count($this->semesters) === 1) { return $this->start_semester->name; } else { - return $this->start_semester->name .' - ' . _('unbegrenzt'); + return _('unbegrenzt'); } } @@ -422,14 +418,14 @@ class Course extends SimpleORMap implements Range, PrivacyObject, StudipItem, Fe } return false; } else { - return $this->start_time <= $semester->beginn; + return true; } } public function getFreeSeats() { $free_seats = $this->admission_turnout - $this->getNumParticipants(); - return max($free_seats, 0);; + return max($free_seats, 0); } public function isWaitlistAvailable() @@ -551,10 +547,7 @@ class Course extends SimpleORMap implements Range, PrivacyObject, StudipItem, Fe $data[0] = $this->name; $data[1] = $sem_type['name']; $data[2] = $this->veranstaltungsnummer; - $data[3] = $this->start_semester->name; - if ($this->start_semester !== $this->end_semester && !$this->isStudygroup()) { - $data[3] .= ' - ' . ($this->end_semester ? $this->end_semester->name : _('unbegrenzt')); - } + $data[3] = $this->getTextualSemester(); return trim(vsprintf($template[$format], array_map('trim', $data))); } @@ -564,9 +557,9 @@ class Course extends SimpleORMap implements Range, PrivacyObject, StudipItem, Fe * The dates can be filtered by an optional time range. By default, * all dates are retrieved. * - * @param $range_begin The begin timestamp of the time range. + * @param int $range_begin The begin timestamp of the time range. * - * @param $range_end The end 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. @@ -595,7 +588,7 @@ class Course extends SimpleORMap implements Range, PrivacyObject, StudipItem, Fe /** * Sets this courses study areas to the given values. * - * @param $ids the new study areas + * @param array $ids the new study areas * @return bool Changes successfully saved? */ public function setStudyAreas($ids) @@ -751,9 +744,13 @@ class Course extends SimpleORMap implements Range, PrivacyObject, StudipItem, Fe */ protected function logStore() { - if ($this->isFieldDirty('start_semester')) { + if ($this->isFieldDirty('start_time')) { //Log change of start semester: - StudipLog::log('SEM_SET_STARTSEMESTER', $this->id, $this->start_semester->beginn); + 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); } @@ -805,6 +802,27 @@ class Course extends SimpleORMap implements Range, PrivacyObject, StudipItem, Fe } } + /** + * 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; + $this->duration_time = -1; + } else { + $this->start_time = $this->getStartSemester()->beginn; + $this->duration_time = $this->getEndSemester()->beginn - $this->start_time; + } + } + //StudipItem interface implementation: diff --git a/lib/models/Semester.class.php b/lib/models/Semester.class.php index b2b7f31..2652de8 100644 --- a/lib/models/Semester.class.php +++ b/lib/models/Semester.class.php @@ -349,23 +349,15 @@ class Semester extends SimpleORMap /** * Returns the start week dates for this semester (and other - * semesters if duration is > 0). + * semesters if $end_semester is given). * - * @param mixed $duration Duration time (false to restrict to current - * semester, -1 for indefinite duration, otherwise - * the int value for the duration so that - * semester start + duration = end) + * @param Semester $end_semester end semester, default is $this * @return array containing the start weeks */ - public function getStartWeeks($duration = false) + public function getStartWeeks(?Semester $end_semester = null) { - if ($duration === false) { + if (!$end_semester) { $end_semester = $this; - } elseif ($duration == -1) { - $semesters = self::getAll(); - $end_semester = end($semesters); - } else { - $end_semester = self::findByTimestamp((int)$this->beginn + (int)$duration); } $timestamp = $this->getCorrectedLectureBegin(); |
