diff --git a/lib/dml/moodle_database.php b/lib/dml/moodle_database.php index 73653196e85..9818372eaf1 100644 --- a/lib/dml/moodle_database.php +++ b/lib/dml/moodle_database.php @@ -2962,6 +2962,8 @@ abstract class moodle_database { ): array { $fullcountsql = $this->generate_fullcount_sql($sql, $params, $fullcountcolumn); if ($sort) { + // Remove "ORDER BY" with any extra spaces from $sort. + $sort = preg_replace('/\s*ORDER\s+BY\s*/i', '', $sort); $fullcountsql .= " ORDER BY " . $sort; } return $this->get_records_sql($fullcountsql, $params, $limitfrom, $limitnum); @@ -2993,6 +2995,8 @@ abstract class moodle_database { ): moodle_recordset { $fullcountsql = $this->generate_fullcount_sql($sql, $params, $fullcountcolumn); if ($sort) { + // Remove "ORDER BY" with any extra spaces from $sort. + $sort = preg_replace('/\s*ORDER\s+BY\s*/i', '', $sort); $fullcountsql .= " ORDER BY " . $sort; } return $this->get_recordset_sql($fullcountsql, $params, $limitfrom, $limitnum); diff --git a/user/tests/table/participants_search_test.php b/user/tests/table/participants_search_test.php index 9b0ff9cd864..6750223bb4f 100644 --- a/user/tests/table/participants_search_test.php +++ b/user/tests/table/participants_search_test.php @@ -36,6 +36,8 @@ use stdClass; * @category test * @copyright 2020 Andrew Nicols * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * + * @covers \core_user\table\participants_search */ final class participants_search_test extends advanced_testcase { @@ -3508,4 +3510,44 @@ final class participants_search_test extends advanced_testcase { return $finaltests; } + + /** + * Tests sorting of participants in a course. + * + * This test runs a search for participants twice, first with an "ORDER BY" clause and second without. + * The test asserts the correct ordering of participants based on the sorting condition. + */ + public function test_sort_participants(): void { + $this->resetAfterTest(); + + $course = $this->getDataGenerator()->create_course(); + $coursecontext = context_course::instance($course->id); + + // Generate users with their role. + $this->getDataGenerator()->create_and_enrol($course, 'teacher'); + $this->getDataGenerator()->create_and_enrol($course, 'student'); + + // Create the basic filter. + $filterset = new participants_filterset(); + $filterset->add_filter(new integer_filter('courseid', null, [(int) $course->id])); + + // Run the search with using ORDER BY. + $search = new participants_search($course, $coursecontext, $filterset); + $rs = $search->get_participants( + sort: 'ORDER BY id', // Adding spaces between "ORDER" and "BY" is intentional. + ); + $records = $this->convert_recordset_to_array($rs); + $userids = array_keys($records); + $this->assertGreaterThan($userids[0], $userids[1]); + + // Run the search without using ORDER BY. + $rs = $search->get_participants( + sort: 'id DESC', + ); + $records = $this->convert_recordset_to_array($rs); + $userids = array_keys($records); + $this->assertGreaterThan($userids[1], $userids[0]); + + $rs->close(); + } }