aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRasmus Fuhse <fuhse@data-quest.de>2022-03-31 14:17:41 +0000
committerAndré Noack <noack@data-quest.de>2022-03-31 14:17:41 +0000
commitb7802baa589843f44f5cbed5a04dd522bd54daa0 (patch)
tree5129c94b428c3b1dbf9aaccc12b64e38b3d6bff7 /lib
parent8073d9c7cb2e8e187cbfb776b865ec9ba2623c25 (diff)
Resolve "Unbegrenzte Veranstaltungen haben Startzeitpunkt!"
Diffstat (limited to 'lib')
-rw-r--r--lib/classes/AdminCourseFilter.class.php2
-rw-r--r--lib/classes/MyRealmModel.php4
-rw-r--r--lib/classes/coursewizardsteps/BasicDataWizardStep.php6
-rw-r--r--lib/classes/searchtypes/StandardSearch.class.php21
-rw-r--r--lib/models/Course.class.php160
-rw-r--r--lib/models/Semester.class.php16
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();