diff --git a/app/controllers/admin/courseplanning.php b/app/controllers/admin/courseplanning.php index 2271acfdbac096aafd6fd642d9b129f705365532..9e508a57d4f1f23749814c1146a951dfa35e96cc 100644 --- a/app/controllers/admin/courseplanning.php +++ b/app/controllers/admin/courseplanning.php @@ -345,12 +345,11 @@ class Admin_CourseplanningController extends AuthenticatedController $end_date->setTimezone(new DateTimeZone('UTC')); $course = Course::find($course_id); - $this->seminar = new Seminar($course); - if ($course->isOpenEnded() || count($course->semesters) > 1) { // course over more than one semester - $start_weeks = $this->seminar->end_semester->getStartWeeks(); - $sem_duration = $this->semester->ende - $this->semester->beginn; - $sem_weeks = $this->semester->getStartWeeks($sem_duration); + if (count($course->semesters) > 1) { // course over more than one semester + $start_weeks = $course->start_semester->getStartWeeks($course->end_semester); + + $sem_weeks = $this->semester->getStartWeeks(); $sem_weeks_start = explode(' Semesterwoche ', $sem_weeks[0]); $sem_weeks_end = explode(' Semesterwoche ', end($sem_weeks)); diff --git a/app/controllers/admin/user.php b/app/controllers/admin/user.php index c8683040723f1a94ad47b8086219272bd4461035..331722624ba7fd3a99192307ca187ec5f3d4f883 100644 --- a/app/controllers/admin/user.php +++ b/app/controllers/admin/user.php @@ -1239,7 +1239,9 @@ class Admin_UserController extends AuthenticatedController $memberships = DBManager::get()->fetchAll("SELECT seminar_user.*, seminare.Name as course_name FROM seminar_user LEFT JOIN seminare USING (seminar_id) - WHERE user_id = ? ORDER BY seminare.start_time DESC, seminare.Name", + LEFT JOIN semester_courses ON (seminare.Seminar_id = semester_courses.course_id) + LEFT JOIN semester_data ON (semester_data.semester_id = semester_courses.semester_id) + WHERE user_id = ? GROUP BY seminare.Seminar_id ORDER BY MAX(semester_data.beginn) DESC, seminare.Name", [$user_id], 'CourseMember::buildExisting'); @@ -1249,6 +1251,7 @@ class Admin_UserController extends AuthenticatedController $this->sections = []; foreach ($memberships as $membership) { + $semester_name = $membership->course->isOpenEnded() ? _('unbegrenzt') : $membership->course->start_semester->name; if (!Request::get('view') || Request::get('view') === 'files') { // count files for course @@ -1259,9 +1262,9 @@ class Admin_UserController extends AuthenticatedController if ($count) { if (!isset($course_files[$membership->seminar_id])) { - $course_files[(string) $membership->course->start_semester->name][$membership->course->id]['course'] = $membership->course; + $course_files[$semester_name][$membership->course->id]['course'] = $membership->course; } - $course_files[(string) $membership->course->start_semester->name][$membership->course->id]['files'] = $count; + $course_files[$semester_name][$membership->course->id]['files'] = $count; } } if (in_array(Request::get('view'), words('courses closed_courses'))) { @@ -1272,9 +1275,9 @@ class Admin_UserController extends AuthenticatedController WHERE sc.seminar_id =?', [$membership->seminar_id]); if ((int)$closed_course) { - $closed_courses[(string) $membership->course->start_semester->name][$membership->course->id] = $membership; + $closed_courses[$semester_name][$membership->course->id] = $membership; } else { - $courses[(string) $membership->course->start_semester->name][$membership->course->id] = $membership; + $courses[$semester_name][$membership->course->id] = $membership; } } } diff --git a/app/controllers/admission/restricted_courses.php b/app/controllers/admission/restricted_courses.php index ccf89aaaa7d444b862addaf0806024e61e30b2c8..5ae3a38add7fe9409ce87192b718d2e6728c8d88 100644 --- a/app/controllers/admission/restricted_courses.php +++ b/app/controllers/admission/restricted_courses.php @@ -56,7 +56,6 @@ class Admission_RestrictedCoursesController extends AuthenticatedController } $semester = Semester::find($this->current_semester_id); $sem_condition .= " - AND seminare.start_time <=" . (int)$semester["beginn"]." AND (semester_courses.semester_id IS NULL OR semester_courses.semester_id = " . DBManager::get()->quote($semester->getId()) . ") "; if ($this->sem_name_prefix) { diff --git a/app/controllers/blubber.php b/app/controllers/blubber.php index 7f45ea8894d46a43adfbcb0f49eb9c1163627c44..35a8d7e573d2dd3d8467d6642b47bb009649cb80 100644 --- a/app/controllers/blubber.php +++ b/app/controllers/blubber.php @@ -406,7 +406,6 @@ class BlubberController extends AuthenticatedController $course = new Course(); $course['name'] = Request::get('name'); $course['status'] = array_shift($studgroup_sem_types); - $course['start_time'] = Semester::findCurrent()->beginn; $course->store(); if ($_FILES['avatar'] && $_FILES['avatar']['error'] !== UPLOAD_ERR_NO_FILE) { diff --git a/app/controllers/course/timesrooms.php b/app/controllers/course/timesrooms.php index 7cad46c32fd59b633422ae8f79f0f5e1b4bcdc38..9e835ca64bc06c81813177284d20901b1ac96e48 100644 --- a/app/controllers/course/timesrooms.php +++ b/app/controllers/course/timesrooms.php @@ -74,10 +74,11 @@ class Course_TimesroomsController extends AuthenticatedController $this->course->applyTimeFilter($semester['beginn'], $semester['ende']); } - $selectable_semesters = new SimpleCollection(Semester::getAll()); - $start = $this->course->start_time; - $end = $this->course->getEndSemester()->ende; - $selectable_semesters = $selectable_semesters->findBy('beginn', [$start, $end], '>=<=')->toArray(); + if ($this->course->isOpenEnded()) { + $selectable_semesters = Semester::getAll(); + } else { + $selectable_semesters = $this->course->semesters->toArray(); + } if (count($selectable_semesters) > 1 || (count($selectable_semesters) == 1 && $this->course->hasDatesOutOfDuration())) { $selectable_semesters[] = ['name' => _('Alle Semester'), 'semester_id' => 'all']; } @@ -247,11 +248,12 @@ class Course_TimesroomsController extends AuthenticatedController if ($end_semester != 0 && $end_semester != -1 && $start_semester->beginn >= $end_semester->beginn) { PageLayout::postError(_('Das Startsemester liegt nach dem Endsemester!')); } else { + $old_start_weeks = !$course->isOpenEnded() ? $course->start_semester->getStartWeeks($course->end_semester) : []; //set the new semester array: if ($end_semester == -1) { - $course->setSemesters([]); + $course->semesters = []; } elseif($end_semester == 0) { - $course->setSemesters([$start_semester]); + $course->semesters = [$start_semester]; } else { $selected_semesters = []; foreach (Semester::getAll() as $sem) { @@ -259,29 +261,23 @@ class Course_TimesroomsController extends AuthenticatedController $selected_semesters[] = $sem; } } - $course->setSemesters($selected_semesters); + $course->semesters = $selected_semesters; } - //deprecated: this is the old way - $course['start_time'] = $start_semester['beginn']; - $course['duration_time'] = $end_semester <= 0 - ? $end_semester - : $end_semester['ende'] - $start_semester['beginn']; - - $old_start_weeks = $course->end_semester ? $course->end_semester->getStartWeeks() : []; // set the semester-chooser to the first semester $this->course->setFilter($course->getStartSemester()); $this->semester_filter = $start_semester->semester_id; $course->store(); - - $new_start_weeks = $course->start_semester->getStartWeeks(); - SeminarCycleDate::removeOutRangedSingleDates($this->course->getStartSemester(), $this->course->getEndSemesterVorlesEnde(), $course->id); - $cycles = SeminarCycleDate::findBySeminar_id($course->id); - foreach ($cycles as $cycle) { - $cycle->end_offset = $this->getNewEndOffset($cycle, $old_start_weeks, $new_start_weeks); - $cycle->generateNewDates(); - $cycle->store(); + if (!$course->isOpenEnded()) { + $new_start_weeks = $course->start_semester->getStartWeeks($course->end_semester); + SeminarCycleDate::removeOutRangedSingleDates($this->course->getStartSemester(), $this->course->getEndSemesterVorlesEnde(), $course->id); + $cycles = SeminarCycleDate::findBySeminar_id($course->id); + foreach ($cycles as $cycle) { + $cycle->end_offset = $this->getNewEndOffset($cycle, $old_start_weeks, $new_start_weeks); + $cycle->generateNewDates(); + $cycle->store(); + } } $messages = $this->course->getStackedMessages(); @@ -1050,20 +1046,18 @@ class Course_TimesroomsController extends AuthenticatedController } if ($this->course->isOpenEnded()) { // course with endless lifespan - $end_semester = Semester::findBySQL("beginn >= ? ORDER BY beginn", [$this->course->start_time]); - } else { // course over more than one semester - $end_semester = $this->course->semesters; + $end_semester = array_values(array_filter(Semester::getAll(), function ($s) {return $s->past === false;})); + } else { // course over one or more semester + $end_semester = $this->course->semesters->getArrayCopy(); } - - $this->start_weeks = $end_semester[count($end_semester) - 1]->getStartWeeks(); - + $this->start_weeks = []; + $this->end_semester_weeks = []; if (!empty($end_semester)) { - $this->end_semester_weeks = []; + $this->start_weeks = $end_semester[0]->getStartWeeks($end_semester[count($end_semester) - 1]); foreach ($end_semester as $sem) { - $sem_duration = $sem->ende - $sem->beginn; - $weeks = $sem->getStartWeeks($sem_duration); + $weeks = $sem->getStartWeeks(); foreach ($this->start_weeks as $key => $week) { if (mb_strpos($week, mb_substr($weeks[0], -15)) !== false) { diff --git a/app/controllers/course/topics.php b/app/controllers/course/topics.php index 3636c12c3b44bccc554eef7c3e70e2e61681e92a..96a238ab4a4a03f435b0d8e68f9bb56eaa2e4313 100644 --- a/app/controllers/course/topics.php +++ b/app/controllers/course/topics.php @@ -156,9 +156,10 @@ class Course_TopicsController extends AuthenticatedController PageLayout::postMessage(MessageBox::success(sprintf(_("%s Themen kopiert."), count(Request::getArray("topic"))))); $this->redirect("course/topics"); } + $semester_sql = " CONCAT('(',IFNULL(GROUP_CONCAT(DISTINCT semester_data.name ORDER BY semester_data.beginn SEPARATOR '-'),'" . _('unbegrenzt') . "'),')')"; if ($GLOBALS['perm']->have_perm("root")) { $this->courseSearch = new SQLSearch(" - SELECT seminare.Seminar_id, CONCAT_WS(' ', seminare.VeranstaltungsNummer, seminare.name, '(', IF(semester_courses.semester_id IS NULL, GROUP_CONCAT(', ', semester_data.name), 'unbegrenzt'), ') (', COUNT(issue_id), ')') + SELECT seminare.Seminar_id, CONCAT_WS(' ', seminare.VeranstaltungsNummer, seminare.name, $semester_sql, '(', COUNT(issue_id), ')') FROM seminare LEFT JOIN semester_courses ON (seminare.Seminar_id = semester_courses.course_id) LEFT JOIN semester_data ON (semester_data.semester_id = semester_courses.semester_id) @@ -172,7 +173,7 @@ class Course_TopicsController extends AuthenticatedController ); } elseif ($GLOBALS['perm']->have_perm("admin")) { $this->courseSearch = new SQLSearch(" - SELECT seminare.Seminar_id, CONCAT_WS(' ', seminare.VeranstaltungsNummer, seminare.name, '(', CONCAT_WS(' ', seminare.VeranstaltungsNummer, seminare.name, '(', IF(semester_courses.semester_id IS NULL, GROUP_CONCAT(', ', semester_data.name), 'unbegrenzt'), ') (', COUNT(issue_id), ')') + SELECT seminare.Seminar_id, CONCAT_WS(' ', seminare.VeranstaltungsNummer, seminare.name, $semester_sql, '(', COUNT(issue_id), ')') FROM seminare INNER JOIN seminar_inst ON (seminare.Seminar_id = seminar_inst.seminar_id) INNER JOIN user_inst ON (user_inst.Institut_id = seminar_inst.institut_id) @@ -191,7 +192,7 @@ class Course_TopicsController extends AuthenticatedController ); } else { $this->courseSearch = new SQLSearch(" - SELECT seminare.Seminar_id, CONCAT_WS(' ', seminare.VeranstaltungsNummer, seminare.name, '(', IF(semester_courses.semester_id IS NULL, GROUP_CONCAT(', ', semester_data.name), 'unbegrenzt'), ') (', COUNT(issue_id), ')') + SELECT seminare.Seminar_id, CONCAT_WS(' ', seminare.VeranstaltungsNummer, seminare.name, $semester_sql, '(', COUNT(issue_id), ')') FROM seminare INNER JOIN seminar_user ON (seminare.Seminar_id = seminar_user.Seminar_id) LEFT JOIN semester_courses ON (seminare.Seminar_id = semester_courses.course_id) diff --git a/app/controllers/file.php b/app/controllers/file.php index 47945f312875c42395b9cc3a795b7543f3a87fae..051f05d8195e6990d30e388a3a4b1c9626ecb9d2 100644 --- a/app/controllers/file.php +++ b/app/controllers/file.php @@ -739,23 +739,25 @@ class FileController extends AuthenticatedController $this->plugin = Request::get('from_plugin'); if (!$GLOBALS['perm']->have_perm("admin")) { - $query = "SELECT seminare.*, COUNT(semester_courses.semester_id) AS semesters + $query = "SELECT seminare.*, MAX(`beginn`) as sorter FROM seminare INNER JOIN seminar_user ON (seminar_user.Seminar_id = seminare.Seminar_id) LEFT JOIN semester_courses ON (semester_courses.course_id = seminare.Seminar_id) + LEFT JOIN semester_data ON (semester_courses.semester_id = semester_data.semester_id) WHERE seminar_user.user_id = :user_id GROUP BY seminare.Seminar_id "; if (Config::get()->DEPUTIES_ENABLE) { $query .= " UNION - SELECT `seminare`.*, COUNT(semester_courses.semester_id) AS semesters + SELECT `seminare`.*, MAX(`beginn`) as sorter FROM `seminare` INNER JOIN `deputies` ON (`deputies`.`range_id` = `seminare`.`Seminar_id`) LEFT JOIN semester_courses ON (semester_courses.course_id = seminare.Seminar_id) + LEFT JOIN semester_data ON (semester_courses.semester_id = semester_data.semester_id) WHERE `deputies`.`user_id` = :user_id GROUP BY seminare.Seminar_id"; } - $query .= " ORDER BY semesters = 0 DESC, start_time DESC, Name ASC"; + $query .= " ORDER BY sorter DESC, Name ASC"; $statement = DBManager::get()->prepare($query); $statement->execute([':user_id' => $GLOBALS['user']->id]); $this->courses = []; @@ -1255,22 +1257,24 @@ class FileController extends AuthenticatedController $this->folder_id = $folder_id; $this->plugin = Request::get('to_plugin'); if (!$GLOBALS['perm']->have_perm('admin')) { - $query = "SELECT seminare.*, COUNT(semester_courses.semester_id) AS semesters + $query = "SELECT seminare.*, MAX(semester_data.`beginn`) as sorter FROM seminare INNER JOIN seminar_user ON (seminar_user.Seminar_id = seminare.Seminar_id) LEFT JOIN semester_courses ON (semester_courses.course_id = seminare.Seminar_id) + LEFT JOIN semester_data ON (semester_courses.semester_id = semester_data.semester_id) WHERE seminar_user.user_id = :user_id GROUP BY seminare.Seminar_id"; if (Config::get()->DEPUTIES_ENABLE) { $query .= " UNION - SELECT `seminare`.*, COUNT(semester_courses.semester_id) AS semesters + SELECT `seminare`.*, MAX(semester_data.`beginn`) as sorter FROM `seminare` INNER JOIN `deputies` ON (`deputies`.`range_id` = `seminare`.`Seminar_id`) LEFT JOIN semester_courses ON (semester_courses.course_id = seminare.Seminar_id) + LEFT JOIN semester_data ON (semester_courses.semester_id = semester_data.semester_id) WHERE `deputies`.`user_id` = :user_id GROUP BY seminare.Seminar_id"; } - $query .= " ORDER BY semesters = 0 DESC, start_time DESC, Name ASC"; + $query .= " ORDER BY sorter DESC, Name ASC"; $statement = DBManager::get()->prepare($query); $statement->execute(['user_id' => $GLOBALS['user']->id]); diff --git a/app/controllers/news.php b/app/controllers/news.php index e60e174f634fa99c5b76e61c01bee80bdf730e55..81e832edb243ed0c3d69affac57e8db5f5a3de60 100644 --- a/app/controllers/news.php +++ b/app/controllers/news.php @@ -709,7 +709,6 @@ class NewsController extends StudipController LEFT JOIN semester_courses ON (semester_courses.course_id = seminar_user.Seminar_id) WHERE seminar_user.user_id = :user_id AND seminar_user.status IN('tutor', 'dozent') - AND seminare.start_time <= :start AND (semester_courses.semester_id = :semester_id OR semester_courses.semester_id IS NULL) "; if (Config::get()->DEPUTIES_ENABLE) { @@ -719,13 +718,11 @@ class NewsController extends StudipController LEFT JOIN seminare ON (deputies.range_id=seminare.Seminar_id) LEFT JOIN semester_courses ON (semester_courses.course_id = deputies.range_id) WHERE deputies.user_id = :user_id - AND seminare.start_time <= :start AND (semester_courses.semester_id = :semester_id OR semester_courses.semester_id IS NULL)"; } $query .= " ORDER BY sem_name ASC"; $statement = DBManager::get()->prepare($query); $statement->bindValue(':user_id', $GLOBALS['user']->id); - $statement->bindValue(':start', $current_semester->beginn); $statement->bindValue(':semester_id', $current_semester->semester_id); $statement->execute(); $seminars = $statement->fetchAll(PDO::FETCH_ASSOC); @@ -744,7 +741,6 @@ class NewsController extends StudipController LEFT JOIN semester_courses ON (semester_courses.course_id = seminar_user.Seminar_id) WHERE seminar_user.user_id = :user_id AND seminar_user.status IN('tutor', 'dozent') - AND seminare.start_time <= :start AND (semester_courses.semester_id = :semester_id OR semester_courses.semester_id IS NULL)"; if (Config::get()->DEPUTIES_ENABLE) { $query .= " UNION SELECT CONCAT(seminare.Name, ' ["._("Vertretung")."]') AS sem_name, seminare.Seminar_id, @@ -753,13 +749,11 @@ class NewsController extends StudipController LEFT JOIN seminare ON (deputies.range_id=seminare.Seminar_id) LEFT JOIN semester_courses ON (semester_courses.course_id = deputies.range_id) WHERE deputies.user_id = :user_id - AND seminare.start_time <= :start AND (semester_courses.semester_id = :semester_id OR semester_courses.semester_id IS NULL)"; } $query .= " ORDER BY sem_name ASC"; $statement = DBManager::get()->prepare($query); $statement->bindValue(':user_id', $GLOBALS['user']->id); - $statement->bindValue(':start', $next_semester->beginn); $statement->bindValue(':semester_id', $next_semester->semester_id); $statement->execute(); $seminars = $statement->fetchAll(PDO::FETCH_ASSOC); diff --git a/app/controllers/questionnaire.php b/app/controllers/questionnaire.php index 895dd16743eb5c5e635cc82ba1e11212874776a6..bab22ab91405eac201617cd07f8e13c3b82a9df5 100644 --- a/app/controllers/questionnaire.php +++ b/app/controllers/questionnaire.php @@ -710,9 +710,9 @@ class QuestionnaireController extends AuthenticatedController //Search courses matching the search criteria: - $sql = 'start_time = :semester_begin '; + $sql = 'LEFT JOIN semester_courses ON (semester_courses.course_id = seminare.Seminar_id) WHERE (semester_courses.semester_id = :semester_id OR semester_courses.semester_id IS NULL) '; $sql_array = [ - 'semester_begin' => $this->semester->beginn + 'semester_id' => $this->semester->id ]; if ($this->institute) { diff --git a/app/controllers/shared/modul.php b/app/controllers/shared/modul.php index cd2e96be954f8272e29f580db4ec478eb01389bd..55644db11b2fb7cc27f5227661423a51e8e62c4b 100644 --- a/app/controllers/shared/modul.php +++ b/app/controllers/shared/modul.php @@ -156,13 +156,13 @@ class Shared_ModulController extends AuthenticatedController $stm = DBManager::get()->prepare('SELECT DISTINCT auth_user_md5.username FROM auth_user_md5 JOIN seminar_user ON (auth_user_md5.user_id = seminar_user.user_id) JOIN seminare ON (seminare.seminar_id = seminar_user.seminar_id) - JOIN semester_data ON (seminare.start_time = semester_data.beginn) + LEFT JOIN semester_courses ON (seminare.seminar_id = semester_courses.course_id) JOIN mvv_lvgruppe_seminar ON (mvv_lvgruppe_seminar.seminar_id = seminare.seminar_id) JOIN mvv_lvgruppe_modulteil ON (mvv_lvgruppe_modulteil.lvgruppe_id = mvv_lvgruppe_seminar.lvgruppe_id) JOIN mvv_modulteil ON (mvv_modulteil.modulteil_id = mvv_lvgruppe_modulteil.modulteil_id) WHERE mvv_modulteil.modul_id = :modul_id AND seminar_user.status = :status - AND semester_data.semester_id = :semester_id'); + AND (semester_courses.semester_id = :semester_id OR semester_courses.semester_id IS NULL)'); $stm->execute(['modul_id' => $modul_id, 'status' => 'autor', ':semester_id' => $semester_id]); $_SESSION['sms_data']['p_rec'] = $stm->fetchFirst(); diff --git a/app/routes/Course.php b/app/routes/Course.php index cffdb0b3c9df88a6c18895c41db9933364822719..bb2f32ff3e06dc0178366c6a6ea529b74152fdcb 100644 --- a/app/routes/Course.php +++ b/app/routes/Course.php @@ -136,12 +136,8 @@ class Course extends \RESTAPI\RouteMap if ($semester) { $memberships = $memberships->filter(function ($m) use ($semester) { - $course = $m->course; - return - $course->start_time == $semester->beginn - || ($course->start_time <= $semester->beginn - && ($course->isOpenEnded() || $semester->beginn <= $course->end_time)); - }); + return $m->course->isInSemester($semester); + }); } return $memberships; diff --git a/app/views/file/choose_file_from_course.php b/app/views/file/choose_file_from_course.php index a0184975114a882c3ed8d6779b8031387c9d595c..ad2ba266ef5115527bb3e1ade7aa7ab76db39b80 100644 --- a/app/views/file/choose_file_from_course.php +++ b/app/views/file/choose_file_from_course.php @@ -44,7 +44,7 @@ if (Request::get('range_type')) { </a> </td> <td> - <?= htmlReady($course->start_semester->name) ?> + <?= htmlReady($course->getTextualSemester()) ?> </td> <td class="actions"> <a href="<?= $controller->link_for('file/choose_file_from_course/' . $folder_id, array_merge($options, ['course_id' => $course->id])) ?>" data-dialog> diff --git a/app/views/file/choose_folder_from_course.php b/app/views/file/choose_folder_from_course.php index 375c2c4c514804e1a541d44ba701ae3bfbb96d21..3496e5b922c782642cc5da6cb0e5658d39e499fd 100644 --- a/app/views/file/choose_folder_from_course.php +++ b/app/views/file/choose_folder_from_course.php @@ -53,7 +53,7 @@ jQuery(function ($) { </button> </td> <td> - <?= htmlReady($course->start_semester->name) ?> + <?= htmlReady($course->getTextualSemester()) ?> </td> </tr> <? endforeach; ?> diff --git a/lib/classes/AdminCourseFilter.class.php b/lib/classes/AdminCourseFilter.class.php index ea0de9a32d51c0385d934b0d7dcdfd5f28e8df9b..6fa47242e98fd72777c76ae1375f9046ab3b7f17 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 570338926f3661c2e37e8010cbb166ab8773eb10..a68a0c1ac5ff6b2055fdfe894cff1f606aeab738 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 f9d3c7f6fe6fc51f90da607f02a99b99999d89dc..0f0a3a91e008ded4c2823e9545d01317e634230e 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 539da99303fdaf404266674650fb6ec57dbe718d..34ae3b246cf119bc253d109bb9f88def3b092e58 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 b078c0ca2a875ce49cc88741671545095b972198..5a41e02adc524644b247c264598c1df30e02a117 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 b2b7f31a864d22683d39d99045ed32fa5d871641..2652de837840d634b394d407ef6c0046ecd0885e 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();