From cd43a7f29e2170a7eaecfb78173e98934547b267 Mon Sep 17 00:00:00 2001
From: Matt Clarkson <mattc@catalyst.net.nz>
Date: Wed, 8 Aug 2012 16:42:29 +1200
Subject: [PATCH] mod/quiz/report: replace get_users_by_capability

---
 mod/quiz/report/attemptsreport.php          | 30 ++++---------
 mod/quiz/report/attemptsreport_table.php    | 37 ++++++++--------
 mod/quiz/report/grading/report.php          | 23 +++++-----
 mod/quiz/report/overview/overview_table.php | 12 +++---
 mod/quiz/report/overview/overviewgraph.php  | 12 ++----
 mod/quiz/report/overview/report.php         | 32 ++++++++------
 mod/quiz/report/reportlib.php               | 15 +++----
 mod/quiz/report/statistics/qstats.php       |  4 +-
 mod/quiz/report/statistics/report.php       | 65 ++++++++++++++---------------
 9 files changed, 103 insertions(+), 127 deletions(-)

diff --git a/mod/quiz/report/attemptsreport.php b/mod/quiz/report/attemptsreport.php
index fe223b7..67a65e5 100644
--- a/mod/quiz/report/attemptsreport.php
+++ b/mod/quiz/report/attemptsreport.php
@@ -78,7 +78,7 @@ abstract class quiz_attempts_report extends quiz_default_report {
 
         $this->context = context_module::instance($cm->id);
 
-        list($currentgroup, $students, $groupstudents, $allowed) =
+        list($currentgroup, $studentssql, $groupstudentssql, $allowedsql) =
                 $this->load_relevant_students($cm, $course);
 
         $this->qmsubselect = quiz_report_qm_filter_select($quiz);
@@ -87,7 +87,7 @@ abstract class quiz_attempts_report extends quiz_default_report {
                 array('qmsubselect' => $this->qmsubselect, 'quiz' => $quiz,
                 'currentgroup' => $currentgroup, 'context' => $this->context));
 
-        return array($currentgroup, $students, $groupstudents, $allowed);
+        return array($currentgroup, $studentssql, $groupstudentssql, $allowedsql);
     }
 
     /**
@@ -117,28 +117,16 @@ abstract class quiz_attempts_report extends quiz_default_report {
             return array($currentgroup, array(), array(), array());
         }
 
-        if (!$students = get_users_by_capability($this->context,
-                array('mod/quiz:reviewmyattempts', 'mod/quiz:attempt'),
-                'u.id, 1', '', '', '', '', '', false)) {
-            $students = array();
-        } else {
-            $students = array_keys($students);
-        }
+        $studentssql = get_enrolled_sql($this->context, array('mod/quiz:attempt', 'mod/quiz:reviewmyattempts'));
 
         if (empty($currentgroup)) {
-            return array($currentgroup, $students, array(), $students);
+            return array($currentgroup, $studentssql, array(), $studentssql);
         }
 
         // We have a currently selected group.
-        if (!$groupstudents = get_users_by_capability($this->context,
-                array('mod/quiz:reviewmyattempts', 'mod/quiz:attempt'),
-                'u.id, 1', '', '', '', $currentgroup, '', false)) {
-            $groupstudents = array();
-        } else {
-            $groupstudents = array_keys($groupstudents);
-        }
+        $groupstudentssl = get_enrolled_sql($this->context, array('mod/quiz:attempt', 'mod/quiz:reviewmyattempts'), $currentgroup);
 
-        return array($currentgroup, $students, $groupstudents, $groupstudents);
+        return array($currentgroup, $studentssql, $groupstudentssql, $groupstudentssql);
     }
 
     /**
@@ -307,17 +295,13 @@ abstract class quiz_attempts_report extends quiz_default_report {
      */
     protected function delete_selected_attempts($quiz, $cm, $attemptids, $allowed) {
         global $DB;
-
+echo 'here'; exit;
         foreach ($attemptids as $attemptid) {
             $attempt = $DB->get_record('quiz_attempts', array('id' => $attemptid));
             if (!$attempt || $attempt->quiz != $quiz->id || $attempt->preview != 0) {
                 // Ensure the attempt exists, and belongs to this quiz. If not skip.
                 continue;
             }
-            if ($allowed && !in_array($attempt->userid, $allowed)) {
-                // Ensure the attempt belongs to a student included in the report. If not skip.
-                continue;
-            }
             add_to_log($quiz->course, 'quiz', 'delete attempt', 'report.php?id=' . $cm->id,
                     $attemptid, $cm->id);
             quiz_delete_attempt($attempt, $quiz);
diff --git a/mod/quiz/report/attemptsreport_table.php b/mod/quiz/report/attemptsreport_table.php
index f119da0..022561b 100644
--- a/mod/quiz/report/attemptsreport_table.php
+++ b/mod/quiz/report/attemptsreport_table.php
@@ -61,11 +61,11 @@ abstract class quiz_attempts_report_table extends table_sql {
     /** @var object mod_quiz_attempts_report_options the options affecting this report. */
     protected $options;
 
-    /** @var object the ids of the students in the currently selected group, if applicable. */
-    protected $groupstudents;
+    /** @var array of sql + parameters to find students in the currently selected group, if applicable. */
+    protected $groupstudentssql;
 
-    /** @var object the ids of the students in the course. */
-    protected $students;
+    /** @var array of sql + parameters to find the students in the course. */
+    protected $studentssql;
 
     /** @var object the questions that comprise this quiz.. */
     protected $questions;
@@ -86,14 +86,14 @@ abstract class quiz_attempts_report_table extends table_sql {
      * @param moodle_url $reporturl
      */
     public function __construct($uniqueid, $quiz, $context, $qmsubselect,
-            mod_quiz_attempts_report_options $options, $groupstudents, $students,
+            mod_quiz_attempts_report_options $options, $groupstudentssql, $studentssql,
             $questions, $reporturl) {
         parent::__construct($uniqueid);
         $this->quiz = $quiz;
         $this->context = $context;
         $this->qmsubselect = $qmsubselect;
-        $this->groupstudents = $groupstudents;
-        $this->students = $students;
+        $this->groupstudentssql = $groupstudentssql;
+        $this->studentssql = $studentssql;
         $this->questions = $questions;
         $this->includecheckboxes = $options->checkboxcolumn;
         $this->reporturl = $reporturl;
@@ -342,7 +342,7 @@ abstract class quiz_attempts_report_table extends table_sql {
      * @return array with 4 elements ($fields, $from, $where, $params) that can be used to
      *      build the actual database query.
      */
-    public function base_sql($reportstudents) {
+    public function base_sql($reportstudentssql) {
         global $DB;
 
         $fields = $DB->sql_concat('u.id', "'#'", 'COALESCE(quiza.attempt, 0)') . ' AS uniqueid,';
@@ -394,24 +394,21 @@ abstract class quiz_attempts_report_table extends table_sql {
                 break;
             case quiz_attempts_report::ENROLLED_WITH:
                 // Show only students with attempts.
-                list($usql, $uparams) = $DB->get_in_or_equal(
-                        $reportstudents, SQL_PARAMS_NAMED, 'u');
-                $params += $uparams;
-                $where = "u.id $usql AND quiza.preview = 0 AND quiza.id IS NOT NULL";
+                $params += $reportstudentssql[1];
+                $from .= "\nINNER JOIN ({$reportstudentssql[0]}) as enr ON enr.id = u.id";
+                $where = "quiza.preview = 0 AND quiza.id IS NOT NULL";
                 break;
             case quiz_attempts_report::ENROLLED_WITHOUT:
                 // Show only students without attempts.
-                list($usql, $uparams) = $DB->get_in_or_equal(
-                        $reportstudents, SQL_PARAMS_NAMED, 'u');
-                $params += $uparams;
-                $where = "u.id $usql AND quiza.id IS NULL";
+                $params += $reportstudentssql[1];
+                $from .= "\nINNER JOIN ({$reportstudentssql[0]}) as enr ON enr.id = u.id";
+                $where = "quiza.id IS NULL";
                 break;
             case quiz_attempts_report::ENROLLED_ALL:
                 // Show all students with or without attempts.
-                list($usql, $uparams) = $DB->get_in_or_equal(
-                        $reportstudents, SQL_PARAMS_NAMED, 'u');
-                $params += $uparams;
-                $where = "u.id $usql AND (quiza.preview = 0 OR quiza.preview IS NULL)";
+                $params += $reportstudentssql[1];
+                $from .= "\nINNER JOIN ({$reportstudentssql[0]}) as enr ON enr.id = u.id";
+                $where = "(quiza.preview = 0 OR quiza.preview IS NULL)";
                 break;
         }
 
diff --git a/mod/quiz/report/grading/report.php b/mod/quiz/report/grading/report.php
index 6d20d2a..954ab40 100644
--- a/mod/quiz/report/grading/report.php
+++ b/mod/quiz/report/grading/report.php
@@ -116,11 +116,10 @@ class quiz_grading_report extends quiz_default_report {
         // Get the group, and the list of significant users.
         $this->currentgroup = $this->get_current_group($cm, $course, $this->context);
         if ($this->currentgroup == self::NO_GROUPS_ALLOWED) {
-            $this->users = array();
+            $this->userssql = array();
         } else {
-            $this->users = get_users_by_capability($this->context,
-                    array('mod/quiz:reviewmyattempts', 'mod/quiz:attempt'), '', '', '', '',
-                    $this->currentgroup, '', false);
+            $this->userssql = get_enrolled_sql($this->context,
+                    array('mod/quiz:reviewmyattempts', 'mod/quiz:attempt'), $this->currentgroup);
         }
 
         $questionsinquiz = quiz_questions_in_quiz($quiz->questions);
@@ -165,22 +164,20 @@ class quiz_grading_report extends quiz_default_report {
                 quiza.state = :statefinished";
         $params = array('mangrquizid' => $this->cm->instance, 'statefinished' => quiz_attempt::FINISHED);
 
+        $usersjoin = '';
         $currentgroup = groups_get_activity_group($this->cm, true);
         if ($currentgroup) {
-            $users = get_users_by_capability($this->context,
-                    array('mod/quiz:reviewmyattempts', 'mod/quiz:attempt'), 'u.id, u.id', '', '', '',
-                    $currentgroup, '', false);
-            if (empty($users)) {
+            $userssql = get_enrolled_sql($this->context,
+                    array('mod/quiz:reviewmyattempts', 'mod/quiz:attempt'), $currentgroup);
+            if (empty($userssql)) {
                 $where .= ' AND quiza.userid = 0';
             } else {
-                list($usql, $uparam) = $DB->get_in_or_equal(array_keys($users),
-                        SQL_PARAMS_NAMED, 'mangru');
-                $where .= ' AND quiza.userid ' . $usql;
-                $params += $uparam;
+                $usersjoin = "JOIN ({$userssql[0]}) AS enr ON quiza.userid = enr.id";
+                $params += $userssql[1];
             }
         }
 
-        return new qubaid_join('{quiz_attempts} quiza', 'quiza.uniqueid', $where, $params);
+        return new qubaid_join("{quiz_attempts} quiza $usersjoin ", 'quiza.uniqueid', $where, $params);
     }
 
     protected function load_attempts_by_usage_ids($qubaids) {
diff --git a/mod/quiz/report/overview/overview_table.php b/mod/quiz/report/overview/overview_table.php
index 5f8f0e3..735ac72 100644
--- a/mod/quiz/report/overview/overview_table.php
+++ b/mod/quiz/report/overview/overview_table.php
@@ -68,12 +68,12 @@ class quiz_overview_table extends quiz_attempts_report_table {
         // End of adding the data from attempts. Now add averages at bottom.
         $this->add_separator();
 
-        if ($this->groupstudents) {
-            $this->add_average_row(get_string('groupavg', 'grades'), $this->groupstudents);
+        if ($this->groupstudentssql) {
+            $this->add_average_row(get_string('groupavg', 'grades'), $this->groupstudentssql);
         }
 
-        if ($this->students) {
-            $this->add_average_row(get_string('overallaverage', 'grades'), $this->students);
+        if ($this->studentssql) {
+            $this->add_average_row(get_string('overallaverage', 'grades'), $this->studentssql);
         }
     }
 
@@ -82,10 +82,10 @@ class quiz_overview_table extends quiz_attempts_report_table {
      * @param string $label the title ot use for this row.
      * @param array $users the users to average over.
      */
-    protected function add_average_row($label, $users) {
+    protected function add_average_row($label, $userssql) {
         global $DB;
 
-        list($fields, $from, $where, $params) = $this->base_sql($users);
+        list($fields, $from, $where, $params) = $this->base_sql($userssql);
         $record = $DB->get_record_sql("
                 SELECT AVG(quiza.sumgrades) AS grade, COUNT(quiza.sumgrades) AS numaveraged
                   FROM $from
diff --git a/mod/quiz/report/overview/overviewgraph.php b/mod/quiz/report/overview/overviewgraph.php
index 6583ef9..b99b94a 100644
--- a/mod/quiz/report/overview/overviewgraph.php
+++ b/mod/quiz/report/overview/overviewgraph.php
@@ -46,15 +46,9 @@ if ($groupid && $groupmode = groups_get_activity_groupmode($cm)) {
         print_error('errorinvalidgroup', 'group', null, $groupid);
     }
     $group = $groups[$groupid];
-    $groupusers = get_users_by_capability($modcontext,
-            array('mod/quiz:reviewmyattempts', 'mod/quiz:attempt'),
-            '', '', '', '', $group->id, '', false);
-    if (!$groupusers) {
-        print_error('nostudentsingroup');
-    }
-    $groupusers = array_keys($groupusers);
+    $groupuserssql = get_enrolled_sql($modcontext, array('mod/quiz:attempt', 'mod/quiz:reviewmyattempts'), $group->id);
 } else {
-    $groupusers = array();
+    $groupuserssql = array();
 }
 
 $line = new graph(800, 600);
@@ -106,7 +100,7 @@ $line->y_format['allusers'] = array(
     'shadow_offset' => 1,
     'legend' => get_string('allparticipants')
 );
-$line->y_data['allusers'] = quiz_report_grade_bands($bandwidth, $bands, $quizid, $groupusers);
+$line->y_data['allusers'] = quiz_report_grade_bands($bandwidth, $bands, $quizid, $groupuserssql);
 
 $line->y_order = array('allusers');
 
diff --git a/mod/quiz/report/overview/report.php b/mod/quiz/report/overview/report.php
index 27b4df5..9fbe4b9 100644
--- a/mod/quiz/report/overview/report.php
+++ b/mod/quiz/report/overview/report.php
@@ -42,7 +42,7 @@ class quiz_overview_report extends quiz_attempts_report {
     public function display($quiz, $cm, $course) {
         global $CFG, $DB, $OUTPUT, $PAGE;
 
-        list($currentgroup, $students, $groupstudents, $allowed) =
+        list($currentgroup, $studentssql, $groupstudentssql, $allowedsql) =
                 $this->init('overview', 'quiz_overview_settings_form', $quiz, $cm, $course);
         $options = new quiz_overview_options('overview', $quiz, $cm, $course);
 
@@ -69,7 +69,7 @@ class quiz_overview_report extends quiz_attempts_report {
         $courseshortname = format_string($course->shortname, true,
                 array('context' => context_course::instance($course->id)));
         $table = new quiz_overview_table($quiz, $this->context, $this->qmsubselect,
-                $options, $groupstudents, $students, $questions, $this->get_base_url());
+                $options, $groupstudentssql, $studentssql, $questions, $this->get_base_url());
         $filename = quiz_report_download_filename(get_string('overviewfilename', 'quiz_overview'),
                 $courseshortname, $quiz->name);
         $table->is_downloading($options->download, $filename,
@@ -78,7 +78,7 @@ class quiz_overview_report extends quiz_attempts_report {
             raise_memory_limit(MEMORY_EXTRA);
         }
 
-        $this->process_actions($quiz, $cm, $currentgroup, $groupstudents, $allowed, $options->get_url());
+        $this->process_actions($quiz, $cm, $currentgroup, $groupstudentssql, $allowedsql, $options->get_url());
 
         // Start output.
         if (!$table->is_downloading()) {
@@ -101,11 +101,16 @@ class quiz_overview_report extends quiz_attempts_report {
             }
         }
 
+        $hasstudents = $DB->record_exists_sql($studentssql[0], $studentssql[1]);
+        if (!empty($groupstudentssql)) {
+            $hasgroupstudents = $DB->record_exists_sql($groupstudentssql[0], $groupstudentssql[1]);
+        }
+
         $hasquestions = quiz_questions_in_quiz($quiz->questions);
         if (!$table->is_downloading()) {
             if (!$hasquestions) {
                 echo quiz_no_questions_message($quiz, $cm, $this->context);
-            } else if (!$students) {
+            } else if (!$hasstudents) {
                 echo $OUTPUT->notification(get_string('nostudentsyet'));
             } else if ($currentgroup && !$groupstudents) {
                 echo $OUTPUT->notification(get_string('nostudentsingroup'));
@@ -115,7 +120,7 @@ class quiz_overview_report extends quiz_attempts_report {
             $this->form->display();
         }
 
-        $hasstudents = $students && (!$currentgroup || $groupstudents);
+        $hasstudents = $hasstudents && (!$currentgroup || $hasgroupstudents);
         if ($hasquestions && ($hasstudents || $options->attempts == self::ALL_WITH)) {
             // Construct the SQL.
             $fields = $DB->sql_concat('u.id', "'#'", 'COALESCE(quiza.attempt, 0)') .
@@ -128,7 +133,7 @@ class quiz_overview_report extends quiz_attempts_report {
                     "END) AS gradedattempt, ";
             }
 
-            list($fields, $from, $where, $params) = $table->base_sql($allowed);
+            list($fields, $from, $where, $params) = $table->base_sql($allowedsql);
 
             $table->set_count_sql("SELECT COUNT(1) FROM $from WHERE $where", $params);
 
@@ -151,7 +156,7 @@ class quiz_overview_report extends quiz_attempts_report {
                 // Output the regrade buttons.
                 if (has_capability('mod/quiz:regrade', $this->context)) {
                     $regradesneeded = $this->count_question_attempts_needing_regrade(
-                            $quiz, $groupstudents);
+                            $quiz, $groupstudentssql);
                     if ($currentgroup) {
                         $a= new stdClass();
                         $a->groupname = groups_get_group_name($currentgroup);
@@ -443,22 +448,23 @@ class quiz_overview_report extends quiz_attempts_report {
      * @param array $groupstudents user ids. If this is given, only data relating
      * to these users is cleared.
      */
-    protected function count_question_attempts_needing_regrade($quiz, $groupstudents) {
+    protected function count_question_attempts_needing_regrade($quiz, $groupstudentssql) {
         global $DB;
 
-        $usertest = '';
+        $userjoin = '';
+
         $params = array();
-        if ($groupstudents) {
-            list($usql, $params) = $DB->get_in_or_equal($groupstudents);
-            $usertest = "quiza.userid $usql AND ";
+        if ($groupstudentssql) {
+            $userjoin = "JOIN ({$groupstudentssql[0]}) AS enr ON enr.id = quiza.userid";
+            $params = $groupstudentssql[1];
         }
 
         $params[] = $quiz->id;
         $sql = "SELECT COUNT(DISTINCT quiza.id)
                 FROM {quiz_attempts} quiza
                 JOIN {quiz_overview_regrades} qqr ON quiza.uniqueid = qqr.questionusageid
+                $userjoin
                 WHERE
-                    $usertest
                     quiza.quiz = ? AND
                     quiza.preview = 0 AND
                     qqr.regraded = 0";
diff --git a/mod/quiz/report/reportlib.php b/mod/quiz/report/reportlib.php
index 344513e..2248ad8 100644
--- a/mod/quiz/report/reportlib.php
+++ b/mod/quiz/report/reportlib.php
@@ -186,10 +186,10 @@ function quiz_report_qm_filter_select($quiz, $quizattemptsalias = 'quiza') {
  * @param number $bandwidth the width of each band.
  * @param int $bands the number of bands
  * @param int $quizid the quiz id.
- * @param array $userids list of user ids.
+ * @param array $userssql sql + parameters to get enrolled users
  * @return array band number => number of users with scores in that band.
  */
-function quiz_report_grade_bands($bandwidth, $bands, $quizid, $userids = array()) {
+function quiz_report_grade_bands($bandwidth, $bands, $quizid, $userssql = array()) {
     global $DB;
     if (!is_int($bands)) {
         debugging('$bands passed to quiz_report_grade_bands must be an integer. (' .
@@ -197,11 +197,11 @@ function quiz_report_grade_bands($bandwidth, $bands, $quizid, $userids = array()
         $bands = (int) $bands;
     }
 
-    if ($userids) {
-        list($usql, $params) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED, 'u');
-        $usql = "qg.userid $usql AND";
+    if ($userssql) {
+        $userjoin = "JOIN ({$userssql[0]}) AS enr ON enr.id = qg.userid";
+        $params = $userssql[1];
     } else {
-        $usql = '';
+        $userjoin = '';
         $params = array();
     }
     $sql = "
@@ -210,7 +210,8 @@ SELECT band, COUNT(1)
 FROM (
     SELECT FLOOR(qg.grade / :bandwidth) AS band
       FROM {quiz_grades} qg
-     WHERE $usql qg.quiz = :quizid
+      $userjoin
+     WHERE qg.quiz = :quizid
 ) subquery
 
 GROUP BY
diff --git a/mod/quiz/report/statistics/qstats.php b/mod/quiz/report/statistics/qstats.php
index 75001bf..1aa754d 100644
--- a/mod/quiz/report/statistics/qstats.php
+++ b/mod/quiz/report/statistics/qstats.php
@@ -95,7 +95,7 @@ class quiz_statistics_question_stats {
      * @param array $groupstudents students in this group.
      * @param bool $allattempts use all attempts, or just first attempts.
      */
-    public function load_step_data($quizid, $currentgroup, $groupstudents, $allattempts) {
+    public function load_step_data($quizid, $currentgroup, $groupstudentssql, $allattempts) {
         global $DB;
 
         $this->allattempts = $allattempts;
@@ -103,7 +103,7 @@ class quiz_statistics_question_stats {
         list($qsql, $qparams) = $DB->get_in_or_equal(array_keys($this->questions),
                 SQL_PARAMS_NAMED, 'q');
         list($fromqa, $whereqa, $qaparams) = quiz_statistics_attempts_sql(
-                $quizid, $currentgroup, $groupstudents, $allattempts, false);
+                $quizid, $currentgroup, $groupstudentssql, $allattempts, false);
 
         $this->lateststeps = $DB->get_records_sql("
                 SELECT
diff --git a/mod/quiz/report/statistics/report.php b/mod/quiz/report/statistics/report.php
index 48c91ee..666df32 100644
--- a/mod/quiz/report/statistics/report.php
+++ b/mod/quiz/report/statistics/report.php
@@ -88,18 +88,17 @@ class quiz_statistics_report extends quiz_default_report {
         $nostudentsingroup = false; // True if a group is selected and there is no one in it.
         if (empty($currentgroup)) {
             $currentgroup = 0;
-            $groupstudents = array();
+            $groupstudentssql = array();
 
         } else if ($currentgroup == self::NO_GROUPS_ALLOWED) {
-            $groupstudents = array();
+            $groupstudentssql = array();
             $nostudentsingroup = true;
 
         } else {
             // All users who can attempt quizzes and who are in the currently selected group.
-            $groupstudents = get_users_by_capability($this->context,
-                    array('mod/quiz:reviewmyattempts', 'mod/quiz:attempt'),
-                    '', '', '', '', $currentgroup, '', false);
-            if (!$groupstudents) {
+            $groupstudentssql = get_enrolled_sql($this->context,
+                    array('mod/quiz:reviewmyattempts', 'mod/quiz:attempt'), $currentgroup);
+            if (!$DB->record_exists_sql($groupstudentssql[0], $groupstudentssql[1])) {
                 $nostudentsingroup = true;
             }
         }
@@ -141,7 +140,7 @@ class quiz_statistics_report extends quiz_default_report {
         // Get the data to be displayed.
         list($quizstats, $questions, $subquestions, $s) =
                 $this->get_quiz_and_questions_stats($quiz, $currentgroup,
-                        $nostudentsingroup, $useallattempts, $groupstudents, $questions);
+                        $nostudentsingroup, $useallattempts, $groupstudentssql, $questions);
         $quizinfo = $this->get_formatted_quiz_info_data($course, $cm, $quiz, $quizstats);
 
         // Set up the table, if there is data.
@@ -155,7 +154,7 @@ class quiz_statistics_report extends quiz_default_report {
 
             if (groups_get_activity_groupmode($cm)) {
                 groups_print_activity_menu($cm, $reporturl->out());
-                if ($currentgroup && !$groupstudents) {
+                if ($currentgroup && !$DB->record_exists_sql($groupstudentssql[0], $groupstudentssql[1])) {
                     $OUTPUT->notification(get_string('nostudentsingroup', 'quiz_statistics'));
                 }
             }
@@ -240,7 +239,7 @@ class quiz_statistics_report extends quiz_default_report {
             // On-screen display of overview report.
             echo $OUTPUT->heading(get_string('quizinformation', 'quiz_statistics'));
             echo $this->output_caching_info($quizstats, $quiz->id, $currentgroup,
-                    $groupstudents, $useallattempts, $reporturl);
+                    $groupstudentssql, $useallattempts, $reporturl);
             echo $this->everything_download_options();
             echo $this->output_quiz_info_table($quizinfo);
             if ($s) {
@@ -624,7 +623,7 @@ class quiz_statistics_report extends quiz_default_report {
      * @param int $currentgroup the current group. 0 for none.
      * @param bool $nostudentsingroup true if there a no students.
      * @param bool $useallattempts use all attempts, or just first attempts.
-     * @param array $groupstudents students in this group.
+     * @param array $groupstudentssql students in this group.
      * @param array $questions question definitions.
      * @return array with three elements:
      *      - integer $s Number of attempts included in the stats.
@@ -632,7 +631,7 @@ class quiz_statistics_report extends quiz_default_report {
      *      - array $qstats The statistics for each question.
      */
     protected function compute_stats($quizid, $currentgroup, $nostudentsingroup,
-            $useallattempts, $groupstudents, $questions) {
+            $useallattempts, $groupstudentssql, $questions) {
         global $DB;
 
         // Calculating MEAN of marks for all attempts by students
@@ -643,7 +642,7 @@ class quiz_statistics_report extends quiz_default_report {
         }
 
         list($fromqa, $whereqa, $qaparams) = quiz_statistics_attempts_sql(
-                $quizid, $currentgroup, $groupstudents, true);
+                $quizid, $currentgroup, $groupstudentssql, true);
 
         $attempttotals = $DB->get_records_sql("
                 SELECT
@@ -701,7 +700,7 @@ class quiz_statistics_report extends quiz_default_report {
 
         // Recalculate sql again this time possibly including test for first attempt.
         list($fromqa, $whereqa, $qaparams) = quiz_statistics_attempts_sql(
-                $quizid, $currentgroup, $groupstudents, $useallattempts);
+                $quizid, $currentgroup, $groupstudentssql, $useallattempts);
 
         // Median ...
         if ($s % 2 == 0) {
@@ -765,7 +764,7 @@ class quiz_statistics_report extends quiz_default_report {
         }
 
         $qstats = new quiz_statistics_question_stats($questions, $s, $summarksavg);
-        $qstats->load_step_data($quizid, $currentgroup, $groupstudents, $useallattempts);
+        $qstats->load_step_data($quizid, $currentgroup, $groupstudentssql, $useallattempts);
         $qstats->compute_statistics();
 
         if ($s > 1) {
@@ -789,7 +788,7 @@ class quiz_statistics_report extends quiz_default_report {
      * @param int $currentgroup the current group. 0 for none.
      * @param bool $nostudentsingroup true if there a no students.
      * @param bool $useallattempts use all attempts, or just first attempts.
-     * @param array $groupstudents students in this group.
+     * @param array $groupstudentssql students in this group.
      * @param array $questions question definitions.
      * @return array with 4 elements:
      *     - $quizstats The statistics for overall attempt scores.
@@ -799,7 +798,7 @@ class quiz_statistics_report extends quiz_default_report {
      * If there is no cached data in the database, returns an array of four nulls.
      */
     protected function try_loading_cached_stats($quiz, $currentgroup,
-            $nostudentsingroup, $useallattempts, $groupstudents, $questions) {
+            $nostudentsingroup, $useallattempts, $groupstudentssql, $questions) {
         global $DB;
 
         $timemodified = time() - self::TIME_TO_CACHE_STATS;
@@ -894,7 +893,7 @@ class quiz_statistics_report extends quiz_default_report {
      * @param int $currentgroup the current group. 0 for none.
      * @param bool $nostudentsingroup true if there a no students.
      * @param bool $useallattempts use all attempts, or just first attempts.
-     * @param array $groupstudents students in this group.
+     * @param array $groupstudentssql students in this group.
      * @param array $questions question definitions.
      * @return array with 4 elements:
      *     - $quizstats The statistics for overall attempt scores.
@@ -903,15 +902,15 @@ class quiz_statistics_report extends quiz_default_report {
      *     - $s Number of attempts included in the stats.
      */
     protected function get_quiz_and_questions_stats($quiz, $currentgroup,
-            $nostudentsingroup, $useallattempts, $groupstudents, $questions) {
+            $nostudentsingroup, $useallattempts, $groupstudentssql, $questions) {
 
         list($quizstats, $questions, $subquestions, $s) =
                 $this->try_loading_cached_stats($quiz, $currentgroup, $nostudentsingroup,
-                        $useallattempts, $groupstudents, $questions);
+                        $useallattempts, $groupstudentssql, $questions);
 
         if (is_null($quizstats)) {
             list($s, $quizstats, $qstats) = $this->compute_stats($quiz->id,
-                    $currentgroup, $nostudentsingroup, $useallattempts, $groupstudents, $questions);
+                    $currentgroup, $nostudentsingroup, $useallattempts, $groupstudentssql, $questions);
 
             if ($s) {
                 $questions = $qstats->questions;
@@ -921,7 +920,7 @@ class quiz_statistics_report extends quiz_default_report {
                         $quizstats, $questions, $subquestions);
 
                 $this->analyse_responses($quizstatisticsid, $quiz->id, $currentgroup,
-                        $nostudentsingroup, $useallattempts, $groupstudents,
+                        $nostudentsingroup, $useallattempts, $groupstudentssql,
                         $questions, $subquestions);
             }
         }
@@ -930,10 +929,10 @@ class quiz_statistics_report extends quiz_default_report {
     }
 
     protected function analyse_responses($quizstatisticsid, $quizid, $currentgroup,
-            $nostudentsingroup, $useallattempts, $groupstudents, $questions, $subquestions) {
+            $nostudentsingroup, $useallattempts, $groupstudentssql, $questions, $subquestions) {
 
         $qubaids = quiz_statistics_qubaids_condition(
-                $quizid, $currentgroup, $groupstudents, $useallattempts);
+                $quizid, $currentgroup, $groupstudentssql, $useallattempts);
 
         $done = array();
         foreach ($questions as $question) {
@@ -984,14 +983,14 @@ class quiz_statistics_report extends quiz_default_report {
      * @param object $quizstats the overall quiz statistics.
      * @param int $quizid the quiz id.
      * @param int $currentgroup the id of the currently selected group, or 0.
-     * @param array $groupstudents ids of students in the group.
+     * @param array $groupstudentssql sql + params for students in group
      * @param bool $useallattempts whether to use all attempts, instead of just
      *      first attempts.
      * @return string a HTML snipped saying when the stats were last computed,
      *      or blank if that is not appropriate.
      */
     protected function output_caching_info($quizstats, $quizid, $currentgroup,
-            $groupstudents, $useallattempts, $reporturl) {
+            $groupstudentssql, $useallattempts, $reporturl) {
         global $DB, $OUTPUT;
 
         if (empty($quizstats->timemodified)) {
@@ -1000,7 +999,7 @@ class quiz_statistics_report extends quiz_default_report {
 
         // Find the number of attempts since the cached statistics were computed.
         list($fromqa, $whereqa, $qaparams) = quiz_statistics_attempts_sql(
-                $quizid, $currentgroup, $groupstudents, $useallattempts, true);
+                $quizid, $currentgroup, $groupstudentssql, $useallattempts, true);
         $count = $DB->count_records_sql("
                 SELECT COUNT(1)
                 FROM $fromqa
@@ -1069,7 +1068,7 @@ class quiz_statistics_report extends quiz_default_report {
     }
 }
 
-function quiz_statistics_attempts_sql($quizid, $currentgroup, $groupstudents,
+function quiz_statistics_attempts_sql($quizid, $currentgroup, $groupstudentssql,
         $allattempts = true, $includeungraded = false) {
     global $DB;
 
@@ -1078,11 +1077,9 @@ function quiz_statistics_attempts_sql($quizid, $currentgroup, $groupstudents,
     $whereqa = 'quiza.quiz = :quizid AND quiza.preview = 0 AND quiza.state = :quizstatefinished';
     $qaparams = array('quizid' => $quizid, 'quizstatefinished' => quiz_attempt::FINISHED);
 
-    if (!empty($currentgroup) && $groupstudents) {
-        list($grpsql, $grpparams) = $DB->get_in_or_equal(array_keys($groupstudents),
-                SQL_PARAMS_NAMED, 'u');
-        $whereqa .= " AND quiza.userid $grpsql";
-        $qaparams += $grpparams;
+    if (!empty($currentgroup) && $groupstudentssql) {
+        $usersjoin = "JOIN ({$groupstudentssql[0]}) AS enr ON quiza.userid = enr.id";
+        $qaparams += $groupstudentssql[1];
     }
 
     if (!$allattempts) {
@@ -1102,9 +1099,9 @@ function quiz_statistics_attempts_sql($quizid, $currentgroup, $groupstudents,
  * @param string $fromqa from quiz_statistics_attempts_sql.
  * @param string $whereqa from quiz_statistics_attempts_sql.
  */
-function quiz_statistics_qubaids_condition($quizid, $currentgroup, $groupstudents,
+function quiz_statistics_qubaids_condition($quizid, $currentgroup, $groupstudentssql,
         $allattempts = true, $includeungraded = false) {
     list($fromqa, $whereqa, $qaparams) = quiz_statistics_attempts_sql($quizid, $currentgroup,
-            $groupstudents, $allattempts, $includeungraded);
+            $groupstudentssql, $allattempts, $includeungraded);
     return new qubaid_join($fromqa, 'quiza.uniqueid', $whereqa, $qaparams);
 }
-- 
1.7.11.3

