diff --git a/lib/db/services.php b/lib/db/services.php index a7de93cc746..0abb0f516c8 100644 --- a/lib/db/services.php +++ b/lib/db/services.php @@ -1313,6 +1313,7 @@ $services = array( 'mod_quiz_get_quizzes_by_courses', 'mod_quiz_get_user_attempts', 'mod_quiz_view_quiz', + 'mod_quiz_get_user_best_grade', 'mod_glossary_get_glossaries_by_courses', 'mod_wiki_get_wikis_by_courses', 'mod_wiki_view_wiki', diff --git a/mod/quiz/classes/external.php b/mod/quiz/classes/external.php index 785621946cc..6b24d796606 100644 --- a/mod/quiz/classes/external.php +++ b/mod/quiz/classes/external.php @@ -447,4 +447,87 @@ class mod_quiz_external extends external_api { ); } + /** + * Describes the parameters for get_user_best_grade. + * + * @return external_external_function_parameters + * @since Moodle 3.1 + */ + public static function get_user_best_grade_parameters() { + return new external_function_parameters ( + array( + 'quizid' => new external_value(PARAM_INT, 'quiz instance id'), + 'userid' => new external_value(PARAM_INT, 'user id', VALUE_DEFAULT, 0), + ) + ); + } + + /** + * Get the best current grade for the given user on a quiz. + * + * @param int $quizid quiz instance id + * @param int $userid user id + * @return array of warnings and the grade information + * @since Moodle 3.1 + */ + public static function get_user_best_grade($quizid, $userid = 0) { + global $DB, $USER; + + $warnings = array(); + + $params = array( + 'quizid' => $quizid, + 'userid' => $userid, + ); + $params = self::validate_parameters(self::get_user_best_grade_parameters(), $params); + + // Request and permission validation. + $quiz = $DB->get_record('quiz', array('id' => $params['quizid']), '*', MUST_EXIST); + list($course, $cm) = get_course_and_cm_from_instance($quiz, 'quiz'); + + $context = context_module::instance($cm->id); + self::validate_context($context); + + // Default value for userid. + if (empty($params['userid'])) { + $params['userid'] = $USER->id; + } + + $user = core_user::get_user($params['userid'], '*', MUST_EXIST); + core_user::require_active_user($user); + + // Extra checks so only users with permissions can view other users attempts. + if ($USER->id != $user->id) { + require_capability('mod/quiz:viewreports', $context); + } + + $result = array(); + $grade = quiz_get_best_grade($quiz, $user->id); + + if ($grade === null) { + $result['hasgrade'] = false; + } else { + $result['hasgrade'] = true; + $result['grade'] = $grade; + } + $result['warnings'] = $warnings; + return $result; + } + + /** + * Describes the get_user_best_grade return value. + * + * @return external_single_structure + * @since Moodle 3.1 + */ + public static function get_user_best_grade_returns() { + return new external_single_structure( + array( + 'hasgrade' => new external_value(PARAM_BOOL, 'Whether the user has a grade on the given quiz.'), + 'grade' => new external_value(PARAM_FLOAT, 'The grade (only if the user has a grade).', VALUE_OPTIONAL), + 'warnings' => new external_warnings(), + ) + ); + } + } diff --git a/mod/quiz/db/services.php b/mod/quiz/db/services.php index 792445dd5c4..1f3a787ef03 100644 --- a/mod/quiz/db/services.php +++ b/mod/quiz/db/services.php @@ -52,4 +52,12 @@ $functions = array( 'type' => 'read', 'capabilities' => 'mod/quiz:view' ), + + 'mod_quiz_get_user_best_grade' => array( + 'classname' => 'mod_quiz_external', + 'methodname' => 'get_user_best_grade', + 'description' => 'Get the best current grade for the given user on a quiz.', + 'type' => 'read', + 'capabilities' => 'mod/quiz:view' + ), ); diff --git a/mod/quiz/tests/external_test.php b/mod/quiz/tests/external_test.php index f2867469d9a..07ea08d7845 100644 --- a/mod/quiz/tests/external_test.php +++ b/mod/quiz/tests/external_test.php @@ -386,4 +386,66 @@ class mod_quiz_external_testcase extends externallib_advanced_testcase { $this->assertEquals('invalidparameter', $e->errorcode); } } + + /** + * Test get_user_best_grade + */ + public function test_get_user_best_grade() { + global $DB; + + $this->setUser($this->student); + + $result = mod_quiz_external::get_user_best_grade($this->quiz->id); + $result = external_api::clean_returnvalue(mod_quiz_external::get_user_best_grade_returns(), $result); + + // No grades yet. + $this->assertFalse($result['hasgrade']); + $this->assertTrue(!isset($result['grade'])); + + $grade = new stdClass(); + $grade->quiz = $this->quiz->id; + $grade->userid = $this->student->id; + $grade->grade = 8.9; + $grade->timemodified = time(); + $grade->id = $DB->insert_record('quiz_grades', $grade); + + $result = mod_quiz_external::get_user_best_grade($this->quiz->id); + $result = external_api::clean_returnvalue(mod_quiz_external::get_user_best_grade_returns(), $result); + + // Now I have grades. + $this->assertTrue($result['hasgrade']); + $this->assertEquals(8.9, $result['grade']); + + // We should not see other users grades. + $anotherstudent = self::getDataGenerator()->create_user(); + $this->getDataGenerator()->enrol_user($anotherstudent->id, $this->course->id, $this->studentrole->id, 'manual'); + + try { + mod_quiz_external::get_user_best_grade($this->quiz->id, $anotherstudent->id); + $this->fail('Exception expected due to missing capability.'); + } catch (required_capability_exception $e) { + $this->assertEquals('nopermissions', $e->errorcode); + } + + // Teacher must be able to see student grades. + $this->setUser($this->teacher); + + $result = mod_quiz_external::get_user_best_grade($this->quiz->id, $this->student->id); + $result = external_api::clean_returnvalue(mod_quiz_external::get_user_best_grade_returns(), $result); + + $this->assertTrue($result['hasgrade']); + $this->assertEquals(8.9, $result['grade']); + + // Invalid user. + try { + mod_quiz_external::get_user_best_grade($this->quiz->id, -1); + $this->fail('Exception expected due to missing capability.'); + } catch (dml_missing_record_exception $e) { + $this->assertEquals('invaliduser', $e->errorcode); + } + + // Remove the created data. + $DB->delete_records('quiz_grades', array('id' => $grade->id)); + + } } diff --git a/mod/quiz/version.php b/mod/quiz/version.php index 29f52724f8a..b71a18eca05 100644 --- a/mod/quiz/version.php +++ b/mod/quiz/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2015111603; +$plugin->version = 2015111604; $plugin->requires = 2015111000; $plugin->component = 'mod_quiz'; $plugin->cron = 60;