From e3b9cd028fab555a69db4bd318ed734769ee9edb Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Willms <tleilax+studip@gmail.com> Date: Wed, 28 Sep 2022 10:04:14 +0000 Subject: [PATCH] fix and restructure MyCoursesSearch, fixes #1606 Closes #1606 Merge request studip/studip!1033 --- app/controllers/course/members.php | 10 +- .../searchtypes/MyCoursesSearch.class.php | 179 +++++++++--------- 2 files changed, 91 insertions(+), 98 deletions(-) diff --git a/app/controllers/course/members.php b/app/controllers/course/members.php index 364542b9ca6..00bdab12c98 100644 --- a/app/controllers/course/members.php +++ b/app/controllers/course/members.php @@ -483,23 +483,21 @@ class Course_MembersController extends AuthenticatedController if (!empty($this->flash['users']) || Request::getArray('users')) { $users = $this->flash['users'] ?: Request::getArray('users'); // create a usable array - foreach ($this->flash['users'] as $user => $val) { + foreach ($users as $user => $val) { if ($val) { $this->users[] = $user; } } PageLayout::setTitle( _('Zielveranstaltung auswählen')); + } elseif (Request::isXhr()) { + $this->response->add_header('X-Dialog-Close', '1'); + $this->render_nothing(); } else { - if (Request::isXhr()) { - $this->response->add_header('X-Dialog-Close', '1'); - $this->render_nothing(); - } else { $this->redirect('course/members/index'); } } } - } /** * Copies or moves selected users to the selected target course. diff --git a/lib/classes/searchtypes/MyCoursesSearch.class.php b/lib/classes/searchtypes/MyCoursesSearch.class.php index e34ba7e75b3..dad725c1413 100644 --- a/lib/classes/searchtypes/MyCoursesSearch.class.php +++ b/lib/classes/searchtypes/MyCoursesSearch.class.php @@ -16,8 +16,6 @@ class MyCoursesSearch extends StandardSearch { - public $search; - private $perm_level; private $parameters; protected $additional_sql_conditions; @@ -34,18 +32,13 @@ class MyCoursesSearch extends StandardSearch * * @return void */ - public function __construct( - $search, - $perm_level = 'dozent', - $parameters = [], - $additional_sql_conditions = '' - ) + public function __construct($search, $perm_level = 'dozent', $parameters = [], $additional_sql_conditions = '') { - $this->avatarLike = $this->search = $search; + parent::__construct($search); + $this->perm_level = $perm_level; $this->parameters = $parameters; - $this->additional_sql_conditions = $additional_sql_conditions; - $this->sql = $this->getSQL(); + $this->additional_sql_conditions = trim($additional_sql_conditions); } @@ -64,15 +57,14 @@ class MyCoursesSearch extends StandardSearch * Use the contextual_data variable to send more variables than just the input * to the SQL. QuickSearch for example sends all other variables of the same * <form>-tag here. - * @param input string: the search-word(s) - * @param contextual_data array: an associative array with more variables - * @param limit int: maximum number of results (default: all) - * @param offset int: return results starting from this row (default: 0) + * @param string $input the search-word(s) + * @param array $contextual_data an associative array with more variables + * @param int $limit maximum number of results (default: all) + * @param int $offset return results starting from this row (default: 0) * @return array: array(array(), ...) */ public function getResults($input, $contextual_data = [], $limit = PHP_INT_MAX, $offset = 0) { - $db = DBManager::get(); $sql = $this->getSQL(); if (!$sql) { return []; @@ -80,23 +72,13 @@ class MyCoursesSearch extends StandardSearch if ($offset || $limit != PHP_INT_MAX) { $sql .= sprintf(' LIMIT %d, %d', $offset, $limit); } - foreach ($this->parameters + $contextual_data as $name => $value) { - if ($name !== "input" && mb_strpos($sql, ":".$name) !== false) { - if (is_array($value)) { - if (count($value)) { - $sql = str_replace(":".$name, implode(',', array_map([$db, 'quote'], $value)), $sql); - } else { - $sql = str_replace(":".$name, "''", $sql); - } - } else { - $sql = str_replace(":".$name, $db->quote($value), $sql); - } - } - } - $statement = $db->prepare($sql, [PDO::FETCH_NUM]); - $data = []; - $data[":input"] = "%".$input."%"; - $statement->execute($data); + + $statement = DBManager::get()->prepare($sql, [PDO::FETCH_NUM]); + $statement->execute(array_merge( + $this->parameters, + $contextual_data, + [':input' => "%{$input}%"] + )); $results = $statement->fetchAll(); return $results; } @@ -116,47 +98,38 @@ class MyCoursesSearch extends StandardSearch ')' )"; + $conditions = implode(' AND ', $this->getConditions()); + switch ($this->perm_level) { // Roots see everything, everywhere. case 'root': - $query = "SELECT DISTINCT s.`Seminar_id`, CONCAT_WS(' ', s.`VeranstaltungsNummer`, s.`Name`, " . $semester_text . ") - FROM `seminare` s - LEFT JOIN semester_courses ON (s.Seminar_id = semester_courses.course_id) - LEFT JOIN `semester_data` ON (semester_data.semester_id = semester_courses.semester_id) - WHERE (s.`VeranstaltungsNummer` LIKE :input - OR s.`Name` LIKE :input) - AND s.`status` NOT IN (:semtypes) - AND s.`Seminar_id` NOT IN (:exclude) - AND semester_data.`semester_id` IN (:semesters) - "; - if ($this->additional_sql_conditions) { - $query .= ' AND ' . $this->additional_sql_conditions . ' '; - } - $query .= " GROUP BY s.Seminar_id "; + $query = "SELECT DISTINCT + s.`Seminar_id`, + CONCAT_WS(' ', s.`VeranstaltungsNummer`, s.`Name`, {$semester_text}) + FROM `seminare` s + LEFT JOIN semester_courses ON (s.Seminar_id = semester_courses.course_id) + LEFT JOIN `semester_data` ON (semester_data.semester_id = semester_courses.semester_id) + WHERE {$conditions} + GROUP BY s.Seminar_id "; if ($semnumber) { $query .= " ORDER BY MAX(semester_data.`beginn`) DESC, s.`VeranstaltungsNummer`, s.`Name`"; } else { - $query .= " ORDER BY MAX(semester_data.beginn) DESC, s.`VeranstaltungsNummer`, s.`Name`"; + $query .= " ORDER BY MAX(semester_data.beginn) DESC, s.`Name`"; } return $query; // Admins see everything at their assigned institutes. case 'admin': $sem_inst = Config::get()->ALLOW_ADMIN_RELATED_INST ? 'si' : 's'; - $query = "SELECT DISTINCT s.`Seminar_id`, CONCAT_WS(' ', s.`VeranstaltungsNummer`, s.`Name`, " . $semester_text . ") - FROM `seminare` s - JOIN `seminar_inst` si USING (Seminar_id) - LEFT JOIN semester_courses ON (s.Seminar_id = semester_courses.course_id) - LEFT JOIN `semester_data` ON (semester_data.semester_id = semester_courses.semester_id) - WHERE (s.`VeranstaltungsNummer` LIKE :input - OR s.`Name` LIKE :input) - AND s.`status` NOT IN (:semtypes) - AND $sem_inst.`institut_id` IN (:institutes) - AND s.`Seminar_id` NOT IN (:exclude) - AND semester_data.`semester_id` IN (:semesters)"; - if ($this->additional_sql_conditions) { - $query .= ' AND ' . $this->additional_sql_conditions . ' '; - } - $query .= " GROUP BY s.Seminar_id "; + $query = "SELECT DISTINCT + s.`Seminar_id`, + CONCAT_WS(' ', s.`VeranstaltungsNummer`, s.`Name`, {$semester_text}) + FROM `seminare` s + JOIN `seminar_inst` si USING (Seminar_id) + LEFT JOIN semester_courses ON (s.Seminar_id = semester_courses.course_id) + LEFT JOIN `semester_data` ON (semester_data.semester_id = semester_courses.semester_id) + WHERE {$conditions} + AND {$sem_inst}.`institut_id` IN (:institutes) + GROUP BY s.Seminar_id "; if ($semnumber) { $query .= " ORDER BY MAX(semester_data.`beginn`) DESC, s.`VeranstaltungsNummer`, s.`Name`"; } else { @@ -165,37 +138,38 @@ class MyCoursesSearch extends StandardSearch return $query; // non-admins search all their administrable courses. default: - $query = "SELECT DISTINCT s.`Seminar_id`, CONCAT_WS(' ', s.`VeranstaltungsNummer`, s.`Name`, " . $semester_text . "), - s.`VeranstaltungsNummer` AS num, s.`Name`, MAX(semester_data.beginn) as beginn - FROM `seminare` s - JOIN `seminar_user` su ON (s.`Seminar_id`=su.`Seminar_id`) - LEFT JOIN semester_courses ON (s.Seminar_id = semester_courses.course_id) - LEFT JOIN `semester_data` ON (semester_data.semester_id = semester_courses.semester_id) - WHERE (s.`VeranstaltungsNummer` LIKE :input - OR s.`Name` LIKE :input) - AND su.`user_id` = :userid - AND su.`status` IN ('dozent','tutor') - AND s.`status` NOT IN (:semtypes) - AND s.`Seminar_id` NOT IN (:exclude) - AND semester_data.`semester_id` IN (:semesters)"; + $query = "SELECT DISTINCT + s.`Seminar_id`, + CONCAT_WS(' ', s.`VeranstaltungsNummer`, s.`Name`, {$semester_text}), + s.`VeranstaltungsNummer` AS num, + s.`Name`, + MAX(semester_data.beginn) AS beginn + FROM `seminare` s + JOIN `seminar_user` su ON (s.`Seminar_id` = su.`Seminar_id`) + LEFT JOIN semester_courses ON (s.Seminar_id = semester_courses.course_id) + LEFT JOIN `semester_data` ON (semester_data.semester_id = semester_courses.semester_id) + WHERE {$conditions} + AND su.`user_id` = :userid + AND su.`status` IN ('dozent','tutor') + GROUP BY s.Seminar_id "; + if (Config::get()->DEPUTIES_ENABLE) { - $query .= " UNION - SELECT DISTINCT s.`Seminar_id`, CONCAT_WS(' ', s.`VeranstaltungsNummer`, ' ', s.`Name`, " . $semester_text . "), - s.`VeranstaltungsNummer` AS num, s.`Name`, MAX(semester_data.beginn) AS beginn - FROM `seminare` s - JOIN `deputies` d ON (s.`Seminar_id` = d.`range_id`) - LEFT JOIN semester_courses ON (s.Seminar_id = semester_courses.course_id) - LEFT JOIN `semester_data` ON (semester_data.semester_id = semester_courses.semester_id) - WHERE (s.`VeranstaltungsNummer` LIKE :input - OR s.`Name` LIKE :input) - AND d.`user_id` = :userid - AND s.`Seminar_id` NOT IN (:exclude) - AND semester_data.`semester_id` IN (:semesters)"; - } - if ($this->additional_sql_conditions) { - $query .= ' AND ' . $this->additional_sql_conditions . ' '; + $query .= " UNION "; + $query .= "SELECT DISTINCT + s.`Seminar_id`, + CONCAT_WS(' ', s.`VeranstaltungsNummer`, ' ', s.`Name`, {$semester_text}), + s.`VeranstaltungsNummer` AS num, + s.`Name`, + MAX(semester_data.beginn) AS beginn + FROM `seminare` s + JOIN `deputies` d ON (s.`Seminar_id` = d.`range_id`) + LEFT JOIN semester_courses ON (s.Seminar_id = semester_courses.course_id) + LEFT JOIN `semester_data` ON (semester_data.semester_id = semester_courses.semester_id) + WHERE {$conditions} + AND d.`user_id` = :userid + GROUP BY s.Seminar_id"; } - $query .= " GROUP BY s.Seminar_id"; + if ($semnumber) { $query .= " ORDER BY beginn DESC, num, `Name`"; } else { @@ -206,6 +180,27 @@ class MyCoursesSearch extends StandardSearch } } + /** + * Returns the default conditions use by all searches as a list. + * + * @return array + */ + private function getConditions(): array + { + $conditions = [ + '(s.`VeranstaltungsNummer` LIKE :input OR s.`Name` LIKE :input)', + 's.`status` NOT IN (:semtypes)', + 's.`Seminar_id` NOT IN (:exclude)', + 'semester_data.`semester_id` IN (:semesters)' + ]; + + if ($this->additional_sql_conditions) { + $conditions[] = $this->additional_sql_conditions; + } + + return $conditions; + } + /** * A very simple overwrite of the same method from SearchType class. * returns the absolute path to this class for autoincluding this class. -- GitLab