Skip to content

Commit

Permalink
MDL-52767 mod_quiz: New Web Service get_quiz_access_information
Browse files Browse the repository at this point in the history
  • Loading branch information
jleyva authored and stronk7 committed Mar 22, 2016
1 parent debb1c3 commit a79a636
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 37 deletions.
145 changes: 109 additions & 36 deletions mod/quiz/classes/external.php
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,27 @@ function.', VALUE_OPTIONAL),
);
}


/**
* Utility function for validating a quiz.
*
* @param int $quizid quiz instance id
* @return array array containing the quiz, course, context and course module objects
* @since Moodle 3.1
*/
protected static function validate_quiz($quizid) {
global $DB;

// Request and permission validation.
$quiz = $DB->get_record('quiz', array('id' => $quizid), '*', MUST_EXIST);
list($course, $cm) = get_course_and_cm_from_instance($quiz, 'quiz');

$context = context_module::instance($cm->id);
self::validate_context($context);

return array($quiz, $course, $cm, $context);
}

/**
* Describes the parameters for view_quiz.
*
Expand Down Expand Up @@ -300,12 +321,7 @@ public static function view_quiz($quizid) {
$params = self::validate_parameters(self::view_quiz_parameters(), array('quizid' => $quizid));
$warnings = array();

// 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);
list($quiz, $course, $cm, $context) = self::validate_quiz($params['quizid']);

// Trigger course_module_viewed event and completion.
quiz_view($quiz, $course, $cm, $context);
Expand Down Expand Up @@ -373,12 +389,7 @@ public static function get_user_attempts($quizid, $userid = 0, $status = 'finish
);
$params = self::validate_parameters(self::get_user_attempts_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);
list($quiz, $course, $cm, $context) = self::validate_quiz($params['quizid']);

if (!in_array($params['status'], array('all', 'finished', 'unfinished'))) {
throw new invalid_parameter_exception('Invalid status value');
Expand Down Expand Up @@ -488,12 +499,7 @@ public static function get_user_best_grade($quizid, $userid = 0) {
);
$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);
list($quiz, $course, $cm, $context) = self::validate_quiz($params['quizid']);

// Default value for userid.
if (empty($params['userid'])) {
Expand Down Expand Up @@ -572,12 +578,7 @@ public static function get_combined_review_options($quizid, $userid = 0) {
);
$params = self::validate_parameters(self::get_combined_review_options_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);
list($quiz, $course, $cm, $context) = self::validate_quiz($params['quizid']);

// Default value for userid.
if (empty($params['userid'])) {
Expand Down Expand Up @@ -691,12 +692,7 @@ public static function start_attempt($quizid, $preflightdata = array(), $forcene
$params = self::validate_parameters(self::start_attempt_parameters(), $params);
$forcenew = $params['forcenew'];

// 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);
list($quiz, $course, $cm, $context) = self::validate_quiz($params['quizid']);

$quizobj = quiz::create($cm->instance, $USER->id);

Expand Down Expand Up @@ -1589,12 +1585,7 @@ public static function get_quiz_feedback_for_grade($quizid, $grade) {
$params = self::validate_parameters(self::get_quiz_feedback_for_grade_parameters(), $params);
$warnings = array();

// 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);
list($quiz, $course, $cm, $context) = self::validate_quiz($params['quizid']);

$result = array();
$result['feedbacktext'] = '';
Expand Down Expand Up @@ -1628,4 +1619,86 @@ public static function get_quiz_feedback_for_grade_returns() {
);
}

/**
* Describes the parameters for get_quiz_access_information.
*
* @return external_external_function_parameters
* @since Moodle 3.1
*/
public static function get_quiz_access_information_parameters() {
return new external_function_parameters (
array(
'quizid' => new external_value(PARAM_INT, 'quiz instance id')
)
);
}

/**
* Return access information for a given quiz.
*
* @param int $quizid quiz instance id
* @return array of warnings and the access information
* @since Moodle 3.1
* @throws moodle_quiz_exception
*/
public static function get_quiz_access_information($quizid) {
global $DB, $USER;

$warnings = array();

$params = array(
'quizid' => $quizid
);
$params = self::validate_parameters(self::get_quiz_access_information_parameters(), $params);

list($quiz, $course, $cm, $context) = self::validate_quiz($params['quizid']);

$result = array();
// Capabilities first.
$result['canattempt'] = has_capability('mod/quiz:attempt', $context);;
$result['canmanage'] = has_capability('mod/quiz:manage', $context);;
$result['canpreview'] = has_capability('mod/quiz:preview', $context);;
$result['canreviewmyattempts'] = has_capability('mod/quiz:reviewmyattempts', $context);;
$result['canviewreports'] = has_capability('mod/quiz:viewreports', $context);;

// Access manager now.
$quizobj = quiz::create($cm->instance, $USER->id);
$ignoretimelimits = has_capability('mod/quiz:ignoretimelimits', $context, null, false);
$timenow = time();
$accessmanager = new quiz_access_manager($quizobj, $timenow, $ignoretimelimits);

$result['accessrules'] = $accessmanager->describe_rules();
$result['activerulenames'] = $accessmanager->get_active_rule_names();
$result['preventaccessreasons'] = $accessmanager->prevent_access();

$result['warnings'] = $warnings;
return $result;
}

/**
* Describes the get_quiz_access_information return value.
*
* @return external_single_structure
* @since Moodle 3.1
*/
public static function get_quiz_access_information_returns() {
return new external_single_structure(
array(
'canattempt' => new external_value(PARAM_BOOL, 'Whether the user can do the quiz or not.'),
'canmanage' => new external_value(PARAM_BOOL, 'Whether the user can edit the quiz settings or not.'),
'canpreview' => new external_value(PARAM_BOOL, 'Whether the user can preview the quiz or not.'),
'canreviewmyattempts' => new external_value(PARAM_BOOL, 'Whether the users can review their previous attempts
or not.'),
'canviewreports' => new external_value(PARAM_BOOL, 'Whether the user can view the quiz reports or not.'),
'accessrules' => new external_multiple_structure(
new external_value(PARAM_TEXT, 'rule description'), 'list of rules'),
'activerulenames' => new external_multiple_structure(
new external_value(PARAM_PLUGIN, 'rule plugin names'), 'list of active rules'),
'preventaccessreasons' => new external_multiple_structure(
new external_value(PARAM_TEXT, 'access restriction description'), 'list of reasons'),
'warnings' => new external_warnings(),
)
);
}

}
9 changes: 9 additions & 0 deletions mod/quiz/db/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,13 @@
'capabilities' => 'mod/quiz:view',
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
),

'mod_quiz_get_quiz_access_information' => array(
'classname' => 'mod_quiz_external',
'methodname' => 'get_quiz_access_information',
'description' => 'Return access information for a given quiz.',
'type' => 'read',
'capabilities' => 'mod/quiz:view',
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
),
);
62 changes: 62 additions & 0 deletions mod/quiz/tests/external_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -1399,4 +1399,66 @@ public function test_get_quiz_feedback_for_grade() {
$this->assertEquals(FORMAT_MOODLE, $result['feedbacktextformat']);
}

/**
* Test get_quiz_access_information
*/
public function test_get_quiz_access_information() {
global $DB;

// Create a new quiz.
$quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
$data = array('course' => $this->course->id);
$quiz = $quizgenerator->create_instance($data);

$this->setUser($this->student);

// Default restrictions (none).
$result = mod_quiz_external::get_quiz_access_information($quiz->id);
$result = external_api::clean_returnvalue(mod_quiz_external::get_quiz_access_information_returns(), $result);

$expected = array(
'canattempt' => true,
'canmanage' => false,
'canpreview' => false,
'canreviewmyattempts' => true,
'canviewreports' => false,
'accessrules' => [],
// This rule is always used, even if the quiz has no open or close date.
'activerulenames' => ['quizaccess_openclosedate'],
'preventaccessreasons' => [],
'warnings' => []
);

$this->assertEquals($expected, $result);

// Now teacher, different privileges.
$this->setUser($this->teacher);
$result = mod_quiz_external::get_quiz_access_information($quiz->id);
$result = external_api::clean_returnvalue(mod_quiz_external::get_quiz_access_information_returns(), $result);

$expected['canmanage'] = true;
$expected['canpreview'] = true;
$expected['canviewreports'] = true;
$expected['canattempt'] = false;
$expected['canreviewmyattempts'] = false;

$this->assertEquals($expected, $result);

$this->setUser($this->student);
// Now add some restrictions.
$quiz->timeopen = time() + DAYSECS;
$quiz->timeclose = time() + WEEKSECS;
$quiz->password = '123456';
$DB->update_record('quiz', $quiz);

$result = mod_quiz_external::get_quiz_access_information($quiz->id);
$result = external_api::clean_returnvalue(mod_quiz_external::get_quiz_access_information_returns(), $result);

// Access limited by time and password.
$this->assertCount(3, $result['accessrules']);
// Two rule names, password and open/close date.
$this->assertCount(2, $result['activerulenames']);
$this->assertCount(1, $result['preventaccessreasons']);

}
}
2 changes: 1 addition & 1 deletion mod/quiz/version.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

defined('MOODLE_INTERNAL') || die();

$plugin->version = 2016032106;
$plugin->version = 2016032108;
$plugin->requires = 2015111000;
$plugin->component = 'mod_quiz';
$plugin->cron = 60;

0 comments on commit a79a636

Please sign in to comment.