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/AutoInsert.php | |
| parent | da0022e5c1abbf9825ae76debaabdff7e8623bb4 (diff) | |
| parent | 97a188592c679890a25c37ab78463add76a52ff7 (diff) | |
Merge branch 'main' into issue-3911issue-3911
Diffstat (limited to 'lib/classes/AutoInsert.php')
| -rw-r--r-- | lib/classes/AutoInsert.php | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/lib/classes/AutoInsert.php b/lib/classes/AutoInsert.php new file mode 100644 index 0000000..b5cc005 --- /dev/null +++ b/lib/classes/AutoInsert.php @@ -0,0 +1,342 @@ +<?php +/** + * 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 Nico Müller <nico.mueller@uni-oldenburg.de> + * @author Michael Riehemann <michael.riehemann@uni-oldenburg.de> + * @author Jan Hendrik Willms <jan.hendrik.willms@uni-oldenburg.de> + * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 + * @category Stud.IP + * @since 2.1 + */ + +/** + * AutoInsert.php + * Provides functions required by StEP00216: + * - Assign seminars for automatic registration of certain user types + * - Maintenance of registration rules + * + * Example of use: + * @code + * + * # show all auto insert seminars + * $auto_sems = AutoInsert::getAllSeminars(); + * + * # Save a new auto insert seminar with the user status + * AutoInsert::saveSeminar($sem_id, $rechte); + * + * @endcode + */ +class AutoInsert +{ + private static $instance = null; + protected static $seminar_cache = null; + + private $settings = []; + + public static function instance() + { + if (self::$instance === null) { + self::$instance = new self(); + } + return self::$instance; + } + + public function __construct() + { + $this->loadSettings(); + } + + private function loadSettings() + { + $query = "SELECT a.seminar_id, GROUP_CONCAT(a.status,IF(LENGTH(a.domain_id)=0,':keine',CONCAT(':',a.domain_id))) AS domain_status, s.Name, s.Schreibzugriff, s.start_time "; + $query .= "FROM auto_insert_sem a "; + $query .= "JOIN seminare AS s USING (Seminar_id) "; + $query .= "GROUP BY s.seminar_id "; + $query .= "ORDER BY s.Name"; + $statement = DBManager::get()->query($query); + $results = $statement->fetchAll(PDO::FETCH_ASSOC); + foreach ($results as $result) { + if ($result['Schreibzugriff'] < 3) { + $domains = explode(',', $result['domain_status']); + + foreach ($domains as $domain) { + $array = explode(':', $domain); + $key = $array[1] . '.' . $array[0]; + $this->settings[$key][$result['seminar_id']] = ['Seminar_id' => $result['seminar_id'], + 'name' => $result['Name'], + 'Schreibzugriff' => $result['Schreibzugriff'], + 'start_time' => $result['start_time']]; + } + } + } + } + + + private function getUserSeminars($user_id, $seminare) + { + $statement = DBManager::get()->prepare("SELECT Seminar_id,s.name,s.Schreibzugriff,s.start_time,su.status + FROM seminar_user su + INNER JOIN seminare s USING(Seminar_id) + WHERE user_id = ? AND Seminar_id IN(?)"); + $statement->execute([$user_id, $seminare]); + return $statement->fetchAll(PDO::FETCH_ASSOC); + } + + /** + * Trägt den Benutzer in den Eingestellten veranstaltungen automatisch ein. + * @param string $user_id + * @param string|bool $status Wenn Status nicht angegeben wird, wird der Status des Users aus user_id genommen + * @return array 'added' Namen der Seminare in die der User eingetragen wurde + * array 'removed' Namen der Seminare aus denen der User ausgetragen wurde + */ + public function saveUser($user_id, $status = false) + { + $domains = []; + if (!$status) { + $status = $GLOBALS['perm']->get_perm($user_id); + } + foreach (UserDomain::getUserDomainsForUser($user_id) as $d) { + $domains [] = $d->id; //Domains des Users + } + + if (count($domains) === 0) { + $domains [] = 'keine'; + } + $settings = []; + $all_seminare = []; + foreach ($domains as $domain) { + + $key = $domain . '.' . $status; + if (is_array($this->settings[$key])) { + foreach ($this->settings[$key] as $id => $value) { + $settings[$id] = $value; + } + } + foreach ($this->settings as $key) { + foreach ($key as $id => $sem) { + $all_seminare[$id] = $sem; + } + } + } + + $seminare = []; + $seminare_tutor_dozent = []; + foreach ($this->getUserSeminars($user_id, array_keys($all_seminare)) as $sem) { + $seminare[$sem['Seminar_id']] = $sem; + if (in_array($sem['status'], ['tutor', 'dozent'])) { + $seminare_tutor_dozent[$sem['Seminar_id']] = $sem; + } + } + $toAdd = array_diff_key($settings, $seminare); + $toRemove = array_diff_key($all_seminare, $toAdd, $settings, $seminare_tutor_dozent); + + $added = []; + $removed = []; + + foreach ($toAdd as $id => $seminar) { + if ($this->addUser($user_id, $seminar)) $added[] = $seminar['name']; + } + foreach ($toRemove as $id => $seminar) { + if ($this->removeUser($user_id, $seminar)) $removed[] = $seminar['name']; + } + + return ['added' => $added, 'removed' => $removed]; + } + + private function addUser($user_id, $seminar) + { + return CourseMember::insertCourseMember($seminar['Seminar_id'], $user_id, 'autor'); + } + + private function removeUser($user_id, $seminar) + { + $rows = CourseMember::deleteBySQL(' user_id = ? AND Seminar_id = ?', [$user_id, $seminar['Seminar_id']]); + $statusgruppe_rows = StatusgruppeUser::deleteBySQL( + 'user_id = ? AND statusgruppe_id IN (SELECT statusgruppe_id FROM statusgruppen WHERE range_id = ?)', + [$user_id, $seminar['Seminar_id']] + ); + if ($rows > 0 || $statusgruppe_rows > 0) return true; + + return false; + } + + /** + * Tests if a seminar already has an autoinsert record + * @param string $seminar_id Id of the seminar + * @return bool Indicating whether the seminar already has an autoinsert record + */ + public static function checkSeminar($seminar_id, $domain_id = false) + { + $cached = self::getSeminarCache(); + + if (!isset($cached[$seminar_id])) { + $query = "SELECT domain_id, 1 + FROM auto_insert_sem + WHERE seminar_id = ?"; + $cached[$seminar_id] = DBManager::get()->fetchGroupedPairs( + $query, + [$seminar_id], + function ($value) { + return (bool) $value; + } + ); + } + + return array_key_exists($domain_id ?: '', $cached[$seminar_id]) + ? $cached[$seminar_id][$domain_id ?: ''] + : false; + } + + /** + * Enables a seminar for autoinsertion of users with the given status(ses) + * @param string $seminar_id Id of the seminar + * @param mixed $status Either a single string or an array of strings + * containing the status(ses) to enable for + * autoinsertion + */ + public static function saveSeminar($seminar_id, $status, $domain_id) + { + $query = "INSERT INTO auto_insert_sem (seminar_id, status,domain_id) VALUES (?, ?,?)"; + $statement = DBManager::get()->prepare($query); + + foreach ((array)$status as $s) { + $statement->execute([$seminar_id, $s, $domain_id]); + } + } + + /** + * Updates an autoinsert record for a given seminar, dependent on the + * parameter $remove it either inserts or removes the record for the given + * parameters + * + * @param string $seminar_id Id of the seminar + * @param string $status Status for autoinsertion + * @param bool $remove Whether the record should be added or removed + */ + public static function updateSeminar($seminar_id, $domain, $status, $remove = false) + { + $query = $remove ? "DELETE FROM auto_insert_sem WHERE seminar_id = ? AND status= ? AND domain_id = ?" : "INSERT IGNORE INTO auto_insert_sem (seminar_id, status,domain_id) VALUES (?, ?, ?)"; + $statement = DBManager::get()->prepare($query); + $statement->execute([$seminar_id, $status, $domain]); + + if ($remove) { + unset(self::getSeminarCache()[$seminar_id]); + } + } + + /** + * Removes a seminar from the autoinsertion process. + * @param string $seminar_id Id of the seminar + */ + public static function deleteSeminar($seminar_id): bool + { + $query = "DELETE FROM auto_insert_sem WHERE seminar_id = ?"; + $statement = DBManager::get()->prepare($query); + $result = $statement->execute([$seminar_id]); + + unset(self::getSeminarCache()[$seminar_id]); + + return $result > 0; + } + + /** + * Returns a list of all seminars enabled for autoinsertion + * @param bool Indicates whether only the seminar ids (true) or the full + * dataset shall be returned (false) + * @return array The list of all enabled seminars (format according to $only_sem_id) + */ + public static function getAllSeminars($only_sem_id = false) + { + if ($only_sem_id) { + $query = "SELECT DISTINCT seminar_id FROM auto_insert_sem"; + $statement = DBManager::get()->query($query); + $results = $statement->fetchAll(PDO::FETCH_COLUMN); + } else { + $query = "SELECT a.seminar_id, GROUP_CONCAT(a.status,IF(LENGTH(a.domain_id)=0,':keine',CONCAT(':',a.domain_id))) AS domain_status, s.Name, s.Schreibzugriff, s.start_time "; + $query .= "FROM auto_insert_sem a "; + $query .= "JOIN seminare AS s USING (Seminar_id) "; + + $query .= "GROUP BY s.seminar_id "; + $query .= "ORDER BY s.Name"; + $statement = DBManager::get()->query($query); + $results = $statement->fetchAll(PDO::FETCH_ASSOC); + foreach ($results as $index => $result) { + $domains = explode(',', $result['domain_status']); + foreach ($domains as $domain) { + $array = explode(':', $domain); + $results[$index]['status'][$array[1]][] = $array[0]; + } + } + } + + return $results; + } + + /** + * Returns a seminar's info for autoinsertion + * @param string $seminar_id Id of the seminar + * @return array The seminar's data as an associative array + */ + public static function getSeminar($seminar_id) + { + $query = "SELECT a.seminar_id, GROUP_CONCAT(a.status) AS status, s.Name "; + $query .= "FROM auto_insert_sem a "; + $query .= "JOIN seminare AS s USING (Seminar_id) "; + $query .= "WHERE a.seminar_id = ? "; + $query .= "GROUP BY s.seminar_id"; + $statement = DBManager::get()->prepare($query); + $statement->execute([$seminar_id]); + + $result = $statement->fetch(PDO::FETCH_ASSOC); + $result['status'] = explode(',', $result['status']); + return $result; + } + + /** + * Store the user's automatic registration in a seminar redundantly to + * avoid an annoying reregistration although the user explicitely left the + * according seminar + * @param string $user_id Id of the user + * @param string $seminar_id Id of the seminar + */ + public static function saveAutoInsertUser($seminar_id, $user_id) + { + $query = "INSERT IGNORE INTO auto_insert_user (Seminar_id, user_id, mkdate) + SELECT ?, user_id, UNIX_TIMESTAMP() + FROM auth_user_md5 + WHERE user_id = ? AND perms NOT IN ('root','admin')"; + return DBManager::get()->execute($query, [$seminar_id, $user_id]); + } + + /** + * Tests whether a user was already automatically registered for a certain + * seminar. + * @param string $seminar_id Id of the seminar + * @param string $user_id If of the user + * @return bool Indicates whether the user was already registered + */ + public static function checkAutoInsertUser($seminar_id, $user_id) + { + $query = "SELECT 1 FROM auto_insert_user WHERE seminar_id = ? AND user_id = ?"; + $statement = DBManager::get()->prepare($query); + $statement->execute([$seminar_id, $user_id]); + $result = $statement->fetchColumn(); + + return $result > 0; + } + + /** + * Returns the cache for seminars. + */ + protected static function getSeminarCache(): StudipCachedArray + { + if (self::$seminar_cache === null) { + self::$seminar_cache = new StudipCachedArray('AutoInsertSeminars'); + } + return self::$seminar_cache; + } +} |
