From d3b698a46e8a64e7a536f33e67d57ec11caf268c Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Thu, 1 Mar 2012 09:38:28 +0700 Subject: [PATCH] MDL-26275 grade: added a safety check to avoid hitting PHP's max_input_var by reducing the number of students per page if necessary --- grade/report/grader/lib.php | 60 ++++++++++++++++++++++++++++++++++--- lang/en/grades.php | 1 + 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/grade/report/grader/lib.php b/grade/report/grader/lib.php index 4969c445c6a..80eff7ca2fa 100644 --- a/grade/report/grader/lib.php +++ b/grade/report/grader/lib.php @@ -137,8 +137,9 @@ class grade_report_grader extends grade_report { $this->baseurl = new moodle_url('index.php', array('id' => $this->courseid)); - if (!empty($this->page)) { - $this->baseurl->params(array('page' => $this->page)); + $studentsperpage = $this->get_students_per_page(); + if (!empty($this->page) && !empty($studentsperpage)) { + $this->baseurl->params(array('perpage' => $studentsperpage, 'page' => $this->page)); } $this->pbarurl = new moodle_url('/grade/report/grader/index.php', array('id' => $this->courseid)); @@ -390,7 +391,8 @@ class grade_report_grader extends grade_report { $this->groupwheresql ORDER BY $sort"; - $this->users = $DB->get_records_sql($sql, $params, $this->get_pref('studentsperpage') * $this->page, $this->get_pref('studentsperpage')); + $studentsperpage = $this->get_students_per_page(); + $this->users = $DB->get_records_sql($sql, $params, $studentsperpage * $this->page, $studentsperpage); if (empty($this->users)) { $this->userselect = ''; @@ -1036,7 +1038,7 @@ class grade_report_grader extends grade_report { } $jsarguments['cfg']['isediting'] = (bool)$USER->gradeediting[$this->courseid]; $jsarguments['cfg']['courseid'] = $this->courseid; - $jsarguments['cfg']['studentsperpage'] = $this->get_pref('studentsperpage'); + $jsarguments['cfg']['studentsperpage'] = $this->get_students_per_page(); $jsarguments['cfg']['showquickfeedback'] = (bool)$this->get_pref('showquickfeedback'); $module = array( @@ -1646,5 +1648,55 @@ class grade_report_grader extends grade_report { return $arrows; } + + /** + * Returns the number of students to be displayed on each page + * + * Takes into account the 'studentsperpage' user preference and the 'max_input_vars' + * PHP setting. Too many fields is only a problem when submitting grades but + * we respect 'max_input_vars' even when viewing grades to prevent students disappearing + * when toggling editing on and off. + * + * @return int The number of students to display per page + */ + private function get_students_per_page() { + global $USER; + static $studentsperpage = null; + + if ($studentsperpage === null) { + $studentsperpage = $this->get_pref('studentsperpage'); + + // Will this number of students result in more fields that we are allowed? + $maxinputvars = ini_get('max_input_vars'); + if ($maxinputvars !== false) { + $fieldspergradeitem = 0; // The number of fields output per grade item for each student + + if ($this->get_pref('quickgrading')) { + // One visible grade field and hidden "oldgrade" field + $fieldspergradeitem += 2; + } + if ($this->get_pref('showquickfeedback')) { + // One visible feedback field and hidden "oldfeedback" field + $fieldspergradeitem += 2; + } + + $fieldsperstudent = $fieldspergradeitem * count($this->gtree->get_items()); + $fieldsrequired = $studentsperpage * $fieldsperstudent; + + if ($fieldsrequired > $maxinputvars) { + $studentsperpage = floor($maxinputvars / $fieldsperstudent); + if ($studentsperpage<1) { + // Make sure students per page doesn't fall below 1 + // PHP max_input_vars could potentially be reached with 1 student + // if there are >250 grade items and quickgrading and showquickfeedback are on + $studentsperpage = 1; + } + debugging(get_string('studentsperpagereduced', 'grades')); + } + } + } + + return $studentsperpage; + } } diff --git a/lang/en/grades.php b/lang/en/grades.php index 8d3ae77d278..4743474066f 100644 --- a/lang/en/grades.php +++ b/lang/en/grades.php @@ -603,6 +603,7 @@ $string['statslink'] = 'Stats'; $string['student'] = 'Student'; $string['studentsperpage'] = 'Students per page'; $string['studentsperpage_help'] = 'This setting determines the number of students displayed per page in the grader report.'; +$string['studentsperpagereduced'] = 'Students per page has been reduced to prevent possible data loss when bulk updating grades'; $string['subcategory'] = 'Normal category'; $string['submissions'] = 'Submissions'; $string['submittedon'] = 'Submitted: {$a}';