diff options
| author | Philipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de> | 2024-09-24 10:53:31 +0200 |
|---|---|---|
| committer | Philipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de> | 2024-09-24 10:53:31 +0200 |
| commit | 4459dd7917f4d1c34f40bb68f0e991e9c3d53e4c (patch) | |
| tree | 5c07151ae61276d334e88f6309c30d439a85c12e /lib/classes/Seminar.class.php | |
| parent | da0022e5c1abbf9825ae76debaabdff7e8623bb4 (diff) | |
| parent | 97a188592c679890a25c37ab78463add76a52ff7 (diff) | |
Merge branch 'main' into issue-3911issue-3911
Diffstat (limited to 'lib/classes/Seminar.class.php')
| -rw-r--r-- | lib/classes/Seminar.class.php | 2439 |
1 files changed, 0 insertions, 2439 deletions
diff --git a/lib/classes/Seminar.class.php b/lib/classes/Seminar.class.php deleted file mode 100644 index 054c337..0000000 --- a/lib/classes/Seminar.class.php +++ /dev/null @@ -1,2439 +0,0 @@ -<? -# Lifter002: TODO -# Lifter003: TEST -# Lifter007: TODO -# Lifter010: TODO -/** - * Seminar.class.php - This class represents a Seminar in Stud.IP - * - * This class provides functions for seminar-members, seminar-dates, and seminar-modules - * - * 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 Till Glöggler <tgloeggl@uni-osnabrueck.de> - * @author Stefan Suchi <suchi@data-quest> - * @author Suchi & Berg GmbH <info@data-quest.de> - * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 - * @category Stud.IP - */ - -require_once 'lib/dates.inc.php'; - -class Seminar -{ - var $issues = null; // Array of Issue - var $irregularSingleDates = null; // Array of SingleDates - var $messages = []; // occured errors, infos, and warnings - var $semester = null; - var $filterStart = 0; - var $filterEnd = 0; - var $hasDatesOutOfDuration = -1; - var $message_stack = []; - - var $user_number = 0;//? - var $commands; //? - var $BookedRoomsStatTemp; //??? - - var $request_id;//TODO - var $requestData; - var $room_request; - - private $_metadate = null; // MetaDate - - private $alias = [ - 'seminar_number' => 'VeranstaltungsNummer', - 'subtitle' => 'Untertitel', - 'description' => 'Beschreibung', - 'location' => 'Ort', - 'misc' => 'Sonstiges', - 'read_level' => 'Lesezugriff', - 'write_level' => 'Schreibzugriff', - 'semester_start_time' => 'start_time', - 'semester_duration_time' => 'duration_time', - 'form' => 'art', - 'participants' => 'teilnehmer', - 'requirements' => 'vorrausetzungen', - 'orga' => 'lernorga', - ]; - - private $course = null; - - private $course_set = null; - - private static $seminar_object_pool; - - public static function GetInstance($id = false, $refresh_cache = false) - { - if ($id) { - if ($refresh_cache) { - self::$seminar_object_pool[$id] = null; - } - if (!empty(self::$seminar_object_pool[$id]) && is_object(self::$seminar_object_pool[$id]) && self::$seminar_object_pool[$id]->getId() == $id) { - return self::$seminar_object_pool[$id]; - } else { - self::$seminar_object_pool[$id] = new Seminar($id); - return self::$seminar_object_pool[$id]; - } - } else { - return new Seminar(false); - } - } - - public static function setInstance(Seminar $seminar) - { - return self::$seminar_object_pool[$seminar->id] = $seminar; - } - - /** - * Constructor - * - * Pass nothing to create a seminar, or the seminar_id from an existing seminar to change or delete - * @access public - * @param string $seminar_id the seminar to be retrieved - */ - public function __construct($course_or_id = FALSE) - { - $course = Course::toObject($course_or_id); - if ($course) { - $this->course = $course; - } elseif ($course_or_id === false) { - $this->course = new Course(); - $this->course->setId($this->course->getNewId()); - } else { //hmhmhm - throw new Exception(sprintf(_('Fehler: Konnte das Seminar mit der ID %s nicht finden!'), $course_or_id)); - } - } - - public function __get($field) - { - if ($field == 'is_new') { - return $this->course->isNew(); - } - if ($field == 'metadate') { - if ($this->_metadate === null) { - $this->_metadate = new MetaDate($this->id); - $this->_metadate->setSeminarStartTime($this->start_time); - $this->_metadate->setSeminarDurationTime($this->duration_time); - } - return $this->_metadate; - } - if(isset($this->alias[$field])) { - $field = $this->alias[$field]; - } - return $this->course->$field; - } - - public function __set($field, $value) - { - if(isset($this->alias[$field])) { - $field = $this->alias[$field]; - } - if ($field == 'metadate') { - return $this->_metadate = $value; - } - return $this->course->$field = $value; - } - - public function __isset($field) - { - if ($field == 'metadate') { - return is_object($this->_metadate); - } - if(isset($this->alias[$field])) { - $field = $this->alias[$field]; - } - return isset($this->course->$field); - } - - public function __call($method, $params) - { - return call_user_func_array([$this->course, $method], $params); - } - - public static function GetSemIdByDateId($date_id) - { - $stmt = DBManager::get()->prepare("SELECT range_id FROM termine WHERE termin_id = ? LIMIT 1"); - $stmt->execute([$date_id]); - return $stmt->fetchColumn(); - } - - /** - * - * creates an new id for this object - * @access private - * @return string the unique id - */ - public function createId() - { - return $this->course->getNewId(); - } - - public function getMembers($status = 'dozent') - { - $ret = []; - foreach($this->course->getMembersWithStatus($status) as $m) { - $ret[$m->user_id]['user_id'] = $m->user_id; - $ret[$m->user_id]['username'] = $m->username; - $ret[$m->user_id]['Vorname'] = $m->vorname; - $ret[$m->user_id]['Nachname'] = $m->nachname; - $ret[$m->user_id]['Email'] = $m->email; - $ret[$m->user_id]['position'] = $m->position; - $ret[$m->user_id]['label'] = $m->label; - $ret[$m->user_id]['status'] = $m->status; - $ret[$m->user_id]['mkdate'] = $m->mkdate; - $ret[$m->user_id]['fullname'] = $m->getUserFullname(); - } - return $ret; - } - - public function getAdmissionMembers($status = 'awaiting') - { - $ret = []; - foreach($this->course->admission_applicants->findBy('status', $status)->orderBy('position nachname') as $m) { - $ret[$m->user_id]['user_id'] = $m->user_id; - $ret[$m->user_id]['username'] = $m->username; - $ret[$m->user_id]['Vorname'] = $m->vorname; - $ret[$m->user_id]['Nachname'] = $m->nachname; - $ret[$m->user_id]['Email'] = $m->email; - $ret[$m->user_id]['position'] = $m->position; - $ret[$m->user_id]['status'] = $m->status; - $ret[$m->user_id]['mkdate'] = $m->mkdate; - $ret[$m->user_id]['fullname'] = $m->getUserFullname(); - } - return $ret; - } - - public function getId() - { - return $this->id; - } - - public function getName() - { - return $this->name; - } - - /** - * return the field VeranstaltungsNummer for the seminar - * - * @return string the seminar-number for the current seminar - */ - public function getNumber() - { - return $this->seminar_number; - } - - public function isVisible() - { - return $this->visible; - } - - public function getInstitutId() - { - return $this->institut_id; - } - - public function getSemesterStartTime() - { - return $this->semester_start_time; - } - - public function getSemesterDurationTime() - { - return $this->semester_duration_time; - } - - public function getNextDate($return_mode = 'string') - { - $next_date = ''; - if ($return_mode == 'int') { - echo __class__.'::'.__function__.', line '.__line__.', return_mode "int" ist not supported by this function!';die; - } - - if (!$termine = SeminarDB::getNextDate($this->id)) - return false; - - foreach ($termine['termin'] as $singledate_id) { - $next_date .= DateFormatter::formatDateAndRoom($singledate_id, $return_mode) . '<br>'; - } - - if (!empty($termine['ex_termin'])) { - foreach ($termine['ex_termin'] as $ex_termin_id) { - $ex_termin = new SingleDate($ex_termin_id); - $template = $GLOBALS['template_factory']->open('dates/missing_date.php'); - $template->formatted_date = DateFormatter::formatDateAndRoom($ex_termin_id, $return_mode); - $template->ex_termin = $ex_termin; - $missing_date = $template->render(); - - if (!empty($termine['termin'])) { - $termin = new SingleDate($termine['termin'][0]); - if ($ex_termin->getStartTime() <= $termin->getStartTime()) { - return $next_date . $missing_date; - } else { - return $next_date; - } - } else { - return $missing_date; - } - } - } else { - return $next_date; - } - - return false; - } - - public function getFirstDate($return_mode = 'string') { - if (!$dates = SeminarDB::getFirstDate($this->id)) { - return false; - } - - return DateFormatter::formatDateWithAllRooms(['termin' => $dates], $return_mode); - } - - /** - * This function returns an associative array of the dates owned by this seminar - * - * @returns mixed a multidimensional array of seminar-dates - */ - public function getUndecoratedData($filter = false) - { - - // Caching - $cache = StudipCacheFactory::getCache(); - $cache_key = 'course/undecorated_data/'. $this->id; - - if ($filter) { - $sub_key = ($_SESSION['_language'] ?? 'none') .'/'. $this->filterStart .'-'. $this->filterEnd; - } else { - $sub_key = ($_SESSION['_language'] ?? 'none') .'/unfiltered'; - } - - $data = unserialize($cache->read($cache_key)); - - // build cache from scratch - if (empty($data) || empty($data[$sub_key])) { - $cycles = $this->metadate->getCycleData(); - $dates = $this->getSingleDates($filter, $filter); - $rooms = []; - - foreach (array_keys($cycles) as $id) { - if ($this->filterStart && $this->filterEnd - && !$this->metadate->hasDates($id, $this->filterStart, $this->filterEnd)) - { - unset($cycles[$id]); - continue; - } - - $cycles[$id]['first_date'] = CycleDataDB::getFirstDate($id); - $cycles[$id]['last_date'] = CycleDataDB::getLastDate($id); - if (!empty($cycles[$id]['assigned_rooms'])) { - foreach ($cycles[$id]['assigned_rooms'] as $room_id => $count) { - if (!isset($rooms[$room_id])) { - $rooms[$room_id] = 0; - } - $rooms[$room_id] += $count; - } - } - } - - // besser wieder mit direktem Query statt Objekten - if (is_array($cycles) && count($cycles) === 0) { - $cycles = false; - } - - $ret['regular']['turnus_data'] = $cycles; - - // the irregular single-dates - foreach ($dates as $val) { - $zw = [ - 'metadate_id' => $val->getMetaDateID(), - 'termin_id' => $val->getTerminID(), - 'date_typ' => $val->getDateType(), - 'start_time' => $val->getStartTime(), - 'end_time' => $val->getEndTime(), - 'mkdate' => $val->getMkDate(), - 'chdate' => $val->getMkDate(), - 'ex_termin' => $val->isExTermin(), - 'orig_ex' => $val->isExTermin(), - 'range_id' => $val->getRangeID(), - 'author_id' => $val->getAuthorID(), - 'resource_id' => $val->getResourceID(), - 'raum' => $val->getFreeRoomText(), - 'typ' => $val->getDateType(), - 'tostring' => $val->toString() - ]; - - if ($val->getResourceID()) { - if (!isset($rooms[$val->getResourceID()])) { - $rooms[$val->getResourceID()] = 0; - } - $rooms[$val->getResourceID()]++; - } - - $ret['irregular'][$val->getTerminID()] = $zw; - } - - $ret['rooms'] = $rooms; - $ret['ort'] = $this->location; - - $data[$sub_key] = $ret; - - // write data to cache - $cache->write($cache_key, serialize($data), 600); - } - - return $data[$sub_key]; - } - - public function getFormattedTurnus($short = FALSE) - { - // activate this with StEP 00077 - /* $cache = Cache::instance(); - * $cache_key = "formatted_turnus".$this->id; - * if (! $return_string = $cache->read($cache_key)) - * { - */ - return $this->getDatesExport(['short' => $short, 'shrink' => true]); - - // activate this with StEP 00077 - // $cache->write($cache_key, $return_string, 60*60); - // } - } - - public function getFormattedTurnusDates($short = FALSE) - { - if ($cycles = $this->metadate->getCycles()) { - $return_string = []; - foreach ($cycles as $id => $c) { - $return_string[$id] = $c->toString($short); - //hmm tja... - if ($c->description){ - $return_string[$id] .= ' ('. htmlReady($c->description) .')'; - } - } - return $return_string; - } else - return FALSE; - } - - public function getMetaDateCount() - { - return sizeof($this->metadate->cycles); - } - - public function getMetaDateValue($key, $value_name) - { - return $this->metadate->cycles[$key]->$value_name; - } - - public function setMetaDateValue($key, $value_name, $value) - { - $this->metadate->cycles[$key]->$value_name = $value; - } - - /** - * restore the data - * - * the complete data of the object will be loaded from the db - * @access public - * @throws Exception if there is no such course - * @return boolean always true - */ - public function restore() - { - if ($this->course->id) { - $this->course->restore(); - } - $this->irregularSingleDates = null; - $this->issues = null; - $this->_metadate = null; - $this->course_set = null; - - return TRUE; - } - - /** - * returns an array of variables from the seminar-object, excluding variables - * containing objects or arrays - * - * @return array - */ - public function getSettings() { - $settings = $this->course->toRawArray(); - unset($settings['config']); - return $settings; - } - - public function store($trigger_chdate = true) - { - // activate this with StEP 00077 - // $cache = Cache::instance(); - // $cache->expire("formatted_turnus".$this->id); - - //check for security consistency - if ($this->write_level < $this->read_level) // hier wusste ein Lehrender nicht, was er tat - $this->write_level = $this->read_level; - - if ($this->irregularSingleDates) { - foreach ($this->irregularSingleDates as $val) { - $val->store(); - } - } - - if ($this->issues) { - foreach ($this->issues as $val) { - $val->store(); - } - } - - $metadate_changed = isset($this->metadate) ? $this->metadate->store() : 0; - $course_changed = $this->course->store(); - if ($metadate_changed && $trigger_chdate) { - return $this->course->triggerChdate(); - } else { - return $course_changed ?: false; - } - } - - public function setStartSemester($start) - { - global $perm; - - if ($perm->have_perm('tutor') && $start != $this->semester_start_time) { - // logging >>>>>> - StudipLog::log("SEM_SET_STARTSEMESTER", $this->getId(), $start); - NotificationCenter::postNotification("CourseDidChangeSchedule", $this); - // logging <<<<<< - $this->semester_start_time = $start; - $this->metadate->setSeminarStartTime($start); - $this->createMessage(_("Das Startsemester wurde geändert.")); - $this->createInfo(_("Beachten Sie, dass Termine, die nicht mit den Einstellungen der regelmäßigen Zeit übereinstimmen (z.B. auf Grund einer Verschiebung der regelmäßigen Zeit), teilweise gelöscht sein könnten!")); - return TRUE; - } - return FALSE; - } - - public function removeAndUpdateSingleDates() - { - SeminarCycleDate::removeOutRangedSingleDates( - $this->semester_start_time, - $this->getEndSemesterVorlesEnde(), - $this->id - ); - - foreach ($this->metadate->cycles as $key => $val) { - $this->metadate->cycles[$key]->readSingleDates(); - $this->metadate->createSingleDates($key); - $this->metadate->cycles[$key]->termine = NULL; - } - NotificationCenter::postNotification("CourseDidChangeSchedule", $this); - } - - public function getStartSemester() - { - return $this->semester_start_time; - } - - /* - * setEndSemester - * @param end integer 0 (one Semester), -1 (eternal), or timestamp of last happening semester - * @returns TRUE on success, FALSE on failure - */ - public function setEndSemester($end) - { - global $perm; - - $previousEndSemester = $this->getEndSemester(); // save the end-semester before it is changed, so we can choose lateron in which semesters we need to be rebuilt the SingleDates - - if ($end != $this->getEndSemester()) { // only change Duration if it differs from the current one - - if ($end == 0) { // the seminar takes place just in the selected start-semester - $this->semester_duration_time = 0; - $this->metadate->setSeminarDurationTime(0); - // logging >>>>>> - StudipLog::log("SEM_SET_ENDSEMESTER", $this->getId(), $end, 'Laufzeit: 1 Semester'); - // logging <<<<<< - } else if ($end == -1) { // the seminar takes place in every semester above and including the start-semester - // logging >>>>>> - StudipLog::log("SEM_SET_ENDSEMESTER", $this->getId(), $end, 'Laufzeit: unbegrenzt'); - // logging <<<<<< - $this->semester_duration_time = -1; - $this->metadate->setSeminarDurationTime(-1); - SeminarCycleDate::removeOutRangedSingleDates( - $this->semester_start_time, - $this->getEndSemesterVorlesEnde(), - $this->id - ); - } else { // the seminar takes place between the selected start~ and end-semester - // logging >>>>>> - StudipLog::log("SEM_SET_ENDSEMESTER", $this->getId(), $end); - // logging <<<<<< - $this->semester_duration_time = $end - $this->semester_start_time; // the duration is stored, not the real end-point - $this->metadate->setSeminarDurationTime($this->semester_duration_time); - } - - $this->createMessage(_("Die Dauer wurde geändert.")); - NotificationCenter::postNotification("CourseDidChangeSchedule", $this); - - /* - * If the duration has been changed, we have to create new SingleDates - * if the new duration is longer than the previous one - */ - if ( ($previousEndSemester != -1) && ( ($previousEndSemester < $this->getEndSemester()) || (($previousEndSemester == 0) && ($this->getEndSemester() == -1) ) )) { - // if the previous duration was unlimited, the only option choosable is - // a shorter duration then 'ever', so there cannot be any new SingleDates - - // special case: if the previous selection was 'one semester' and the new one is 'eternal', - // than we have to find out the end of the only semester, the start-semester - if ($previousEndSemester == 0) { - $startAfterTimeStamp = $this->course->start_semester->ende; - } else { - $startAfterTimeStamp = $previousEndSemester; - } - - foreach ($this->metadate->cycles as $key => $val) { - $this->metadate->createSingleDates(['metadate_id' => $key, 'startAfterTimeStamp' => $startAfterTimeStamp]); - $this->metadate->cycles[$key]->termine = NULL; // emtpy the SingleDates for each cycle, so that SingleDates, which were not in the current view, are not loaded and therefore should not be visible - } - } - } - - return TRUE; - } - - /* - * getEndSemester - * @returns 0 (one Semester), -1 (eternal), or TimeStamp of last Semester for this Seminar - */ - public function getEndSemester() - { - if ($this->semester_duration_time == 0) return 0; // seminar takes place only in the start-semester - if ($this->semester_duration_time == -1) return -1; // seminar takes place eternally - return $this->semester_start_time + $this->semester_duration_time; // seminar takes place between start~ and end-semester - } - - public function getEndSemesterVorlesEnde() - { - if ($this->semester_duration_time == -1) { - $semesters = Semester::getAll(); - $very_last_semester = array_pop($semesters); - return $very_last_semester->vorles_ende; - } - return $this->course->end_semester->vorles_ende; - } - - /** - * return the name of the seminars start-semester - * - * @return string the name of the start-semester or false if there is no start-semester - */ - public function getStartSemesterName() - { - return $this->course->start_semester->name; - } - - /** - * return an array of singledate-objects for the submitted cycle identified by metadate_id - * - * @param string $metadate_id the id identifying the cycle - * - * @return mixed an array of singledate-objects - */ - public function readSingleDatesForCycle($metadate_id) - { - return $this->metadate->readSingleDates($metadate_id, $this->filterStart, $this->filterEnd); - } - - public function readSingleDates($force = FALSE, $filter = FALSE) - { - if (!$force) { - if (is_array($this->irregularSingleDates)) { - return TRUE; - } - } - $this->irregularSingleDates = []; - - if ($filter) { - $data = SeminarDB::getSingleDates($this->id, $this->filterStart, $this->filterEnd); - } else { - $data = SeminarDB::getSingleDates($this->id); - } - - foreach ($data as $val) { - unset($termin); - $termin = new SingleDate(); - $termin->fillValuesFromArray($val); - $this->irregularSingleDates[$val['termin_id']] =& $termin; - } - } - - public function &getSingleDate($singleDateID, $cycle_id = '') - { - if ($cycle_id == '') { - $this->readSingleDates(); - return $this->irregularSingleDates[$singleDateID]; - } else { - $dates = $this->metadate->getSingleDates($cycle_id, $this->filterStart, $this->filterEnd); - $data =& $dates; - return $data[$singleDateID]; - } - } - - public function &getSingleDates($filter = false, $force = false, $include_deleted_dates = false) - { - $this->readSingleDates($force, $filter); - if (!$include_deleted_dates) { - return $this->irregularSingleDates; - } else { - $deleted_dates = []; - foreach (SeminarDB::getDeletedSingleDates($this->getId(), $this->filterStart, $this->filterEnd) as $val) { - $termin = new SingleDate(); - $termin->fillValuesFromArray($val); - $deleted_dates[$val['termin_id']] = $termin; - } - $dates = array_merge($this->irregularSingleDates, $deleted_dates); - uasort($dates, function($a,$b) { - if ($a->getStartTime() == $b->getStartTime()) return 0; - return $a->getStartTime() < $b->getStartTime() ? -1 : 1;} - ); - return $dates; - } - } - - public function getCycles() - { - return $this->metadate->getCycles(); - } - - public function &getSingleDatesForCycle($metadate_id) - { - if (!$this->metadate->cycles[$metadate_id]->termine) { - $this->metadate->readSingleDates($metadate_id, $this->filterStart, $this->filterEnd); - if (!$this->metadate->cycles[$metadate_id]->termine) { - $this->readSingleDates(); - $this->metadate->createSingleDates($metadate_id, $this->irregularSingleDates); - $this->metadate->readSingleDates($metadate_id, $this->filterStart, $this->filterEnd); - } - //$this->metadate->readSingleDates($metadate_id, $this->filterStart, $this->filterEnd); - } - $dates = $this->metadate->getSingleDates($metadate_id, $this->filterStart, $this->filterEnd); - return $dates; - } - - public function readIssues($force = false) - { - if (!is_array($this->issues) || $force) { - $this->issues = []; - $data = SeminarDB::getIssues($this->id); - - foreach ($data as $val) { - unset($issue); - $issue = new Issue(); - $issue->fillValuesFromArray($val); - $this->issues[$val['issue_id']] =& $issue; - } - } - } - - public function addSingleDate(&$singledate) - { - // logging >>>>>> - StudipLog::log("SEM_ADD_SINGLEDATE", $this->getId(), $singledate->toString(), 'SingleDateID: '.$singledate->getTerminID()); - // logging <<<<<< - - $cache = StudipCacheFactory::getCache(); - $cache->expire('course/undecorated_data/'. $this->getId()); - - $this->readSingleDates(); - $this->irregularSingleDates[$singledate->getSingleDateID()] =& $singledate; - NotificationCenter::postNotification("CourseDidChangeSchedule", $this); - return TRUE; - } - - public function addIssue(&$issue) - { - $this->readIssues(); - if ($issue instanceof Issue) { - $max = -1; - if (is_array($this->issues)) foreach ($this->issues as $val) { - if ($val->getPriority() > $max) { - $max = $val->getPriority(); - } - } - $max++; - $issue->setPriority($max); - $this->issues[$issue->getIssueID()] =& $issue; - return TRUE; - } else { - return FALSE; - } - } - - public function deleteSingleDate($date_id, $cycle_id = '') - { - $this->readSingleDates(); - // logging >>>>>> - StudipLog::log("SEM_DELETE_SINGLEDATE",$date_id, $this->getId(), 'Cycle_id: '.$cycle_id); - // logging <<<<<< - if ($cycle_id == '') { - $this->irregularSingleDates[$date_id]->delete(true); - unset ($this->irregularSingleDates[$date_id]); - NotificationCenter::postNotification("CourseDidChangeSchedule", $this); - return TRUE; - } else { - $this->metadate->deleteSingleDate($cycle_id, $date_id, $this->filterStart, $this->filterEnd); - NotificationCenter::postNotification("CourseDidChangeSchedule", $this); - return TRUE; - } - } - - public function cancelSingleDate($date_id, $cycle_id = '') - { - if ($cycle_id) { - return $this->deleteSingleDate($date_id, $cycle_id); - } - $this->readSingleDates(); - // logging >>>>>> - StudipLog::log("SEM_DELETE_SINGLEDATE",$date_id, $this->getId(), 'appointment cancelled'); - // logging <<<<<< - $this->irregularSingleDates[$date_id]->setExTermin(true); - $this->irregularSingleDates[$date_id]->store(); - unset ($this->irregularSingleDates[$date_id]); - NotificationCenter::postNotification("CourseDidChangeSchedule", $this); - return TRUE; - } - - public function unDeleteSingleDate($date_id, $cycle_id = '') - { - // logging >>>>>> - StudipLog::log("SEM_UNDELETE_SINGLEDATE",$date_id, $this->getId(), 'Cycle_id: '.$cycle_id); - NotificationCenter::postNotification("CourseDidChangeSchedule", $this); - // logging <<<<<< - if ($cycle_id == '') { - $termin = new SingleDate($date_id); - if (!$termin->isExTermin()) { - return false; - } - $termin->setExTermin(false); - $termin->store(); - return true; - } else { - return $this->metadate->unDeleteSingleDate($cycle_id, $date_id, $this->filterStart, $this->filterEnd); - } - } - - /** - * return all stacked messages as a multidimensional array - * - * The array has the following structure: - * array( 'type' => ..., 'message' ... ) - * where type is one of error, info and success - * - * @return mixed the array of stacked messages - */ - public function getStackedMessages() - { - if ( is_array( $this->message_stack ) ) { - $ret = []; - - // cycle through message types and set title and details appropriate - foreach ($this->message_stack as $type => $messages ) { - switch ( $type ) { - case 'error': - $ret['error'] = [ - 'title' => _("Es sind Fehler/Probleme aufgetreten!"), - 'details' => $this->message_stack['error'] - ]; - break; - - case 'info': - $ret['info'] = [ - 'title' => implode('<br>', $this->message_stack['info']), - 'details' => [] - ]; - break; - - case 'success': - $ret['success'] = [ - 'title' => _("Ihre Änderungen wurden gespeichert!"), - 'details' => $this->message_stack['success'] - ]; - break; - } - } - - return $ret; - } - - return false; - } - - /** - * return the next stacked messag-string - * - * @return string a message-string - */ - public function getNextMessage() - { - if ($this->messages[0]) { - $ret = $this->messages[0]; - unset ($this->messages[0]); - sort($this->messages); - return $ret; - } - return FALSE; - } - - /** - * stack an error-message - * - * @param string $text the message to stack - */ - public function createError($text) - { - $this->messages[] = 'error§'.$text.'§'; - $this->message_stack['error'][] = $text; - } - - /** - * stack an info-message - * - * @param string $text the message to stack - */ - public function createInfo($text) - { - $this->messages[] = 'info§'.$text.'§'; - $this->message_stack['info'][] = $text; - } - - /** - * stack a success-message - * - * @param string $text the message to stack - */ - public function createMessage($text) - { - $this->messages[] = 'msg§'.$text.'§'; - $this->message_stack['success'][] = $text; - } - - /** - * add an array of messages to the message-stack - * - * @param mixed $messages array of pre-marked message-strings - * @param bool returns true on success - */ - public function appendMessages( $messages ) - { - if (!is_array($messages)) return false; - - foreach ( $messages as $type => $msgs ) { - foreach ($msgs as $msg) { - $this->message_stack[$type][] = $msg; - } - } - return true; - } - - public function addCycle($data = []) - { - $new_id = $this->metadate->addCycle($data); - if($new_id){ - $this->setStartWeek($data['startWeek'], $new_id); - $this->setTurnus($data['turnus'], $new_id); - } - // logging >>>>>> - if($new_id){ - $cycle_info = $this->metadate->cycles[$new_id]->toString(); - NotificationCenter::postNotification("CourseDidChangeSchedule", $this); - StudipLog::log("SEM_ADD_CYCLE", $this->getId(), NULL, $cycle_info, '<pre>'.print_r($data,true).'</pre>'); - } - // logging <<<<<< - return $new_id; - } - - /** - * Change a regular timeslot of the seminar. The data is passed as an array - * conatining the following fields: - * start_stunde, start_minute, end_stunde, end_minute - * description, turnus, startWeek, day, sws - * - * @param array $data the cycle-data - * - * @return void - */ - public function editCycle($data = []) - { - $cycle = $this->metadate->cycles[$data['cycle_id']]; - $new_start = mktime($data['start_stunde'], $data['start_minute']); - $new_end = mktime($data['end_stunde'], $data['end_minute']); - $old_start = mktime($cycle->getStartStunde(),$cycle->getStartMinute()); - $old_end = mktime($cycle->getEndStunde(), $cycle->getEndMinute()); - $do_changes = false; - - // check, if the new timeslot exceeds the old one - if (($new_start < $old_start) || ($new_end > $old_end) || ($data['day'] != $cycle->day) ) { - $has_bookings = false; - - // check, if there are any booked rooms - foreach($cycle->getSingleDates() as $singleDate) { - if ($singleDate->getStarttime() > (time() - 3600) && $singleDate->hasRoom()) { - $has_bookings = true; - break; - } - } - - // if the timeslot exceeds the previous one and has some booked rooms - // they would be lost, so ask the user for permission to do so. - if (!$data['really_change'] && $has_bookings) { - $link_params = [ - 'editCycle_x' => '1', - 'editCycle_y' => '1', - 'cycle_id' => $data['cycle_id'], - 'start_stunde' => $data['start_stunde'], - 'start_minute' => $data['start_minute'], - 'end_stunde' => $data['end_stunde'], - 'end_minute' => $data['end_minute'], - 'day' => $data['day'], - 'really_change' => 'true' - ]; - $question = _("Wenn Sie die regelmäßige Zeit auf %s ändern, verlieren Sie die Raumbuchungen für alle in der Zukunft liegenden Termine!") - ."\n". _("Sind Sie sicher, dass Sie die regelmäßige Zeit ändern möchten?"); - $question_time = '**'. strftime('%A', $data['day']) .', '. $data['start_stunde'] .':'. $data['start_minute'] - .' - '. $data['end_stunde'] .':'. $data['end_minute'] .'**'; - - echo (string)QuestionBox::create( - sprintf($question, $question_time), - URLHelper::getURL('', $link_params) - ); - - } else { - $do_changes = true; - } - } else { - $do_changes = true; - } - - $messages = false; - $same_time = false; - - // only apply changes, if the user approved the change or - // the change does not need any approval - if ($do_changes) { - if ($data['description'] != $cycle->getDescription()) { - $this->createMessage(_("Die Beschreibung des regelmäßigen Eintrags wurde geändert.")); - $message = true; - $do_changes = true; - } - - if ($old_start == $new_start && $old_end == $new_end) { - $same_time = true; - } - if ($data['startWeek'] != $cycle->week_offset) { - $this->setStartWeek($data['startWeek'], $cycle->metadate_id); - $message = true; - $do_changes = true; - } - if ($data['turnus'] != $cycle->cycle) { - $this->setTurnus($data['turnus'], $cycle->metadate_id); - $message = true; - $do_changes = true; - } - if ($data['day'] != $cycle->day) { - $message = true; - $same_time = false; - $do_changes = true; - } - if (round(str_replace(',','.', $data['sws']),1) != $cycle->sws) { - $cycle->sws = $data['sws']; - $this->createMessage(_("Die Semesterwochenstunden für Lehrende des regelmäßigen Eintrags wurden geändert.")); - $message = true; - $do_changes = true; - } - - $change_from = $cycle->toString(); - if ($this->metadate->editCycle($data)) { - if (!$same_time) { - // logging >>>>>> - StudipLog::log("SEM_CHANGE_CYCLE", $this->getId(), NULL, $change_from .' -> '. $cycle->toString()); - NotificationCenter::postNotification("CourseDidChangeSchedule", $this); - // logging <<<<<< - $this->createMessage(sprintf(_("Die regelmäßige Veranstaltungszeit wurde auf \"%s\" für alle in der Zukunft liegenden Termine geändert!"), - '<b>'.getWeekday($data['day']) . ', ' . $data['start_stunde'] . ':' . $data['start_minute'].' - '. - $data['end_stunde'] . ':' . $data['end_minute'] . '</b>')); - $message = true; - } - } else { - if (!$same_time) { - $this->createInfo(sprintf(_("Die regelmäßige Veranstaltungszeit wurde auf \"%s\" geändert, jedoch gab es keine Termine die davon betroffen waren."), - '<b>'.getWeekday($data['day']) . ', ' . $data['start_stunde'] . ':' . $data['start_minute'].' - '. - $data['end_stunde'] . ':' . $data['end_minute'] . '</b>')); - $message = true; - } - } - $this->metadate->sortCycleData(); - - if (!$message) { - $this->createInfo("Sie haben keine Änderungen vorgenommen!"); - } - } - } - - public function deleteCycle($cycle_id) - { - // logging >>>>>> - $cycle_info = $this->metadate->cycles[$cycle_id]->toString(); - StudipLog::log("SEM_DELETE_CYCLE", $this->getId(), NULL, $cycle_info); - NotificationCenter::postNotification("CourseDidChangeSchedule", $this); - // logging <<<<<< - return $this->metadate->deleteCycle($cycle_id); - } - - public function setTurnus($turnus, $metadate_id = false) - { - if ($this->metadate->getTurnus($metadate_id) != $turnus) { - $this->metadate->setTurnus($turnus, $metadate_id); - $key = $metadate_id ? $metadate_id : $this->metadate->getFirstMetadate()->metadate_id; - $this->createMessage(sprintf(_("Der Turnus für den Termin %s wurde geändert."), $this->metadate->cycles[$key]->toString())); - $this->metadate->createSingleDates($key); - $this->metadate->cycles[$key]->termine = null; - NotificationCenter::postNotification("CourseDidChangeSchedule", $this); - } - return TRUE; - } - - public function getTurnus($metadate_id = false) - { - return $this->metadate->getTurnus($metadate_id); - } - - - /** - * get StatOfNotBookedRooms returns an array: - * open: number of rooms with no booking - * all: number of singleDates, which can have a booking - * open_rooms: array of singleDates which have no booking - * - * @param String $cycle_id Id of cycle - * @return array as described above - */ - public function getStatOfNotBookedRooms($cycle_id) - { - if (!isset($this->BookedRoomsStatTemp[$cycle_id])) { - $this->BookedRoomsStatTemp[$cycle_id] = SeminarDB::getStatOfNotBookedRooms($cycle_id, $this->id, $this->filterStart, $this->filterEnd); - } - return $this->BookedRoomsStatTemp[$cycle_id]; - } - - public function getStatus() - { - return $this->status; - } - - public function getBookedRoomsTooltip($cycle_id) - { - $stat = $this->getStatOfNotBookedRooms($cycle_id); - $pattern = '%s , %s, %s-%s <br />'; - $return = ''; - if ($stat['open'] > 0 && $stat['open'] !== $stat['all']) { - $return = _('Folgende Termine haben keine Raumbuchung:') . '<br />'; - - foreach ($stat['open_rooms'] as $aSingleDate) { - $return .= sprintf($pattern,strftime('%a', $aSingleDate['date']), - strftime('%d.%m.%Y', $aSingleDate['date']), - strftime('%H:%M', $aSingleDate['date']), - strftime('%H:%M', $aSingleDate['end_time'])); - } - } - - // are there any dates with declined room-requests? - if ($stat['declined'] > 0) { - $return .= _('Folgende Termine haben eine abgelehnte Raumanfrage') . '<br />'; - foreach ($stat['declined_dates'] as $aSingleDate) { - $return .= sprintf($pattern,strftime('%a', $aSingleDate['date']), - strftime('%d.%m.%Y', $aSingleDate['date']), - strftime('%H:%M', $aSingleDate['date']), - strftime('%H:%M', $aSingleDate['end_time'])); - } - } - - return $return; - } - - /** - * @param $cycle_id - * @return string - */ - public function getCycleColorClass($cycle_id) - { - if (Config::get()->RESOURCES_ENABLE && Config::get()->RESOURCES_ENABLE_BOOKINGSTATUS_COLORING) { - if (!$this->metadate->hasDates($cycle_id, $this->filterStart, $this->filterEnd)) { - return 'red'; - } - - $stat = $this->getStatOfNotBookedRooms($cycle_id); - - if ($stat['open'] > 0 && $stat['open'] == $stat['all']) { - return 'red'; - } - if ($stat['open'] > 0) { - return 'yellow '; - } - return 'green '; - } - - return ''; - } - - public function &getIssues($force = false) - { - $this->readIssues($force); - $this->renumberIssuePrioritys(); - if (is_array($this->issues)) { - uasort($this->issues, function ($a, $b) { - return $a->getPriority() - $b->getPriority(); - }); - } - return $this->issues; - } - - public function deleteIssue($issue_id) - { - $this->issues[$issue_id]->delete(); - unset($this->issues[$issue_id]); - return TRUE; - } - - public function &getIssue($issue_id) - { - $this->readIssues(); - return $this->issues[$issue_id]; - } - - /* - * changeIssuePriority - * - * changes an issue with an given id to a new priority - * - * @param - * issue_id the issue_id of the issue to be changed - * new_priority the new priority - */ - public function changeIssuePriority($issue_id, $new_priority) - { - /* REMARK: - * This function only works, when an issue is moved ONE slote higher or lower - * It does NOT work with ARBITRARY movements! - */ - $this->readIssues(); - $old_priority = $this->issues[$issue_id]->getPriority(); // get old priority, so we can just exchange prioritys of two issues - foreach ($this->issues as $id => $issue) { // search for the concuring issue - if ($issue->getPriority() == $new_priority) { - $this->issues[$id]->setPriority($old_priority); // the concuring issue gets the old id of the changed issue - $this->issues[$id]->store(); // ###store_problem### - } - } - - $this->issues[$issue_id]->setPriority($new_priority); // changed issue gets the new priority - $this->issues[$issue_id]->store(); // ###store_problem### - - } - - public function renumberIssuePrioritys() - { - if (is_array($this->issues)) { - - $sorter = []; - foreach ($this->issues as $id => $issue) { - $sorter[$id] = $issue->getPriority(); - } - asort($sorter); - $i = 0; - foreach ($sorter as $id => $old_priority) { - $this->issues[$id]->setPriority($i); - $i++; - } - } - } - - public function autoAssignIssues($themen, $cycle_id) - { - $this->metadate->cycles[$cycle_id]->autoAssignIssues($themen, $this->filterStart, $this->filterEnd); - } - - - public function applyTimeFilter($start, $end) - { - $this->filterStart = $start; - $this->filterEnd = $end; - } - - public function setFilter($timestamp) - { - if ($timestamp == 'all') { - $_SESSION['raumzeitFilter'] = 'all'; - $this->applyTimeFilter(0, 0); - } else { - $filterSemester = Semester::findByTimestamp($timestamp); - $_SESSION['raumzeitFilter'] = $filterSemester->beginn; - $this->applyTimeFilter($filterSemester->beginn, $filterSemester->ende); - } - } - - public function registerCommand($command, $function) - { - $this->commands[$command] = $function; - } - - public function processCommands() - { - global $cmd; - - // workaround for multiple submit-buttons with new Button-API - foreach ($this->commands as $r_cmd => $func) { - if (Request::submitted($r_cmd)) { - $cmd = $r_cmd; - } - } - - if (!isset($cmd) && Request::option('cmd')) $cmd = Request::option('cmd'); - if (!isset($cmd)) return FALSE; - - if (isset($this->commands[$cmd])) { - call_user_func($this->commands[$cmd], $this); - } - } - - public function getFreeTextPredominantRoom($cycle_id) - { - if (!($room = $this->metadate->cycles[$cycle_id]->getFreeTextPredominantRoom($this->filterStart, $this->filterEnd))) { - return FALSE; - } - return $room; - } - - public function getPredominantRoom($cycle_id, $list = FALSE) - { - if (!($rooms = $this->metadate->cycles[$cycle_id]->getPredominantRoom($this->filterStart, $this->filterEnd))) { - return FALSE; - } - if ($list) { - return $rooms; - } else { - return $rooms[0]; - } - } - - - public function hasDatesOutOfDuration($force = false) - { - if ($this->hasDatesOutOfDuration == -1 || $force) { - $this->hasDatesOutOfDuration = SeminarDB::hasDatesOutOfDuration($this->getStartSemester(), $this->getEndSemesterVorlesEnde(), $this->id); - } - return $this->hasDatesOutOfDuration; - } - - public function getStartWeek($metadate_id = false) - { - return $this->metadate->getStartWoche($metadate_id); - } - - public function setStartWeek($week, $metadate_id = false) - { - if ($this->metadate->getStartWoche($metadate_id) == $week) { - return FALSE; - } else { - $this->metadate->setStartWoche($week, $metadate_id); - $key = $metadate_id ? $metadate_id : $this->metadate->getFirstMetadate()->metadate_id; - $this->createMessage(sprintf(_("Die Startwoche für den Termin %s wurde geändert."), $this->metadate->cycles[$key]->toString())); - $this->metadate->createSingleDates($key); - $this->metadate->cycles[$key]->termine = null; - NotificationCenter::postNotification("CourseDidChangeSchedule", $this); - } - } - - - /** - * instance method - * - * returns number of participants for each usergroup in seminar, - * total, lecturers, tutors, authors, users - * - * @param string (optional) return count only for given usergroup - * - * @return array <description> - */ - - public function getNumberOfParticipants() - { - $args = func_get_args(); - array_unshift($args, $this->id); - return call_user_func_array(["Seminar", "getNumberOfParticipantsBySeminarId"], $args); - } - - /** - * class method - * - * returns number of participants for each usergroup in given seminar, - * total, lecturers, tutors, authors, users - * - * @param string seminar_id - * - * @param string (optional) return count only for given usergroup - * - * @return array <description> - */ - - public function getNumberOfParticipantsBySeminarId($sem_id) - { - $db = DBManager::get(); - $stmt1 = $db->prepare("SELECT - COUNT(Seminar_id) AS anzahl, - COUNT(IF(status='dozent',Seminar_id,NULL)) AS anz_dozent, - COUNT(IF(status='tutor',Seminar_id,NULL)) AS anz_tutor, - COUNT(IF(status='autor',Seminar_id,NULL)) AS anz_autor, - COUNT(IF(status='user',Seminar_id,NULL)) AS anz_user - FROM seminar_user - WHERE Seminar_id = ? - GROUP BY Seminar_id"); - $stmt1->execute([$sem_id]); - $numbers = $stmt1->fetch(PDO::FETCH_ASSOC); - - $stmt2 = $db->prepare("SELECT COUNT(*) as anzahl - FROM admission_seminar_user - WHERE seminar_id = ? - AND status = 'accepted'"); - $stmt2->execute([$sem_id]); - $acceptedUsers = $stmt2->fetch(PDO::FETCH_ASSOC); - - - $count = 0; - if ($numbers["anzahl"]) { - $count += $numbers["anzahl"]; - } - if ($acceptedUsers["anzahl"]) { - $count += $acceptedUsers["anzahl"]; - } - - $participant_count = []; - $participant_count['total'] = $count; - $participant_count['lecturers'] = $numbers['anz_dozent'] ? (int) $numbers['anz_dozent'] : 0; - $participant_count['tutors'] = $numbers['anz_tutor'] ? (int) $numbers['anz_tutor'] : 0; - $participant_count['authors'] = $numbers['anz_autor'] ? (int) $numbers['anz_autor'] : 0; - $participant_count['users'] = $numbers['anz_user'] ? (int) $numbers['anz_user'] : 0; - - // return specific parameter if - $params = func_get_args(); - if (sizeof($params) > 1) { - if (in_array($params[1], array_keys($participant_count))) { - return $participant_count[$params[1]]; - } else { - trigger_error(get_class($this)."::__getParticipantInfos - unknown parameter requested"); - } - } - - return $participant_count; - } - - - /** - * Returns the IDs of this course's study areas. - * - * @return array an array of IDs - */ - public function getStudyAreas() - { - $stmt = DBManager::get()->prepare("SELECT DISTINCT sem_tree_id ". - "FROM seminar_sem_tree ". - "WHERE seminar_id=?"); - - $stmt->execute([$this->id]); - return $stmt->fetchAll(PDO::FETCH_COLUMN, 0); - } - - /** - * Sets the study areas of this course. - * - * @param array an array of IDs - * - * @return void - */ - public function setStudyAreas($selected) - { - $old = $this->getStudyAreas(); - $sem_tree = TreeAbstract::GetInstance("StudipSemTree"); - $removed = array_diff($old, $selected); - $added = array_diff($selected, $old); - $count_removed = 0; - $count_added = 0; - foreach($removed as $one){ - $count_removed += $sem_tree->DeleteSemEntries($one, $this->getId()); - } - foreach($added as $one){ - $count_added += $sem_tree->InsertSemEntry($one, $this->getId()); - } - if ($count_added || $count_removed) { - NotificationCenter::postNotification("CourseDidChangeStudyArea", $this); - } - return count($old) + $count_added - $count_removed; - } - - /** - * @return boolean returns TRUE if this course is publicly visible, - * FALSE otherwise - */ - public function isPublic() - { - return Config::get()->ENABLE_FREE_ACCESS && $this->read_level == 0; - } - - /** - * @return boolean returns TRUE if this course is a studygroup, - * FALSE otherwise - */ - public function isStudygroup() - { - global $SEM_CLASS, $SEM_TYPE; - return $SEM_CLASS[$SEM_TYPE[$this->status]["class"]]["studygroup_mode"]; - } - - /** - * @return int returns default colour group for new members (shown in meine_seminare.php) - * - **/ - public function getDefaultGroup() - { - if ($this->isStudygroup()) { - return 8; - } else { - return select_group ($this->semester_start_time); - } - } - - - /** - * Deletes the current seminar - * - * @return void returns success-message if seminar could be deleted - * otherwise an error-message - */ - - public function delete() - { - $s_id = $this->id; - - // Delete that Seminar. - - // Alle Benutzer aus dem Seminar rauswerfen. - $db_ar = CourseMember::deleteBySQL('Seminar_id = ?', [$s_id]); - if ($db_ar > 0) { - $this->createMessage(sprintf(_("%s Teilnehmende und Lehrende archiviert."), $db_ar)); - } - - // Alle Benutzer aus Wartelisten rauswerfen - AdmissionApplication::deleteBySQL('seminar_id = ?', [$s_id]); - - // Alle beteiligten Institute rauswerfen - $query = "DELETE FROM seminar_inst WHERE Seminar_id = ?"; - $statement = DBManager::get()->prepare($query); - $statement->execute([$s_id]); - if (($db_ar = $statement->rowCount()) > 0) { - $this->createMessage(sprintf(_("%s Zuordnungen zu Einrichtungen archiviert."), $db_ar)); - } - - // user aus den Statusgruppen rauswerfen - $count = Statusgruppen::deleteBySQL('range_id = ?', [$s_id]); - if ($count > 0) { - $this->createMessage(sprintf(_('%s Funktionen/Gruppen gelöscht.'), $count)); - } - - // seminar_sem_tree entries are deleted automatically on deletion of the Course object. - - // Alle Termine mit allem was dranhaengt zu diesem Seminar loeschen. - if (($db_ar = SingleDateDB::deleteAllDates($s_id)) > 0) { - $this->createMessage(sprintf(_("%s Veranstaltungstermine archiviert."), $db_ar)); - } - - //Themen - IssueDB::deleteAllIssues($s_id); - - //Cycles - SeminarCycleDate::deleteBySQL('seminar_id = ' . DBManager::get()->quote($s_id)); - - // Alle weiteren Postings zu diesem Seminar in den Forums-Modulen löschen - foreach (PluginEngine::getPlugins('ForumModule') as $plugin) { - $plugin->deleteContents($s_id); // delete content irrespective of plugin-activation in the seminar - - if ($plugin->isActivated($s_id)) { // only show a message, if the plugin is activated, to not confuse the user - $this->createMessage(sprintf(_('Einträge in %s archiviert.'), $plugin->getPluginName())); - } - } - - // Alle Pluginzuordnungen entfernen - PluginManager::getInstance()->deactivateAllPluginsForRange('sem', $s_id); - - // Alle Dokumente zu diesem Seminar loeschen. - $folder = Folder::findTopFolder($s_id); - if($folder) { - if($folder->delete()) { - $this->createMessage(_("Dokumente und Ordner archiviert.")); - } - } - - - // Freie Seite zu diesem Seminar löschen - $db_ar = StudipScmEntry::deleteBySQL('range_id = ?', [$s_id]); - if ($db_ar > 0) { - $this->createMessage(_("Freie Seite der Veranstaltung archiviert.")); - } - - // Alle News-Verweise auf dieses Seminar löschen - if ( ($db_ar = StudipNews::DeleteNewsRanges($s_id)) ) { - $this->createMessage(sprintf(_("%s Ankündigungen gelöscht."), $db_ar)); - } - //delete entry in news_rss_range - StudipNews::UnsetRssId($s_id); - - //kill the datafields - DataFieldEntry::removeAll($s_id); - - //kill all wiki-pages - $db_wiki = WikiPage::deleteBySQL('range_id = ?', [$s_id]); - if ($db_wiki > 0) { - $this->createMessage(sprintf(_("%s Wiki-Seiten archiviert."), $db_wiki)); - } - - $query = "DELETE FROM wiki_links WHERE range_id = ?"; - $statement = DBManager::get()->prepare($query); - $statement->execute([$s_id]); - - // delete course config values - ConfigValue::deleteBySQL('range_id = ?', [$s_id]); - - // kill all the ressources that are assigned to the Veranstaltung (and all the linked or subordinated stuff!) - if (Config::get()->RESOURCES_ENABLE) { - ResourceBooking::deleteBySql( - 'range_id = :course_id', - [ - 'course_id' => $s_id - ] - ); - if ($rr = RoomRequest::existsByCourse($s_id)) { - RoomRequest::find($rr)->delete(); - } - } - - // kill virtual seminar-entries in calendar - $query = "DELETE FROM schedule_seminare WHERE seminar_id = ?"; - $statement = DBManager::get()->prepare($query); - $statement->execute([$s_id]); - - if(Config::get()->ELEARNING_INTERFACE_ENABLE){ - global $connected_cms; - $del_cms = 0; - $cms_types = ObjectConnections::GetConnectedSystems($s_id); - if(count($cms_types)){ - foreach($cms_types as $system){ - ELearningUtils::loadClass($system); - $del_cms += $connected_cms[$system]->deleteConnectedModules($s_id); - } - $this->createMessage(sprintf(_("%s Verknüpfungen zu externen Systemen gelöscht."), $del_cms )); - } - } - - //kill the object_user_vists for this seminar - object_kill_visits(null, $s_id); - - // Logging... - $query = "SELECT CONCAT(seminare.VeranstaltungsNummer, ' ', seminare.name, '(', semester_data.name, ')') - FROM seminare - LEFT JOIN semester_data ON (seminare.start_time = semester_data.beginn) - WHERE seminare.Seminar_id = ?"; - $statement = DBManager::get()->prepare($query); - $statement->execute([$s_id]); - $semlogname = $statement->fetchColumn() ?: sprintf('unknown sem_id: %s', $s_id); - - StudipLog::log("SEM_ARCHIVE",$s_id,NULL,$semlogname); - // ...logged - - // delete deputies if necessary - Deputy::deleteByRange_id($s_id); - - UserDomain::removeUserDomainsForSeminar($s_id); - - AutoInsert::deleteSeminar($s_id); - - //Anmeldeset Zordnung entfernen - $cs = $this->getCourseSet(); - if ($cs) { - CourseSet::removeCourseFromSet($cs->getId(), $this->getId()); - $cs->load(); - if (!count($cs->getCourses()) - && $cs->isGlobal() - && $cs->getUserid() != '') { - $cs->delete(); - } - } - AdmissionPriority::unsetAllPrioritiesForCourse($this->getId()); - // und das Seminar loeschen. - $this->course->delete(); - $this->restore(); - return true; - } - - /** - * returns a html representation of the seminar-dates - * - * @param array optional variables which are passed to the template - * @return string the html-representation of the dates - * - * @author Till Glöggler <tgloeggl@uos.de> - */ - public function getDatesHTML($params = []) - { - return $this->getDatesTemplate('dates/seminar_html.php', $params); - } - - /** - * returns a representation without html of the seminar-dates - * - * @param array optional variables which are passed to the template - * @return string the representation of the dates without html - * - * @author Till Glöggler <tgloeggl@uos.de> - */ - public function getDatesExport($params = []) - { - return $this->getDatesTemplate('dates/seminar_export.php', $params); - } - - /** - * returns a xml-representation of the seminar-dates - * - * @param array optional variables which are passed to the template - * @return string the xml-representation of the dates - * - * @author Till Glöggler <tgloeggl@uos.de> - */ - public function getDatesXML($params = []) - { - return $this->getDatesTemplate('dates/seminar_xml.php', $params); - } - - /** - * returns a representation of the seminar-dates with a specifiable template - * - * @param mixed this can be a template-object or a string pointing to a template in path_to_studip/templates - * @param array optional parameters which are passed to the template - * @return string the template output of the dates - * - * @author Till Glöggler <tgloeggl@uos.de> - */ - public function getDatesTemplate($template, $params = []) - { - if (!$template instanceof Flexi_Template && is_string($template)) { - $template = $GLOBALS['template_factory']->open($template); - } - - if (!empty($params['semester_id'])) { - $semester = Semester::find($params['semester_id']); - if ($semester) { - // apply filter - $this->applyTimeFilter($semester->beginn, $semester->ende); - } - } - - $template->dates = $this->getUndecoratedData(isset($params['semester_id'])); - $template->seminar_id = $this->getId(); - - $template->set_attributes($params); - return trim($template->render()); - } - - /** - * returns an asscociative array with the attributes of the seminar depending - * on the field-names in the database - * @return array - */ - public function getData() - { - $data = $this->course->toArray(); - foreach($this->alias as $a => $o) { - $data[$a] = $this->course->$o; - } - return $data; - } - - /** - * returns an array with all IDs of Institutes this seminar is related to - * @param sem_id string: optional ID of a seminar, when null, this ID will be used - * @return: array of IDs (not associative) - */ - public function getInstitutes($sem_id = null) - { - if (!$sem_id && $this) { - $sem_id = $this->id; - } - - $query = "SELECT institut_id FROM seminar_inst WHERE seminar_id = :sem_id - UNION - SELECT Institut_id FROM seminare WHERE Seminar_id = :sem_id"; - $statement = DBManager::get()->prepare($query); - $statement->execute(compact('sem_id')); - return $statement->fetchAll(PDO::FETCH_COLUMN); - } - - /** - * set the entries for seminar_inst table in database - * seminare.institut_id will always be added - * @param institutes array: array of Institut_id's - * @return bool: if something changed - */ - public function setInstitutes($institutes = []) - { - if (is_array($institutes)) { - $institutes[] = $this->institut_id; - $institutes = array_unique($institutes); - - $query = "SELECT institut_id FROM seminar_inst WHERE seminar_id = ?"; - $statement = DBManager::get()->prepare($query); - $statement->execute([$this->id]); - $old_inst = $statement->fetchAll(PDO::FETCH_COLUMN); - - $todelete = array_diff($old_inst, $institutes); - - $query = "DELETE FROM seminar_inst WHERE seminar_id = ? AND institut_id = ?"; - $statement = DBManager::get()->prepare($query); - - foreach($todelete as $inst) { - $tmp_instname= get_object_name($inst, 'inst'); - StudipLog::log('CHANGE_INSTITUTE_DATA', $this->id, $inst, 'Die beteiligte Einrichtung "'. $tmp_instname['name'] .'" wurde gelöscht.'); - $statement->execute([$this->id, $inst]); - NotificationCenter::postNotification('SeminarInstitutionDidDelete', $inst, $this->id); - - } - - $toinsert = array_diff($institutes, $old_inst); - - $query = "INSERT INTO seminar_inst (seminar_id, institut_id) VALUES (?, ?)"; - $statement = DBManager::get()->prepare($query); - - foreach($toinsert as $inst) { - $tmp_instname= get_object_name($inst, 'inst'); - StudipLog::log('CHANGE_INSTITUTE_DATA', $this->id, $inst, 'Die beteiligte Einrichtung "'. $tmp_instname['name'] .'" wurde hinzugefügt.'); - $statement->execute([$this->id, $inst]); - NotificationCenter::postNotification('SeminarInstitutionDidCreate', $inst, $this->id); - } - if ($todelete || $toinsert) { - NotificationCenter::postNotification("CourseDidChangeInstitutes", $this); - } - return $todelete || $toinsert; - } else { - $this->createError(_("Ungültige Eingabe der Institute. Es muss " . - "mindestens ein Institut angegeben werden.")); - return false; - } - } - - /** - * adds a user to the seminar with the given status - * @param user_id string: ID of the user - * @param status string: status of the user for the seminar "user", "autor", "tutor", "dozent" - * @param force bool: if false (default) the user will only be upgraded and not degraded in his/her status - */ - public function addMember($user_id, $status = 'autor', $force = false) - { - - if (in_array($GLOBALS['perm']->get_perm($user_id), ["admin", "root"])) { - $this->createError(_("Admin und Root dürfen nicht Mitglied einer Veranstaltung sein.")); - return false; - } - $db = DBManager::get(); - - $rangordnung = array_flip(['user', 'autor', 'tutor', 'dozent']); - if ($rangordnung[$status] > $rangordnung['autor'] && SeminarCategories::getByTypeId($this->status)->only_inst_user) { - //überprüfe, ob im richtigen Institut: - $user_institute_stmt = $db->prepare( - "SELECT Institut_id " . - "FROM user_inst " . - "WHERE user_id = :user_id " . - ""); - $user_institute_stmt->execute(['user_id' => $user_id]); - $user_institute = $user_institute_stmt->fetchAll(PDO::FETCH_COLUMN, 0); - - if (!in_array($this->institut_id, $user_institute) && !count(array_intersect($user_institute, $this->getInstitutes()))) { - $this->createError(_("Einzutragender Nutzer stammt nicht einem beteiligten Institut an.")); - - return false; - } - } - $course_member = CourseMember::findOneBySQL('user_id = ? AND Seminar_id = ?', [$user_id, $this->id]); - $new_position = (int) DBManager::get()->fetchColumn( - "SELECT MAX(position) + 1 FROM seminar_user WHERE status = ? AND Seminar_id = ?", - [$status, $this->id] - ); - $numberOfTeachers = CourseMember::countBySql("Seminar_id = ? AND status = 'dozent'", [$this->id]); - - if (!$course_member && !$force) { - CourseMember::create([ - 'Seminar_id' => $this->id, - 'user_id' => $user_id, - 'status' => $status, - 'position' => $new_position?:0, - 'gruppe' => (int) select_group($this->getSemesterStartTime()), - 'visible' => in_array($status, ['tutor', 'dozent']) ? 'yes' : 'unknown', - ]); - // delete the entries, user is now in the seminar - if (AdmissionApplication::deleteBySQL('user_id = ? AND seminar_id = ?', [$user_id, $this->getId()])) { - //renumber the waiting/accepted/lot list, a user was deleted from it - AdmissionApplication::renumberAdmission($this->getId()); - } - $cs = $this->getCourseSet(); - if ($cs) { - AdmissionPriority::unsetPriority($cs->getId(), $user_id, $this->getId()); - } - - CalendarScheduleModel::deleteSeminarEntries($user_id, $this->getId()); - NotificationCenter::postNotification('CourseDidGetMember', $this, $user_id); - NotificationCenter::postNotification('UserDidEnterCourse', $this->id, $user_id); - StudipLog::log('SEM_USER_ADD', $this->id, $user_id, $status, 'Wurde in die Veranstaltung eingetragen'); - $this->course->resetRelation('members'); - $this->course->resetRelation('admission_applicants'); - - // Check if we need to add user to parent course as well. - if ($this->parent_course) { - $parent = new Seminar($this->parent); - $parent->addMember($user_id, $status, $force); - } - - return $this; - } elseif ( - ($force || $rangordnung[$course_member->status] < $rangordnung[$status]) - && ($course_member->status !== 'dozent' || $numberOfTeachers > 1) - ) { - $visibility = $course_member->visible; - if (in_array($status, ['tutor', 'dozent'])) { - $visibility = 'yes'; - } - $course_member->status = $status; - $course_member->visible = $visibility; - $course_member->position = $new_position; - $course_member->store(); - - if ($course_member->status === 'dozent') { - $termine = DBManager::get()->fetchFirst( - "SELECT termin_id FROM termine WHERE range_id = ?", - [$this->id] - ); - - DBManager::get()->execute( - "DELETE FROM termin_related_persons WHERE range_id IN (?) AND user_id = ?", - [$termine, $user_id] - ); - } - NotificationCenter::postNotification('CourseDidChangeMember', $this, $user_id); - $this->course->resetRelation('members'); - $this->course->resetRelation('admission_applicants'); - return $this; - } else { - if ($course_member->status === 'dozent' && $numberOfTeachers <= 1) { - $this->createError(sprintf(_('Die Person kann nicht herabgestuft werden, ' . -'da mindestens ein/eine Veranstaltungsleiter/-in (%s) in die Veranstaltung eingetragen sein muss!'), - get_title_for_status('dozent', 1, $this->status)) . - ' ' . sprintf(_('Tragen Sie zunächst eine weitere Person als Veranstaltungsleiter/-in (%s) ein.'), -get_title_for_status('dozent', 1, $this->status))); - } - - return false; - } - } - - /** - * Cancels a subscription to an admission. - * - * @param array $users - * @param string $status - * @return array - * @throws NotificationVetoException - */ - public function cancelAdmissionSubscription(array $users, string $status): array - { - $msgs = []; - $messaging = new messaging; - $course_set = $this->getCourseSet(); - $users = User::findMany($users); - foreach ($users as $user) { - $prio_delete = false; - if ($course_set) { - $prio_delete = AdmissionPriority::unsetPriority($course_set->getId(), $user->id, $this->getId()); - } - $result = AdmissionApplication::deleteBySQL( - 'seminar_id = ? AND user_id = ? AND status = ?', - [$this->getId(), $user->id, $status] - ); - if ($result || $prio_delete) { - setTempLanguage($user->id); - if ($status !== 'accepted') { - $message = sprintf( - _('Sie wurden von der Warteliste der Veranstaltung **%s** gestrichen und sind damit __nicht__ zugelassen worden.'), - $this->getFullName() - ); - } else { - $message = sprintf( - _('Sie wurden aus der Veranstaltung **%s** gestrichen und sind damit __nicht__ zugelassen worden.'), - $this->getFullName() - ); - } - restoreLanguage(); - $messaging->insert_message( - $message, - $user->username, - '____%system%____', - false, - false, - '1', - false, - sprintf('%s %s', _('Systemnachricht:'), _('nicht zugelassen in Veranstaltung')), - true - ); - StudipLog::log('SEM_USER_DEL', $this->getId(), $user->id, 'Wurde aus der Veranstaltung entfernt'); - NotificationCenter::postNotification('UserDidLeaveCourse', $this->getId(), $user->id); - - $msgs[] = $user->getFullName(); - } - } - return $msgs; - } - - /** - * Cancels a subscription to a course - * @param array $users - * @return array - * @throws Exception - */ - public function cancelSubscription(array $users): array - { - $msgs = []; - $messaging = new messaging; - $users = User::findMany($users); - foreach ($users as $user) { - // delete member from seminar - if ($this->deleteMember($user->id)) { - setTempLanguage($user->id); - $message = sprintf( - _('Ihre Anmeldung zur Veranstaltung **%s** wurde aufgehoben.'), - $this->getFullName() - ); - restoreLanguage(); - $messaging->insert_message( - $message, - $user->username, - '____%system%____', - false, - false, - '1', - false, - sprintf('%s %s', _('Systemnachricht:'), _("Anmeldung aufgehoben")), - true - ); - $msgs[] = $user->getFullName(); - } - } - - return $msgs; - } - - /** - * deletes a user from the seminar by respecting the rule that at least one - * user with status "dozent" must stay there - * @param string $user_id user_id of the user to delete - * @return boolean - */ - public function deleteMember($user_id): bool - { - $dozenten = $this->getMembers(); - if (count($dozenten) >= 2 || empty($dozenten[$user_id])) { - $result = CourseMember::deleteBySQL('Seminar_id = ? AND user_id = ?', [$this->id, $user_id]); - if ($result === 0) { - return true; - } - // If this course is a child of another course... - if ($this->parent_course) { - // ... check if user is member in another sibling ... - $other = CourseMember::countBySQL( - "`user_id` = :user AND `Seminar_id` IN (:courses) AND `Seminar_id` != :this", - ['user' => $user_id, 'courses' => $this->parent->children->pluck('seminar_id'), 'this' => $this->id] - ); - - // ... and delete from parent course if this was the only - // course membership in this family. - if ($other === 0) { - $s = new Seminar($this->parent); - $s->deleteMember($user_id); - } - } - - if ($this->children != null) { - foreach ($this->children as $child) { - $s = new Seminar($child); - $s->deleteMember($user_id); - } - } - - if (!empty($dozenten[$user_id])) { - $query = "SELECT termin_id FROM termine WHERE range_id = ?"; - $statement = DBManager::get()->prepare($query); - $statement->execute([$this->id]); - $termine = $statement->fetchAll(PDO::FETCH_COLUMN); - - $query = "DELETE FROM termin_related_persons WHERE range_id = ? AND user_id = ?"; - $statement = DBManager::get()->prepare($query); - - foreach ($termine as $termin_id) { - $statement->execute([$termin_id, $user_id]); - } - if (Deputy::isActivated()) { - $other_dozenten = array_diff(array_keys($dozenten), [$user_id]); - foreach (Deputy::findByRange_id($user_id) as $default_deputy) { - if ($default_deputy->user_id != $GLOBALS['user']->id && - !Deputy::countBySql("range_id IN (?)", [$other_dozenten])) { - Deputy::deleteBySQL("range_id = ? AND user_id = ?", [$this->id, $default_deputy->user_id]); - } - } - } - } - - // Delete course related datafield entries - DatafieldEntryModel::deleteBySQL('range_id = ? AND sec_range_id = ?', [$user_id, $this->id]); - - // Remove from associated status groups - foreach (Statusgruppen::findBySeminar_id($this->id) as $group) { - $group->removeUser($user_id, true); - } - - $this->createMessage(sprintf( - _('Nutzer %s wurde aus der Veranstaltung entfernt.'), - '<i>' . htmlReady(get_fullname($user_id)) . '</i>' - )); - NotificationCenter::postNotification('CourseDidChangeMember', $this, $user_id); - NotificationCenter::postNotification('UserDidLeaveCourse', $this->id, $user_id); - StudipLog::log('SEM_USER_DEL', $this->id, $user_id, 'Wurde aus der Veranstaltung entfernt'); - $this->course->resetRelation('members'); - return true; - } else { - $this->createError( - sprintf( - _('Die Veranstaltung muss wenigstens <b>einen/eine</b> VeranstaltungsleiterIn (%s) eingetragen haben!'), - get_title_for_status('dozent', 1, $this->status) - ) - . ' ' . _('Tragen Sie zunächst einen anderen ein, um diesen zu löschen.') - ); - return false; - } - } - - /** - * sets the almost never used column position in the table seminar_user - * @param array $members members array: array of user_id's - wrong IDs will be ignored - * @return Seminar - */ - public function setMemberPriority($members): Seminar - { - CourseMember::findEachBySQL( - function (CourseMember $membership) use (&$members) { - $membership->position = array_search($membership->user_id, $members); - $membership->store(); - }, - "Seminar_id = ? AND user_id IN (?)", - [$this->id, $members] - ); - return $this; - } - - /** - * returns array with information about enrolment to this course for given user_id - * ['enrolment_allowed'] : true or false - * ['cause']: keyword to describe the cause - * ['description'] : readable description of the cause - * - * @param string $user_id - * @return array - */ - public function getEnrolmentInfo($user_id) - { - $info = []; - $user = User::find($user_id); - if ($this->getSemClass()->isGroup()) { - $info['enrolment_allowed'] = false; - $info['cause'] = 'grouped'; - $info['description'] = _("Dies ist eine Veranstaltungsgruppe. Sie können sich nur in deren Unterveranstaltungen eintragen."); - return $info; - } - if ($this->read_level == 0 && Config::get()->ENABLE_FREE_ACCESS && !$GLOBALS['perm']->get_studip_perm($this->getId(), $user_id)) { - $info['enrolment_allowed'] = true; - $info['cause'] = 'free_access'; - $info['description'] = _("Für die Veranstaltung ist keine Anmeldung erforderlich."); - return $info; - } - if (!$user) { - $info['enrolment_allowed'] = false; - $info['cause'] = 'nobody'; - $info['description'] = _("Sie sind nicht in Stud.IP angemeldet."); - return $info; - } - if ($GLOBALS['perm']->have_perm('root', $user_id)) { - $info['enrolment_allowed'] = true; - $info['cause'] = 'root'; - $info['description'] = _("Sie dürfen ALLES."); - return $info; - } - if ($GLOBALS['perm']->have_studip_perm('admin', $this->getId(), $user_id)) { - $info['enrolment_allowed'] = true; - $info['cause'] = 'courseadmin'; - $info['description'] = _("Sie sind Administrator_in der Veranstaltung."); - return $info; - } - if ($GLOBALS['perm']->have_perm('admin', $user_id)) { - $info['enrolment_allowed'] = false; - $info['cause'] = 'admin'; - $info['description'] = _("Als Administrator_in können Sie sich nicht für eine Veranstaltung anmelden."); - return $info; - } - //Ist bereits Teilnehmer - if ($GLOBALS['perm']->have_studip_perm('user', $this->getId(), $user_id)) { - $info['enrolment_allowed'] = true; - $info['cause'] = 'member'; - $info['description'] = _("Sie sind für die Veranstaltung angemeldet."); - return $info; - } - $admission_status = $user->admission_applications->findBy('seminar_id', $this->getId())->val('status'); - if ($admission_status == 'accepted') { - $info['enrolment_allowed'] = false; - $info['cause'] = 'accepted'; - $info['description'] = _("Sie wurden für diese Veranstaltung vorläufig akzeptiert."); - return $info; - } - if ($admission_status == 'awaiting') { - $info['enrolment_allowed'] = false; - $info['cause'] = 'awaiting'; - $info['description'] = _("Sie stehen auf der Warteliste für diese Veranstaltung."); - return $info; - } - if ($GLOBALS['perm']->get_perm($user_id) == 'user') { - $info['enrolment_allowed'] = false; - $info['cause'] = 'user'; - $info['description'] = _("Sie haben nicht die erforderliche Berechtigung sich für eine Veranstaltung anzumelden."); - return $info; - } - //falsche Nutzerdomäne - $same_domain = true; - $user_domains = UserDomain::getUserDomainsForUser($user_id); - if (count($user_domains) > 0) { - $seminar_domains = UserDomain::getUserDomainsForSeminar($this->getId()); - $same_domain = UserDomain::checkUserVisibility($seminar_domains, $user_domains);; - } - if (!$same_domain && !$this->isStudygroup()) { - $info['enrolment_allowed'] = false; - $info['cause'] = 'domain'; - $info['description'] = _("Sie sind nicht in einer zugelassenenen Nutzerdomäne, Sie können sich nicht eintragen!"); - return $info; - } - //Teilnehmerverwaltung mit Sperregel belegt - if (LockRules::Check($this->getId(), 'participants')) { - $info['enrolment_allowed'] = false; - $info['cause'] = 'locked'; - $lockdata = LockRules::getObjectRule($this->getId()); - $info['description'] = _("In diese Veranstaltung können Sie sich nicht eintragen!") . ($lockdata['description'] ? '<br>' . formatLinks($lockdata['description']) : ''); - return $info; - } - //Veranstaltung unsichtbar für aktuellen Nutzer - if (!$this->visible && !$this->isStudygroup() && !$GLOBALS['perm']->have_perm(Config::get()->SEM_VISIBILITY_PERM, $user_id)) { - $info['enrolment_allowed'] = false; - $info['cause'] = 'invisible'; - $info['description'] = _("Die Veranstaltung ist gesperrt, Sie können sich nicht eintragen!"); - return $info; - } - if ($courseset = $this->getCourseSet()) { - $info['enrolment_allowed'] = true; - $info['cause'] = 'courseset'; - $info['description'] = _("Die Anmeldung zu dieser Veranstaltung folgt speziellen Regeln. Lesen Sie den Hinweistext."); - $user_prio = AdmissionPriority::getPrioritiesByUser($courseset->getId(), $user_id); - if (isset($user_prio[$this->getId()])) { - if ($courseset->hasAdmissionRule('LimitedAdmission')) { - $info['description'] .= ' ' . sprintf(_("(Sie stehen auf der Anmeldeliste für die automatische Platzverteilung mit der Priorität %s.)"), $user_prio[$this->getId()]); - } else { - $info['description'] .= ' ' . _("(Sie stehen auf der Anmeldeliste für die automatische Platzverteilung.)"); - } - } - return $info; - } - $info['enrolment_allowed'] = true; - $info['cause'] = 'normal'; - $info['description'] = ''; - return $info; - } - - /** - * adds user with given id as preliminary member to course - * - * @param string $user_id - * @return integer 1 if successfull - */ - public function addPreliminaryMember($user_id, $comment = '') - { - $new_admission_member = new AdmissionApplication(); - $new_admission_member->user_id = $user_id; - $new_admission_member->position = 0; - $new_admission_member->status = 'accepted'; - $new_admission_member->comment = $comment; - $this->course->admission_applicants[] = $new_admission_member; - $ok = $new_admission_member->store(); - if ($ok && $this->isStudygroup()) { - StudygroupModel::applicationNotice($this->getId(), $user_id); - } - $cs = $this->getCourseSet(); - if ($cs) { - $prio_delete = AdmissionPriority::unsetPriority($cs->getId(), $user_id, $this->getId()); - } - // LOGGING - StudipLog::log('SEM_USER_ADD', $this->getId(), $user_id, 'accepted', 'Vorläufig akzeptiert'); - return $ok; - } - - /** - * returns courseset object for this course - * - * @return CourseSet courseset object or null - */ - public function getCourseSet() - { - if ($this->course_set === null) { - $this->course_set = CourseSet::getSetForCourse($this->id); - if ($this->course_set === null) { - $this->course_set = false; - } - } - return $this->course_set ?: null; - } - - /** - * returns true if the number of participants of this course is limited - * - * @return boolean - */ - public function isAdmissionEnabled() - { - $cs = $this->getCourseSet(); - return ($cs && $cs->isSeatDistributionEnabled()); - } - - /** - * returns the number of free seats in the course or true if not limited - * - * @return integer - */ - public function getFreeAdmissionSeats() - { - if ($this->isAdmissionEnabled()) { - return $this->course->getFreeSeats(); - } else { - return true; - } - } - - /** - * returns true if the course is locked - * - * @return boolean - */ - public function isAdmissionLocked() - { - $cs = $this->getCourseSet(); - return ($cs && $cs->hasAdmissionRule('LockedAdmission')); - } - - /** - * returns true if the course is password protected - * - * @return boolean - */ - public function isPasswordProtected() - { - $cs = $this->getCourseSet(); - return ($cs && $cs->hasAdmissionRule('PasswordAdmission')); - } - - /** - * returns array with start and endtime of course enrolment timeframe - * return null if there is no timeframe - * - * @return array assoc array with start_time end_time as keys timestamps as values - */ - public function getAdmissionTimeFrame() - { - $cs = $this->getCourseSet(); - return ($cs && $cs->hasAdmissionRule('TimedAdmission')) ? - ['start_time' => $cs->getAdmissionRule('TimedAdmission')->getStartTime(), - 'end_time' => $cs->getAdmissionRule('TimedAdmission')->getEndTime()] : []; - } - - /** - * returns StudipModule object for given slot, null when deactivated or not available - * - * @param string $slot - * @return StudipModule|null - */ - public function getSlotModule($slot): ?StudipModule - { - $module = 'Core' . ucfirst($slot); - if ($this->course->isToolActive($module)) { - return PluginEngine::getPlugin($module); - } - return null; - } - - /** - * adds user with given id on waitinglist - * - * @param string $user_id - * @param string $which_end 'last' or 'first' - * @return integer|bool number on waitlist or false if not successful - */ - public function addToWaitlist($user_id, $which_end = 'last') - { - if (AdmissionApplication::exists([$user_id, $this->id]) || CourseMember::find([$this->id, $user_id])) { - return false; - } - switch ($which_end) { - // Append users to waitlist end. - case 'last': - $maxpos = DBManager::get()->fetchColumn("SELECT MAX(`position`) - FROM `admission_seminar_user` - WHERE `seminar_id`=? - AND `status`='awaiting'", [$this->id]); - $waitpos = $maxpos+1; - break; - // Prepend users to waitlist start. - case 'first': - default: - // Move all others on the waitlist up by the number of people to add. - AdmissionApplication::renumberAdmission($this->id); - $waitpos = 1; - } - $new_admission_member = new AdmissionApplication(); - $new_admission_member->user_id = $user_id; - $new_admission_member->position = $waitpos; - $new_admission_member->status = 'awaiting'; - $new_admission_member->seminar_id = $this->id; - if ($new_admission_member->store()) { - StudipLog::log('SEM_USER_ADD', $this->id, $user_id, 'awaiting', 'Auf Warteliste gesetzt, Position: ' . $waitpos); - $this->course->resetRelation('admission_applicants'); - return $waitpos; - } - return false; - } -} |
