Merge branch 'MDL-75642-master' of https://github.com/BruceGoodGuy/moodle
This commit is contained in:
@@ -271,7 +271,7 @@ class quiz {
|
||||
/**
|
||||
* Get the quiz context.
|
||||
*
|
||||
* @return context the module context for this quiz.
|
||||
* @return context_module the module context for this quiz.
|
||||
*/
|
||||
public function get_context() {
|
||||
return $this->context;
|
||||
|
||||
@@ -823,7 +823,7 @@ class edit_renderer extends \plugin_renderer_base {
|
||||
$structure->get_question_in_slot($slot),
|
||||
null, null, $qtype);
|
||||
}
|
||||
if ($structure->can_be_edited()) {
|
||||
if ($structure->can_be_edited() && $structure->has_use_capability($slot)) {
|
||||
$questionicons .= $this->question_remove_icon($structure, $slot, $pageurl);
|
||||
}
|
||||
$questionicons .= $this->marked_out_of_field($structure, $slot);
|
||||
|
||||
@@ -244,6 +244,25 @@ class structure {
|
||||
return $this->get_question_in_slot($slotnumber)->length != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the current user have '...use' capability over the question(s) in a given slot?
|
||||
*
|
||||
*
|
||||
* @param int $slotnumber the index of the slot in question.
|
||||
* @return bool true if they have the required capability.
|
||||
*/
|
||||
public function has_use_capability(int $slotnumber): bool {
|
||||
$slot = $this->slotsinorder[$slotnumber];
|
||||
if (is_numeric($slot->questionid)) {
|
||||
// Non-random question.
|
||||
return question_has_capability_on($this->get_question_by_id($slot->questionid), 'use');
|
||||
} else {
|
||||
// Random question.
|
||||
$context = \context::instance_by_id($slot->contextid);
|
||||
return has_capability('moodle/question:useall', $context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the course id that the quiz belongs to.
|
||||
* @return int the course.id for the quiz.
|
||||
|
||||
@@ -156,7 +156,7 @@ switch($requestmethod) {
|
||||
foreach ($ids as $id) {
|
||||
$slot = $DB->get_record('quiz_slots', array('quizid' => $quiz->id, 'id' => $id),
|
||||
'*', MUST_EXIST);
|
||||
if (quiz_has_question_use($quiz, $slot->slot)) {
|
||||
if ($structure->has_use_capability($slot->slot)) {
|
||||
$structure->remove_slot($slot->slot);
|
||||
}
|
||||
}
|
||||
@@ -192,6 +192,13 @@ switch($requestmethod) {
|
||||
if (!$slot = $DB->get_record('quiz_slots', array('quizid' => $quiz->id, 'id' => $id))) {
|
||||
throw new moodle_exception('AJAX commands.php: Bad slot ID '.$id);
|
||||
}
|
||||
|
||||
if (!$structure->has_use_capability($slot->slot)) {
|
||||
$slotdetail = $structure->get_slot_by_id($slot->id);
|
||||
$context = context::instance_by_id($slotdetail->contextid);
|
||||
throw new required_capability_exception($context,
|
||||
'moodle/question:useall', 'nopermissions', '');
|
||||
}
|
||||
$structure->remove_slot($slot->slot);
|
||||
quiz_delete_previews($quiz);
|
||||
quiz_update_sumgrades($quiz);
|
||||
|
||||
@@ -2266,6 +2266,9 @@ function quiz_require_question_use($questionid) {
|
||||
|
||||
/**
|
||||
* Verify that the question exists, and the user has permission to use it.
|
||||
*
|
||||
* @deprecated in 4.1 use mod_quiz\structure::has_use_capability(...) instead.
|
||||
*
|
||||
* @param object $quiz the quiz settings.
|
||||
* @param int $slot which question in the quiz to test.
|
||||
* @return bool whether the user can use this question.
|
||||
@@ -2273,6 +2276,8 @@ function quiz_require_question_use($questionid) {
|
||||
function quiz_has_question_use($quiz, $slot) {
|
||||
global $DB;
|
||||
|
||||
debugging('Deprecated. Please use mod_quiz\structure::has_use_capability instead.');
|
||||
|
||||
$sql = 'SELECT q.*
|
||||
FROM {quiz_slots} slot
|
||||
JOIN {question_references} qre ON qre.itemid = slot.id
|
||||
|
||||
@@ -236,3 +236,61 @@ Feature: Edit quiz page - remove multiple questions
|
||||
And I click on "Delete selected" "button"
|
||||
|
||||
Then I should see "Cannot remove questions"
|
||||
|
||||
@javascript
|
||||
Scenario: Delete multiple random questions from sections.
|
||||
Given the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | Question A | First question |
|
||||
| Test questions | truefalse | Question B | Second question |
|
||||
| Test questions | truefalse | Question C | Third question |
|
||||
| Test questions | truefalse | Question D | Fourth question |
|
||||
| Test questions | truefalse | Question E | Fifth question |
|
||||
| Test questions | truefalse | Question F | Sixth question |
|
||||
And I am on the "Quiz 1" "mod_quiz > Edit" page
|
||||
|
||||
When I open the "last" add to quiz menu
|
||||
And I follow "a random question"
|
||||
And I set the field "Number of random questions" to "3"
|
||||
And I press "Add random question"
|
||||
And I click on "Select multiple items" "button"
|
||||
And I click on "selectquestion-1" "checkbox"
|
||||
And I click on "selectquestion-2" "checkbox"
|
||||
And I click on "Delete selected" "button"
|
||||
And I click on "Yes" "button" in the "Confirm" "dialogue"
|
||||
# To make sure question is deleted completely.
|
||||
And I reload the page
|
||||
Then I should see "Random (Test questions)" on quiz page "1"
|
||||
And I should not see "Random (Test questions)" on quiz page "2"
|
||||
And I should not see "Random (Test questions)" on quiz page "3"
|
||||
And I should see "Total of marks: 1.00"
|
||||
And I should see "Questions: 1"
|
||||
|
||||
@javascript
|
||||
Scenario: Delete all random questions by checking select all.
|
||||
Given the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | Question A | First question |
|
||||
| Test questions | truefalse | Question B | Second question |
|
||||
| Test questions | truefalse | Question C | Third question |
|
||||
| Test questions | truefalse | Question D | Fourth question |
|
||||
| Test questions | truefalse | Question E | Fifth question |
|
||||
| Test questions | truefalse | Question F | Sixth question |
|
||||
And I am on the "Quiz 1" "mod_quiz > Edit" page
|
||||
|
||||
# Delete all questions in page. Page contains multiple questions.
|
||||
When I open the "last" add to quiz menu
|
||||
And I follow "a random question"
|
||||
And I set the field "Number of random questions" to "3"
|
||||
And I press "Add random question"
|
||||
And I click on "Select multiple items" "button"
|
||||
And I press "Select all"
|
||||
And I click on "Delete selected" "button"
|
||||
And I click on "Yes" "button" in the "Confirm" "dialogue"
|
||||
# To make sure question is deleted completely.
|
||||
And I reload the page
|
||||
Then I should not see "Random (Test questions)" on quiz page "1"
|
||||
And I should not see "Random (Test questions)" on quiz page "2"
|
||||
And I should not see "Random (Test questions)" on quiz page "3"
|
||||
And I should see "Total of marks: 0.00"
|
||||
And I should see "Questions: 0"
|
||||
|
||||
@@ -958,4 +958,39 @@ class structure_test extends \advanced_testcase {
|
||||
$this->assertFalse($versiondata[2]->selected);
|
||||
$this->assertFalse($versiondata[3]->selected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the current user have '...use' capability over the question(s) in a given slot.
|
||||
*
|
||||
* @covers ::has_use_capability
|
||||
*/
|
||||
public function test_has_use_capability() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Create a quiz with question.
|
||||
$quizobj = $this->create_test_quiz([]);
|
||||
$questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
$cat = $questiongenerator->create_question_category(['contextid' => $quizobj->get_context()->id]);
|
||||
$q = $questiongenerator->create_question('essay', null,
|
||||
['category' => $cat->id, 'name' => 'This is essay question']);
|
||||
quiz_add_quiz_question($q->id, $quizobj->get_quiz());
|
||||
|
||||
// Create the quiz object.
|
||||
$structure = structure::create_for_quiz($quizobj);
|
||||
$slots = $structure->get_slots();
|
||||
|
||||
// Get slot.
|
||||
$slotid = array_pop($slots)->slot;
|
||||
|
||||
$course = $quizobj->get_course();
|
||||
$generator = $this->getDataGenerator();
|
||||
$teacher = $generator->create_and_enrol($course, 'editingteacher');
|
||||
$student = $generator->create_and_enrol($course);
|
||||
|
||||
$this->setUser($teacher);
|
||||
$this->assertTrue($structure->has_use_capability($slotid));
|
||||
|
||||
$this->setUser($student);
|
||||
$this->assertFalse($structure->has_use_capability($slotid));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
This files describes API changes in the quiz code.
|
||||
|
||||
=== 4.1 ===
|
||||
|
||||
* quiz_has_question_use is now deprecated. Use mod_quiz\structure::has_use_capability istead.
|
||||
|
||||
|
||||
=== 4.0.3, 4.1 ===
|
||||
|
||||
* If a quiz is sequential the external functions mod_quiz_external::get_attempt_data, mod_quiz_external::get_attempt_summary will not return any data
|
||||
|
||||
Reference in New Issue
Block a user