diff options
Diffstat (limited to 'lib/classes/admission/CourseSet.class.php')
| -rw-r--r-- | lib/classes/admission/CourseSet.class.php | 1185 |
1 files changed, 0 insertions, 1185 deletions
diff --git a/lib/classes/admission/CourseSet.class.php b/lib/classes/admission/CourseSet.class.php deleted file mode 100644 index d94bc05..0000000 --- a/lib/classes/admission/CourseSet.class.php +++ /dev/null @@ -1,1185 +0,0 @@ -<?php - -/** - * CourseSet.class.php - * - * Represents groups of Stud.IP courses that have common rules for admission. - * - * 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 Thomas Hackl <thomas.hackl@uni-passau.de> - * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 - * @category Stud.IP - */ - -class CourseSet -{ - // --- ATTRIBUTES --- - - /** - * Admission rules that are applied to the courses belonging to this set. - */ - protected $admissionRules = []; - - /** - * Seat distribution algorithm. - */ - protected $algorithm = null; - - /** - * IDs of courses that are aggregated into this set. The array is in the - * form ($courseId1 => true, $courseId2 => true). - */ - protected $courses = []; - - /** - * Has the seat distribution algorithm already been executed? - */ - protected $hasAlgorithmRun = false; - - /** - * Unique identifier for this set. - */ - protected $id = ''; - - /** - * Some extensive descriptional text for informing confused students. - */ - protected $infoText = ''; - - /** - * Which Stud.IP institute does the course set belong to? - */ - protected $institutes = []; - - /** - * Some display name for this course set. - */ - protected $name = ''; - - /** - * Is the course set only visible for the creator? - */ - protected $private = false; - - /** - * Who owns this course set? - */ - protected $user_id = false; - - /** - * When was the course set changed? - */ - protected $chdate = null; - - /* - * Lists of users who are treated differently on seat distribution - */ - protected $userlists = []; - - // --- OPERATIONS --- - - public function __construct($setId='') { - $this->id = $setId; - $this->name = _("Anmeldeset"); - $this->algorithm = new RandomAlgorithm(); - // Autoload admission rules. - AdmissionRule::getAvailableAdmissionRules(); - // Define autoload function for admission rules. - spl_autoload_register(['UserFilterField', 'getAvailableFilterFields']); - if ($setId) { - $this->load(); - } - } - - /** - * Adds the given admission rule to the list of rules for the course set. - * - * @param AdmissionRule rule - * @return CourseSet - */ - public function addAdmissionRule($rule) - { - $this->admissionRules[$rule->getId()] = $rule; - return $this; - } - - /** - * Adds the course with the given ID to the course set. - * - * @param String courseId - * @return CourseSet - */ - public function addCourse($courseId) - { - $this->courses[$courseId] = true; - return $this; - } - - /** - * Adds a new institute ID. - * - * @param String newId - * @return CourseSet - */ - public function addInstitute($newId) { - $this->institutes[$newId] = true; - return $this; - } - - /** - * Adds several institute IDs to the existing institute assignments. - * - * @param Array newIds - * @return CourseSet - */ - public function addInstitutes($newIds) { - foreach ($newIds as $newId) { - $this->addInstitute($newId); - } - return $this; - } - - /** - * Adds a UserList to the course set. The list contains several users and a - * factor that changes seat distribution chances for these users; - * - * @param String listId - * @return CourseSet - */ - public function addUserList($listId) - { - $this->userlists[$listId] = true; - return $this; - } - - /** - * Is the given user allowed to register as participant in the given - * course according to the rules of this course set? - * - * @param String userId - * @param String courseId - * @return Array Optional error messages from rules if something went wrong. - */ - public function checkAdmission($userId, $courseId) { - $errors = []; - foreach ($this->admissionRules as $rule) { - // All rules must be fulfilled. - $ruleCheck = $rule->ruleApplies($userId, $courseId); - if ($ruleCheck) { - $errors = array_merge($errors, $ruleCheck); - } - } - return $errors; - } - - /** - * Removes all admission rules at once. - * - * @return CourseSet - */ - public function clearAdmissionRules() { - $this->admissionRules = []; - return $this; - } - - /** - * Deletes the course set and all associated data. - */ - public function delete() { - NotificationCenter::postNotification('CourseSetWillDelete', $this->id, $GLOBALS['user']->id); - // Delete institute associations. - $stmt = DBManager::get()->prepare("DELETE FROM `courseset_institute` - WHERE `set_id`=?"); - $stmt->execute([$this->id]); - // Delete course associations. - $stmt = DBManager::get()->prepare("DELETE FROM `seminar_courseset` - WHERE `set_id`=?"); - $stmt->execute([$this->id]); - // Delete all rules... - foreach ($this->admissionRules as $rule) { - $rule->delete(); - } - // ... and their association to the current course set. - $stmt = DBManager::get()->prepare("DELETE FROM `courseset_rule` - WHERE `set_id`=?"); - $stmt->execute([$this->id]); - // Delete associations to user lists. - $stmt = DBManager::get()->prepare("DELETE FROM `courseset_factorlist` - WHERE `set_id`=?"); - $stmt->execute([$this->id]); - // Delete course set data. - $stmt = DBManager::get()->prepare("DELETE FROM `coursesets` - WHERE `set_id`=?"); - $stmt->execute([$this->id]); - /* - * Delete waiting lists - */ - foreach ($this->courses as $id => $assigned) { - AdmissionApplication::deleteBySQL("status='awaiting' AND seminar_id=?", [$id]); - } - //Delete priorities - AdmissionPriority::unsetAllPriorities($this->getId()); - NotificationCenter::postNotification('CourseSetDidDelete', $this->id, $GLOBALS['user']->id); - } - - /** - * Starts the seat distribution algorithm. - */ - public function distributeSeats() { - if ($this->algorithm) { - // Call pre-distribution hooks on all assigned rules. - foreach ($this->admissionRules as &$rule) { - $rule->beforeSeatDistribution($this); - } - $this->algorithm->run($this); - // Mark as "seats distributed". - $this->setAlgorithmRun(true); - // Call post-distribution hooks on all assigned rules. - foreach ($this->admissionRules as &$rule) { - $rule->afterSeatDistribution($this); - } - AdmissionPriority::unsetAllPriorities($this->getId()); - } - } - - public function setAlgorithmRun($state) - { - NotificationCenter::postNotification('CourseSetAlgorithmWillStart', $state, $this->getId()); - $this->hasAlgorithmRun = (bool)$state; - $db = DBManager::get(); - $ok = $db->execute("UPDATE coursesets SET algorithm_run = ? WHERE set_id = ?", [$this->hasAlgorithmRun, $this->getId()]); - if ($ok) { - NotificationCenter::postNotification('CourseSetAlgorithmDidStart', $state, $this->getId()); - } - return $ok; - } - - /** - * returns true if the set allows only a limited number of places - * - * @return boolean - */ - public function isSeatDistributionEnabled() - { - return $this->getSeatDistributionTime() !== null; - } - - /** - * returns timestamp of distribution time or null if no distribution time available - * may return 0 if first-come-first-serve is enabled - * - * @return integer|null timestamp of distribution - */ - public function getSeatDistributionTime() - { - $pr_admission = $this->getAdmissionRule('ParticipantRestrictedAdmission'); - if ($pr_admission) { - return $pr_admission->getDistributionTime(); - } - } - - /** - * Get all admission rules belonging to the course set. - * - * @return AdmissionRule[] - */ - public function getAdmissionRules() - { - return $this->admissionRules; - } - - public function getAdmissionRule($class_name) - { - $result = array_filter($this->getAdmissionRules(), function($r) use ($class_name) { - return $r instanceof $class_name;} - ); - return array_pop($result); - } - /** - * check if course set has given admission rule - * - * @param string $rule name of AdmissionRule class - * @return boolean - */ - public function hasAdmissionRule($rule) - { - return is_object($this->getAdmissionRule($rule)); - } - - /** - * Get the currently used distribution algorithm. - * - * @return AdmissionAlgorithm - */ - public function getAlgorithm() - { - return $this->algorithm; - } - - /** - * How many users will be allowed to register according to the defined - * rules? This can help in estimating whether the combination of the - * defined rules makes sense. - * - * @return int - */ - public function getAllowedUserCount() - { - $users = []; - foreach ($this->admissionRules as $rule) { - $users = array_merge($users, $rule->getAffectedUsers()); - } - return sizeof($users); - } - - /** - * Gets the course IDs belonging to the course set. - * - * @return Array - */ - public function getCourses() - { - return array_keys($this->courses); - } - - /** - * Gets all courses belonging to the given course set ID. - * - * @param String $courseSetId - * @return Array - */ - public static function getCoursesByCourseSetId($courseSetId) - { - $query = "SELECT `seminar_id` - FROM `seminar_courseset` - WHERE `set_id` = ?"; - $stmt = DBManager::get()->prepare($query); - $stmt->execute([$courseSetId]); - return $stmt->fetchAll(PDO::FETCH_ASSOC); - } - - /** - * Gets all course sets belonging to the given institute ID. - * - * @param String $instituteId - * @return Array - */ - public static function getCoursesetsByInstituteId($instituteId, $filter = []) { - $query = "SELECT DISTINCT ci.* - FROM `courseset_institute` ci - JOIN `coursesets` c ON (ci.`set_id`=c.`set_id`) - LEFT JOIN courseset_rule cr ON cr.set_id=ci.set_id - LEFT JOIN seminar_courseset sc ON c.set_id = sc.set_id - LEFT JOIN seminare s ON s.seminar_id = sc.seminar_id - WHERE ci.`institute_id`=?"; - $parameters = [$instituteId]; - if (!$GLOBALS['perm']->have_perm('admin')) { - $query .= " AND (c.`private`=0 OR c.`user_id`=?)"; - $parameters[] = $GLOBALS['user']->id; - } - if (!empty($filter['course_set_name'])) { - $query .= " AND c.name LIKE ?"; - $parameters[] = $filter['course_set_name'] . '%'; - } - if (!empty($filter['rule_types']) && is_array($filter['rule_types']) && count($filter['rule_types'])) { - $query .= " AND cr.type IN (?)"; - $parameters[] = $filter['rule_types']; - } - if (!empty($filter['semester_id'])) { - $query .= " AND s.start_time = ?"; - $parameters[] = Semester::find($filter['semester_id'])->beginn; - } - if (!empty($filter['course_set_chdate'])) { - $query .= " AND c.chdate > ?"; - $parameters[] = $filter['course_set_chdate']; - } - $query .= " ORDER BY c.name"; - $stmt = DBManager::get()->prepare($query); - $stmt->execute($parameters); - return $stmt->fetchAll(PDO::FETCH_ASSOC); - } - - /** - * Gets all global course sets - * - * @param array $filter - * @return Array - */ - public static function getGlobalCoursesets($filter = []) { - $query = "SELECT DISTINCT c.set_id - FROM coursesets c - LEFT JOIN courseset_institute ci ON ci.`set_id`=c.`set_id` - LEFT JOIN courseset_rule cr ON cr.set_id=ci.set_id - LEFT JOIN seminar_courseset sc ON c.set_id = sc.set_id - LEFT JOIN seminare s ON s.seminar_id = sc.seminar_id - WHERE ci.institute_id IS NULL"; - $parameters = []; - $query .= " AND (c.`private`=0 OR c.`user_id`=?)"; - $parameters[] = $GLOBALS['user']->id; - if (!empty($filter['course_set_name'])) { - $query .= " AND c.name LIKE ?"; - $parameters[] = $filter['course_set_name'] . '%'; - } - if (!empty($filter['rule_types']) && is_array($filter['rule_types']) && count($filter['rule_types'])) { - $query .= " AND cr.type IN (?)"; - $parameters[] = $filter['rule_types']; - } - if (!empty($filter['semester_id'])) { - $query .= " AND s.start_time = ?"; - $parameters[] = Semester::find($filter['semester_id'])->beginn; - } - if (!empty($filter['course_set_chdate'])) { - $query .= " AND c.chdate > ?"; - $parameters[] = $filter['course_set_chdate']; - } - $query .= " ORDER BY c.name"; - $stmt = DBManager::get()->prepare($query); - $stmt->execute($parameters); - return $stmt->fetchAll(PDO::FETCH_ASSOC); - } - - /** - * Get the identifier of the course set. - * - * @return String - */ - public function getId() - { - return $this->id; - } - - /** - * Get the course set's info text. - * - * @return String - */ - public function getInfoText() - { - return $this->infoText; - } - - /** - * Which institutes does the rule belong to? - * - * @return Array - */ - public function getInstituteIds() { - return $this->institutes; - } - - public function isGlobal() - { - return count($this->institutes) == 0; - } - /** - * Gets this course set's display name. - */ - public function getName() { - return $this->name; - } - - /** - * Returns the date of the last change. - * @return int - */ - public function getChdate() - { - return $this->chdate; - } - - /** - * Retrieves the priorities given to the courses in this set. - * - * @return Array - */ - public function getPriorities() - { - return AdmissionPriority::getPriorities($this->id); - } - - public function getNumApplicants() - { - return AdmissionPriority::getPrioritiesCount($this->id); - } - - /** - * Is the current courseset private? - * - * @return bool - */ - public function getPrivate() { - return $this->private; - } - - - /** - * returns latest semester id from assigned courses - * if no courses are assigned current semester - * - * @return string id of semester - */ - public function getSemester() { - $db = DBManager::get(); - $data = $db->fetchOne(" - SELECT semester_data.* - FROM semester_data - INNER JOIN semester_courses ON (semester_data.semester_id = semester_courses.semester_id) - WHERE semester_courses.course_id IN (?) - ORDER BY semester_data.ende DESC - LIMIT 1 - ", [$this->getCourses()]); - if ($data) { - $semester = Semester::buildExisting($data); - } else { - $semester = $_SESSION['_default_sem'] ? Semester::find($_SESSION['_default_sem']) : Semester::findCurrent(); - } - return $semester->id; - } - - /** - * Gets the owner of this course set. - */ - public function getUserId() { - return $this->user_id; - } - - public function setUserId($user_id) { - $this->user_id = $user_id; - return $this; - } - - /** - * Gets the course sets the given course belongs to. - * - * @param String courseId - * @return CourseSet - */ - public static function getSetForCourse($courseId) - { - $stmt = DBManager::get()->prepare("SELECT `set_id` - FROM `seminar_courseset` WHERE `seminar_id`=?"); - $stmt->execute([$courseId]); - $set_id = $stmt->fetchColumn(); - if ($set_id) { - return new CourseSet($set_id); - } - return null; - } - - /** - * Gets the course sets the given rule belongs to. - * - * @param String $rule_id - * @return CourseSet - */ - public static function getSetForRule($rule_id) - { - $set_id = DBManager::get()->fetchColumn("SELECT `set_id` - FROM `courseset_rule` WHERE `rule_id`=?", [$rule_id]); - if ($set_id) { - return new CourseSet($set_id); - } - return null; - } - - /** - * Retrieves the lists of users that are considered specially in - * seat distribution. - * - * @return Array - */ - public function getUserLists() - { - return array_keys($this->userlists); - } - - public function getUserFactorList() - { - $factored_users = []; - - foreach ($this->getUserLists() as $ul_id) { - $user_list = new AdmissionUserList($ul_id); - - // Iterate through user list. - foreach ($user_list->getUsers() as $user => $assigned) { - switch ($user_list->getFactor()) { - // Maximum factor, just set it and stop further processing of user lists. - case PHP_INT_MAX: - $factored_users[$user] = PHP_INT_MAX; - break; - // Backlist, set malus and stop further processing of user lists. - case 0: - $factored_users[$user] = 0; - break; - default: - // Add up current bonus if it isn't already at 0 or PHP_INT_MAX. - if ($factored_users[$user] !== 0 && $factored_users[$user] != PHP_INT_MAX) { - $factored_users[$user] = isset($factored_users[$user]) ? - $factored_users[$user] + $user_list->getFactor() : - $user_list->getFactor(); - } - } - } - } - - return $factored_users; - } - - /** - * Evaluates whether the seat distribution algorithm has already been - * executed on this course set. - * - * @return boolean True if algorithm has already run, otherwise false. - */ - public function hasAlgorithmRun() { - return $this->hasAlgorithmRun; - } - - /** - * Helper function for loading data from DB. - */ - public function load() { - // Load basic data. - $stmt = DBManager::get()->prepare( - "SELECT * FROM `coursesets` WHERE set_id=? LIMIT 1"); - $stmt->execute([$this->id]); - if ($data = $stmt->fetch(PDO::FETCH_ASSOC)) { - $this->name = $data['name']; - $this->infoText = $data['infotext']; - $this->hasAlgorithmRun = (bool)$data['algorithm_run']; - if ($data['algorithm']) { - if (class_exists($data['algorithm'])) { - $this->algorithm = new $data['algorithm'](); - } - } - $this->private = (bool) $data['private']; - $this->user_id = $data['user_id']; - $this->chdate = $data['chdate']; - } - // Load institute assigments. - $stmt = DBManager::get()->prepare(" - SELECT courseset_institute.institute_id - FROM `courseset_institute` - INNER JOIN Institute ON (courseset_institute.institute_id = Institute.Institut_id) - WHERE courseset_institute.set_id = ? - ORDER BY Institute.Name ASC - "); - $stmt->execute([$this->id]); - $this->institutes = []; - while ($data = $stmt->fetch(PDO::FETCH_ASSOC)) { - $this->institutes[$data['institute_id']] = true; - } - // Load courses. - $stmt = DBManager::get()->prepare( - "SELECT seminar_id FROM `seminar_courseset` WHERE set_id=?"); - $stmt->execute([$this->id]); - $this->courses = []; - while ($data = $stmt->fetch(PDO::FETCH_ASSOC)) { - $this->courses[$data['seminar_id']] = true; - } - // Load admission rules. - $stmt = DBManager::get()->prepare( - "SELECT * FROM `courseset_rule` WHERE set_id=?"); - $stmt->execute([$this->id]); - $this->admissionRules = []; - while ($data = $stmt->fetch(PDO::FETCH_ASSOC)) { - if (class_exists($data['type'])) { - $this->admissionRules[$data['rule_id']] = - new $data['type']($data['rule_id'], $this->id); - } - } - // Load assigned user lists. - $stmt = DBManager::get()->prepare("SELECT `factorlist_id` - FROM `courseset_factorlist` WHERE `set_id`=?"); - $stmt->execute([$this->id]); - $this->userlists = []; - while ($current = $stmt->fetch(PDO::FETCH_ASSOC)) { - $this->userlists[$current['factorlist_id']] = true; - } - return $this; - } - - /** - * Removes the course with the given ID from the set. - * - * @param String courseId - * @return CourseSet - */ - public function removeCourse($courseId) - { - unset($this->courses[$courseId]); - return $this; - } - - /** - * Removes the rule with the given ID from the set. - * - * @param String ruleId - * @return CourseSet - */ - public function removeAdmissionRule($ruleId) - { - unset($this->admissionRules[$ruleId]); - return $this; - } - - /** - * Removes the institute with the given ID from the set. - * - * @param String instituteId - * @return CourseSet - */ - public function removeInstitute($instituteId) - { - unset($this->institutes[$instituteId]); - return $this; - } - - /** - * Removes the user list with the given ID from the set. - * - * @param String listId - * @return CourseSet - */ - public function removeUserlist($listId) - { - unset($this->userlists[$listId]); - return $this; - } - - /** - * Adds several admission rules after clearing the existing rule - * assignments. - * - * @param Array newIds - * @return CourseSet - */ - public function setAdmissionRules($newRules) { - $this->admissionRules = []; - foreach ($newRules as $newRule) { - $rule = ObjectBuilder::build($newRule, 'AdmissionRule'); - $this->addAdmissionRule($rule); - } - return $this; - } - - /** - * Sets a seat distribution algorithm for this course set. This will only - * have an effect in conjunction with a TimedAdmission, as the algorithm - * needs a defined point in time where it will start. - * - * @param String newAlgorithm - * @return CourseSet - */ - public function setAlgorithm($newAlgorithm) - { - try { - $this->algorithm = new $newAlgorithm(); - } catch (Exception $e) { - } - return $this; - } - - /** - * Adds several course IDs after clearing the existing course - * assignments. - * - * @param Array newIds - * @return CourseSet - */ - public function setCourses($newIds) { - $this->courses = array_fill_keys($newIds, true); - return $this; - } - - /** - * Adds several institute IDs after clearing the existing institute - * assignments. - * - * @param Array newIds - * @return CourseSet - */ - public function setInstitutes($newIds) { - $this->institutes = []; - $this->addInstitutes($newIds); - return $this; - } - - /** - * Set the course set's info text. - * - * @return CourseSet - */ - public function setInfoText($newText) - { - $this->infoText = $newText; - return $this; - } - - /* Sets a new name for this course set. - * - * @param String newName - * @return CourseSet - */ - public function setName($newName) { - $this->name = $newName; - return $this; - } - - /** - * Set a new value for courseset privacy. - * - * @param bool $newPrivate - * @return CourseSet - */ - public function setPrivate($newPrivate) { - $this->private = $newPrivate; - return $this; - } - - /** - * Adds several user list IDs after clearing the existing user list - * assignments. - * - * @param Array newIds - * @return CourseSet - */ - public function setUserlists($newIds) { - $this->userlists = []; - foreach ($newIds as $newId) { - $this->addUserlist($newId); - } - return $this; - } - - public function store() { - // Generate new ID if course set doesn't exist in DB yet. - if (!$this->id) { - do { - $newid = md5(uniqid(get_class($this), true)); - $db = DBManager::get()->query("SELECT `set_id` - FROM `coursesets` WHERE `set_id`='$newid'"); - } while ($db->fetch()); - $this->id = $newid; - } - if (!$this->user_id) { - $this->user_id = $GLOBALS['user']->id; - } - if ($this->isSeatDistributionEnabled()) { - if (!$this->getAlgorithm()) { - $algorithm = new RandomAlgorithm(); - $this->setAlgorithm($algorithm); - } - if (!$this->getSeatDistributionTime()) { - $this->setAlgorithmRun(true); - //Delete priorities - AdmissionPriority::unsetAllPriorities($this->getId()); - } - if ($this->getSeatDistributionTime() > time()) { - $this->setAlgorithmRun(false); - } - } - // Store basic data. - $stmt = DBManager::get()->prepare("INSERT INTO `coursesets` - (`set_id`, `user_id`, `name`, `infotext`, `algorithm`, `algorithm_run`, - `private`, `mkdate`, `chdate`) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE - `name`=VALUES(`name`), `infotext`=VALUES(`infotext`), - `algorithm`=VALUES(`algorithm`), `algorithm_run`=VALUES(`algorithm_run`), `private`=VALUES(`private`), - `chdate`=VALUES(`chdate`)"); - $stmt->execute([$this->id, $this->user_id, $this->name, $this->infoText, - get_class($this->algorithm), $this->hasAlgorithmRun(), intval($this->private), time(), time()]); - // Delete removed institute assignments from database. - DBManager::get()->exec("DELETE FROM `courseset_institute` - WHERE `set_id`='".$this->id."' AND `institute_id` NOT IN ('". - implode("', '", array_keys($this->institutes))."')"); - // Store associated institute IDs. - foreach ($this->institutes as $institute => $associated) { - $stmt = DBManager::get()->prepare("INSERT IGNORE INTO `courseset_institute` - (`set_id`, `institute_id`, `mkdate`) - VALUES (?, ?, ?)"); - $stmt->execute([$this->id, $institute, time()]); - } - // log removed course assignments. - DBManager::get()->fetchAll("SELECT seminar_id,set_id FROM `seminar_courseset` - WHERE `set_id` = ? AND `seminar_id` NOT IN (?)", [$this->id, count($this->courses) ? array_keys($this->courses) : ''], - function ($row) { - StudipLog::log('SEM_CHANGED_ACCESS', $row['seminar_id'], - null, 'Entfernung von Anmeldeset', sprintf('Anmeldeset: %s', $row['set_id'])); - //Delete priorities - AdmissionPriority::unsetAllPrioritiesForCourse($row['seminar_id']); - Course::buildExisting(['seminar_id' => $row['seminar_id']])->triggerChdate(); - }); - //removed course assignments - DBManager::get()->execute("DELETE FROM `seminar_courseset` - WHERE `set_id` = ? AND `seminar_id` NOT IN (?)", [$this->id, count($this->courses) ? array_keys($this->courses) : '']); - //log removing other associations - DBManager::get()->execute("SELECT seminar_id,set_id FROM `seminar_courseset` - WHERE `set_id` <> ? AND `seminar_id` IN (?)", [$this->id, array_keys($this->courses)], - function ($row) { - StudipLog::log('SEM_CHANGED_ACCESS', $row['seminar_id'], - null, 'Entfernung von Anmeldeset', sprintf('Anmeldeset: %s', $row['set_id'])); - //Delete priorities - AdmissionPriority::unsetAllPrioritiesForCourse($row['seminar_id']); - Course::buildExisting(['seminar_id' => $row['seminar_id']])->triggerChdate(); - }); - //Delete other associations, only one set possible - DBManager::get()->execute("DELETE FROM `seminar_courseset` - WHERE `set_id` <> ? AND `seminar_id` IN (?)", [$this->id, array_keys($this->courses)]); - // Store associated course IDs. - foreach ($this->courses as $course => $associated) { - $stmt = DBManager::get()->prepare("INSERT IGNORE INTO `seminar_courseset` - (`set_id`, `seminar_id`, `mkdate`) - VALUES (?, ?, ?)"); - $stmt->execute([$this->id, $course, time()]); - if ($stmt->rowCount()) { - StudipLog::log('SEM_CHANGED_ACCESS', $course, - null, 'Zuordnung zu Anmeldeset', sprintf('Anmeldeset: %s', $this->id)); - Course::buildExisting(['seminar_id' => $course])->triggerChdate(); - } - } - - // Delete removed user list assignments from database. - DBManager::get()->exec("DELETE FROM `courseset_factorlist` - WHERE `set_id`='".$this->id."' AND `factorlist_id` NOT IN ('". - implode("', '", array_keys($this->userlists))."')"); - // Store associated user list IDs. - foreach ($this->userlists as $list => $associated) { - $stmt = DBManager::get()->prepare("INSERT IGNORE INTO `courseset_factorlist` - (`set_id`, `factorlist_id`, `mkdate`) - VALUES (?, ?, ?)"); - $stmt->execute([$this->id, $list, time()]); - } - // Delete removed admission rules from database. - $stmt = DBManager::get()->query("SELECT `rule_id`, `type` FROM `courseset_rule` - WHERE `set_id`='".$this->id."' AND `rule_id` NOT IN ('". - implode("', '", array_keys($this->admissionRules))."')"); - $data = $stmt->fetchAll(PDO::FETCH_ASSOC); - foreach ($data as $ruleData) { - $rule = new $ruleData['type']($ruleData['rule_id']); - $rule->delete(); - } - // Store all rules. - foreach ($this->admissionRules as $rule) { - // Store each rule... - $rule->store(); - // ... and its connection to the current course set. - $stmt = DBManager::get()->prepare("INSERT INTO `courseset_rule` - (`set_id`, `rule_id`, `type`, `mkdate`) - VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE - `type`=VALUES(`type`)"); - $stmt->execute([$this->id, $rule->getId(), get_class($rule), time()]); - } - //fix free access courses - if (count($this->courses)) { - DBManager::get()->execute("UPDATE seminare SET Lesezugriff=1,Schreibzugriff=1 WHERE seminar_id IN(?)", [array_keys($this->courses)]); - } - //create general log - $this->log_store(); - - } - - /** - * Generates a general log entry if the CourseSet rules were changed. - */ - private function log_store() - { - $text = ''; - $rule_counter = 1; - foreach ($this->getAdmissionRules() as $rule) { - $rule_text = strip_tags(kill_format($rule->toString())); - $semicolon = ($rule_counter < count($this->getAdmissionRules()) ? '; ' : ''); - $text .= '#' . $rule_counter . ' => ' . $rule_text . $semicolon; - $rule_counter++; - } - - $courses = $this->getCourses(); - foreach ($courses as $course_id) { - StudipLog::log( - 'SEM_CHANGED_ACCESS', - $course_id, - NULL, - $text, - sprintf('Anmeldeset: %s (%s)', strip_tags(kill_format(($this->name))), $this->id) - ); - } - } - - /** - * A textual description of the current rule. - * - * @param bool short Show only short info without overview of assigned - * courses and institutes. - * @return String - */ - public function toString($short=false) { - $tpl = $GLOBALS['template_factory']->open('admission/courseset/info'); - $tpl->set_attribute('courseset', $this); - $tpl->set_attribute('is_limited', false); - $institutes = []; - if (!$short) { - $institutes = Institute::findAndMapMany(function($i) {return $i->name;}, array_keys($this->institutes), 'ORDER BY Name'); - $tpl->set_attribute('institutes', $institutes); - } - if (!$short || $this->hasAdmissionRule('LimitedAdmission')) { - $courses = Course::findAndMapMany(function($c) { - return [ - 'id' => $c->id, - 'name' => $c->getFullName('number-name-semester'), - 'visible' => $c->visible - ]; - }, - array_keys($this->courses), - 'ORDER BY start_time,VeranstaltungsNummer,Name'); - if (!$GLOBALS['perm']->have_perm(Config::get()->SEM_VISIBILITY_PERM)) { - $courses = array_filter($courses, - function ($c) { - return $c['visible']; - } - ); - } - $tpl->set_attribute('is_limited', $this->hasAdmissionRule('LimitedAdmission')); - $tpl->set_attribute('courses', $courses); - } - $tpl->set_attribute('short', $short); - return $tpl->render(); - } - - public function __toString() { - return $this->toString(); - } - - /** - * is user with given user id allowed to assign/unassign given course to courseset - * - * @param string $user_id - * @param string $course_id - * @return boolean - */ - public function isUserAllowedToAssignCourse($user_id, $course_id) - { - global $perm; - $is_dozent = $perm->have_studip_perm('tutor', $course_id, $user_id); - $is_admin = $perm->have_perm('admin', $user_id) || ($perm->have_perm('dozent', $user_id) && Config::get()->ALLOW_DOZENT_COURSESET_ADMIN); - $is_private = $this->getPrivate(); - $is_my_own = $this->getUserId() == $user_id; - $is_correct_institute = $this->isGlobal() || isset($this->institutes[Course::find($course_id)->institut_id]); - return $is_dozent && $is_correct_institute && ($is_my_own || $is_admin || !$is_private || $this->isGlobal()) || $perm->have_perm('root', $user_id); - } - - /** - * is user with given user id allowed to edit or delete the courseset - * - * @param string $user_id - * @return boolean - */ - public function isUserAllowedToEdit($user_id) - { - global $perm; - - if ($this->getUserId() == '') { - return false; - } - if ($perm->have_perm('root', $user_id) || $this->getUserId() == $user_id) { - return true; - } - if (count($this->institutes) == 0 && count($this->courses) == 1 && $perm->have_studip_perm('tutor', current($this->getCourses()), $user_id)) { - return true; - } - if ($perm->have_perm('admin', $user_id) || ($perm->have_perm('dozent', $user_id) && Config::get()->ALLOW_DOZENT_COURSESET_ADMIN)) { - foreach (array_keys($this->getInstituteIds()) as $one) { - if ($perm->have_studip_perm('dozent', $one, $user_id)) { - return true; - } - } - } - return false; - } - - /** - * checks if given rule is allowed to be added to current set of rules - * - * @param AdmissionRule|string $admission_rule - * @return boolean - */ - public function isAdmissionRuleAllowed($admission_rule) - { - foreach ($this->getAdmissionRules() as $one) { - if (!$one->isCombinationAllowed($admission_rule)) { - return false; - } - } - return true; - } - - public static function getGlobalLockedAdmissionSetId() - { - $db = DBManager::get(); - $locked_set_id = $db->fetchColumn("SELECT cr.set_id FROM courseset_rule cr - INNER JOIN coursesets USING(set_id) - WHERE type='LockedAdmission' and private=1 and user_id='' LIMIT 1"); - if (!$locked_set_id) { - $cs_insert = $db->prepare("INSERT INTO coursesets (set_id,user_id,name,infotext,algorithm,private,mkdate,chdate) - VALUES (?,?,?,?,'',?,?,?)"); - $cs_r_insert = $db->prepare("INSERT INTO courseset_rule (set_id,rule_id,type,mkdate) VALUES (?,?,?,UNIX_TIMESTAMP())"); - $locked_insert = $db->prepare("INSERT INTO lockedadmissions (rule_id,message,mkdate,chdate) VALUES (?,'Die Anmeldung ist gesperrt',UNIX_TIMESTAMP(),UNIX_TIMESTAMP())"); - $locked_set_id = md5(uniqid('coursesets',1)); - $name = 'Anmeldung gesperrt (global)'; - $cs_insert->execute([$locked_set_id,'',$name,'',1,time(),time()]); - $locked_rule_id = md5(uniqid('lockedadmissions',1)); - $locked_insert->execute([$locked_rule_id]); - $cs_r_insert->execute([$locked_set_id,$locked_rule_id,'LockedAdmission']); - } - return $locked_set_id; - } - - public static function addCourseToSet($set_id, $course_id) - { - $db = DBManager::get(); - $ok = $db->execute("INSERT IGNORE INTO seminar_courseset (set_id,seminar_id,mkdate) VALUES (?,?,UNIX_TIMESTAMP())", [$set_id, $course_id]); - if ($ok) { - StudipLog::log('SEM_CHANGED_ACCESS', $course_id, - null, 'Zuordnung zu Anmeldeset', sprintf('Anmeldeset: %s', $set_id)); - $course = Course::find($course_id); - if ($course) { - $course->chdate = time(); - $course->lesezugriff = 1; - $course->schreibzugriff = 1; - $course->store(); - } - } - return $ok; - } - - public static function removeCourseFromSet($set_id, $course_id) - { - $db = DBManager::get(); - $ok = $db->execute("DELETE FROM seminar_courseset WHERE set_id=? AND seminar_id=? LIMIT 1", [$set_id, $course_id]); - if ($ok) { - StudipLog::log('SEM_CHANGED_ACCESS', $course_id, - null, 'Entfernung von Anmeldeset', sprintf('Anmeldeset: %s', $set_id)); - //Delete priorities - AdmissionPriority::unsetAllPrioritiesForCourse($course_id); - Course::buildExisting(['seminar_id' => $course_id])->triggerChdate(); - } - return $ok; - } - - public function __clone() - { - $this->courses = []; - $this->id = null; - $this->user_id = null; - $cloned_rules = []; - foreach ($this->admissionRules as $key => $rule) { - $dolly = clone $rule; - $cloned_rules[$dolly->id] = $dolly; - } - $this->admissionRules = $cloned_rules; - } - -} /* end of class CourseSet */ |
