MDL-71378 core_question & mod_quiz: Refactor deprecated contexts
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
issueNumber: MDL-71378
|
||||
notes:
|
||||
tool_brickfield:
|
||||
- message: >
|
||||
tool_brickfield\local\areas\core_question\answerbase::find_system_areas
|
||||
|
||||
|
||||
No replacement. System context no longer a valid context to assign a
|
||||
question category
|
||||
type: deprecated
|
||||
- message: >
|
||||
tool_brickfield\local\areas\core_question\base::find_system_areas
|
||||
|
||||
|
||||
No replacement. System context no longer a valid context to assign a
|
||||
question category
|
||||
type: deprecated
|
||||
@@ -0,0 +1,42 @@
|
||||
issueNumber: MDL-71378
|
||||
notes:
|
||||
core:
|
||||
- message: >
|
||||
question_make_default_categories()
|
||||
|
||||
|
||||
No longer creates a default category in either CONTEXT_SYSTEM,
|
||||
CONTEXT_COURSE, or CONTEXT_COURSECAT.
|
||||
|
||||
Superceded by question_get_default_category which can optionally create one if it does not exist.
|
||||
type: deprecated
|
||||
- message: |
|
||||
question_delete_course()
|
||||
|
||||
No replacement. Course contexts no longer hold question categories.
|
||||
type: deprecated
|
||||
- message: |
|
||||
question_delete_course_category()
|
||||
|
||||
Course category contexts no longer hold question categories.
|
||||
type: deprecated
|
||||
qbank_bulkmove:
|
||||
- message: >
|
||||
qbank_bulkmove/helper::get_displaydata
|
||||
|
||||
|
||||
Superceded by a modal and webservice, see
|
||||
qbank_bulkmove/modal_question_bank_bulkmove and
|
||||
core_question_external\move_questions
|
||||
type: deprecated
|
||||
- message: |
|
||||
qbank_bulkmove\output\renderer::render_bulk_move_form
|
||||
|
||||
Superceded by qbank_bulkmove\output\bulk_move
|
||||
type: deprecated
|
||||
core_question:
|
||||
- message: |
|
||||
question_type::generate_test
|
||||
|
||||
No replacement, not used anywhere in core.
|
||||
type: deprecated
|
||||
@@ -82,8 +82,12 @@ abstract class answerbase extends base {
|
||||
* question categories at the system context, or course category context.
|
||||
*
|
||||
* @return mixed
|
||||
* @deprecated since Moodle 5.0.
|
||||
* @todo MDL-82413 Final deprecation in Moodle 6.0.
|
||||
*/
|
||||
#[\core\attribute\deprecated(null, since: '5.0', reason: 'This method should not be used', mdl: 'MDL-71378')]
|
||||
public function find_system_areas(): ?\moodle_recordset {
|
||||
\core\deprecation::emit_deprecation_if_present([self::class, __FUNCTION__]);
|
||||
global $DB;
|
||||
$params = [
|
||||
'syscontext' => CONTEXT_SYSTEM,
|
||||
@@ -132,8 +136,6 @@ abstract class answerbase extends base {
|
||||
|
||||
$coursecontext = \context_course::instance($courseid);
|
||||
$param = [
|
||||
'ctxcourse' => CONTEXT_COURSE,
|
||||
'courseid' => $courseid,
|
||||
'module' => CONTEXT_MODULE,
|
||||
'coursecontextpath' => $DB->sql_like_escape($coursecontext->path) . '/%',
|
||||
];
|
||||
@@ -157,11 +159,8 @@ abstract class answerbase extends base {
|
||||
ON qc.id = qbe.questioncategoryid
|
||||
INNER JOIN {context} ctx
|
||||
ON ctx.id = qc.contextid
|
||||
WHERE (ctx.contextlevel = :ctxcourse
|
||||
AND ctx.id = qc.contextid
|
||||
AND ctx.instanceid = :courseid)
|
||||
OR (ctx.contextlevel = :module
|
||||
AND {$DB->sql_like('ctx.path', ':coursecontextpath')})
|
||||
WHERE ctx.contextlevel = :module
|
||||
AND {$DB->sql_like('ctx.path', ':coursecontextpath')}
|
||||
ORDER BY a.id ASC";
|
||||
|
||||
return $DB->get_recordset_sql($sql, $param);
|
||||
|
||||
@@ -74,8 +74,6 @@ abstract class base extends area_base {
|
||||
global $DB;
|
||||
$coursecontext = \context_course::instance($courseid);
|
||||
$param = [
|
||||
'ctxcourse' => CONTEXT_COURSE,
|
||||
'courseid' => $courseid,
|
||||
'module' => CONTEXT_MODULE,
|
||||
'coursecontextpath' => $DB->sql_like_escape($coursecontext->path) . '/%',
|
||||
];
|
||||
@@ -96,11 +94,8 @@ abstract class base extends area_base {
|
||||
ON qc.id = qbe.questioncategoryid
|
||||
INNER JOIN {context} ctx
|
||||
ON ctx.id = qc.contextid
|
||||
WHERE (ctx.contextlevel = :ctxcourse
|
||||
AND ctx.id = qc.contextid
|
||||
AND ctx.instanceid = :courseid)
|
||||
OR (ctx.contextlevel = :module
|
||||
AND {$DB->sql_like('ctx.path', ':coursecontextpath')})
|
||||
WHERE ctx.contextlevel = :module
|
||||
AND {$DB->sql_like('ctx.path', ':coursecontextpath')}
|
||||
ORDER BY q.id ASC";
|
||||
|
||||
return $DB->get_recordset_sql($sql, $param);
|
||||
@@ -111,8 +106,12 @@ abstract class base extends area_base {
|
||||
* question categories at the system context only.
|
||||
*
|
||||
* @return \moodle_recordset
|
||||
* @deprecated since Moodle 5.0.
|
||||
* @todo MDL-82413 Final deprecation in Moodle 6.0.
|
||||
*/
|
||||
#[\core\attribute\deprecated(null, since: '5.0', reason: 'This method should not be used', mdl: 'MDL-71378')]
|
||||
public function find_system_areas(): ?\moodle_recordset {
|
||||
\core\deprecation::emit_deprecation_if_present([self::class, __FUNCTION__]);
|
||||
global $DB;
|
||||
$params = [
|
||||
'syscontext' => CONTEXT_SYSTEM,
|
||||
@@ -175,15 +174,7 @@ abstract class base extends area_base {
|
||||
$catid = 'null';
|
||||
|
||||
if ($record = self::get_course_and_category(CONTEXT_MODULE, $event->objectid)) {
|
||||
if ($record->contextlevel == CONTEXT_MODULE) {
|
||||
$courseid = $record->courseid;
|
||||
} else if ($record->contextlevel == CONTEXT_COURSE) {
|
||||
$courseid = $record->instanceid;
|
||||
} else if ($record->contextlevel == CONTEXT_COURSECAT) {
|
||||
$catid = $record->instanceid;
|
||||
} else if ($record->contextlevel == CONTEXT_SYSTEM) {
|
||||
$courseid = 1;
|
||||
}
|
||||
$courseid = $record->courseid;
|
||||
}
|
||||
|
||||
return "
|
||||
@@ -202,6 +193,10 @@ abstract class base extends area_base {
|
||||
public static function get_course_and_category($coursemodule, $refid) {
|
||||
global $DB;
|
||||
|
||||
if ($coursemodule !== CONTEXT_MODULE) {
|
||||
debugging("Invalid contextlevel: ($coursemodule}", DEBUG_DEVELOPER);
|
||||
}
|
||||
|
||||
$sql = 'SELECT ctx.instanceid,
|
||||
cm.course as courseid,
|
||||
ctx.contextlevel
|
||||
@@ -214,7 +209,7 @@ abstract class base extends area_base {
|
||||
ON qc.id = qbe.questioncategoryid
|
||||
INNER JOIN {context} ctx
|
||||
ON ctx.id = qc.contextid
|
||||
LEFT JOIN {course_modules} cm
|
||||
INNER JOIN {course_modules} cm
|
||||
ON cm.id = ctx.instanceid
|
||||
AND ctx.contextlevel = :coursemodule
|
||||
WHERE q.id = :refid';
|
||||
|
||||
@@ -93,51 +93,30 @@ class area_test extends area_test_base {
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
$component = 'core_question';
|
||||
|
||||
list($category1, $course1, $qcat1, $questions1) = $generator->setup_course_and_questions('course');
|
||||
list($category2, $course2, $qcat2, $questions2) = $generator->setup_course_and_questions('category');
|
||||
list($category3, $course3, $qcat3, $questions3) = $generator->setup_course_and_questions('system');
|
||||
[$category, $course, $qcat, $questions, $qbank] = $generator->setup_course_and_questions();
|
||||
|
||||
$c = new \tool_brickfield\local\areas\core_question\questiontext();
|
||||
// Set up results arrays from the recordset for easier testing.
|
||||
$course1areas = $this->array_from_recordset($c->find_course_areas($course1->id));
|
||||
$course2areas = $c->find_course_areas($course2->id);
|
||||
$course3areas = $c->find_course_areas($course3->id);
|
||||
$sysareas = $this->array_from_recordset($c->find_system_areas());
|
||||
$course1areas = $this->array_from_recordset($c->find_course_areas($course->id));
|
||||
|
||||
// Assert the core_question area exists for the individual question's context, courseid and categoryid.
|
||||
// Assert the core_question area exists for the individual question's context, courseid and categoryid.
|
||||
$this->assert_area_in_array(
|
||||
$course1areas,
|
||||
$component,
|
||||
\context_course::instance($course1->id)->id,
|
||||
$questions1[0]->id,
|
||||
$course1->id,
|
||||
null
|
||||
);
|
||||
$this->assert_area_in_array(
|
||||
$sysareas,
|
||||
$component,
|
||||
\context_coursecat::instance($category2->id)->id,
|
||||
$questions2[0]->id,
|
||||
SITEID,
|
||||
$category2->id
|
||||
);
|
||||
$this->assert_area_in_array(
|
||||
$sysareas,
|
||||
$component,
|
||||
\context_system::instance()->id,
|
||||
$questions3[0]->id,
|
||||
SITEID,
|
||||
\context_module::instance($qbank->cmid)->id,
|
||||
$questions[0]->id,
|
||||
$course->id,
|
||||
null
|
||||
);
|
||||
|
||||
// Emulate the question_created event.
|
||||
$event = \core\event\question_created::create_from_question_instance($questions1[1],
|
||||
\context_course::instance($course1->id));
|
||||
$event = \core\event\question_created::create_from_question_instance($questions[1],
|
||||
\context_module::instance($qbank->cmid));
|
||||
$relevantresults = $this->array_from_recordset($c->find_relevant_areas($event));
|
||||
$this->assert_area_in_array(
|
||||
$course1areas,
|
||||
$relevantresults,
|
||||
$component,
|
||||
\context_course::instance($relevantresults[0]->courseid)->id,
|
||||
$relevantresults[0]->contextid,
|
||||
$relevantresults[0]->itemid,
|
||||
$relevantresults[0]->courseid,
|
||||
$relevantresults[0]->categoryid
|
||||
@@ -154,7 +133,8 @@ class area_test extends area_test_base {
|
||||
/** @var \core_question_generator $generator */
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$cat = $generator->create_question_category(['contextid' => \context_course::instance($course->id)->id]);
|
||||
$qbank = $this->getDataGenerator()->create_module('qbank', ['course' => $course->id]);
|
||||
$cat = $generator->create_question_category(['contextid' => \context_module::instance($qbank->cmid)->id]);
|
||||
$question1 = $generator->create_question('multichoice', null,
|
||||
['name' => 'Example multichoice question', 'category' => $cat->id]);
|
||||
$question2 = $generator->create_question('numerical', null,
|
||||
|
||||
@@ -34,92 +34,6 @@ class questionanswers_test extends \advanced_testcase {
|
||||
parent::setUpBeforeClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test find course areas.
|
||||
*/
|
||||
public function test_find_course_areas(): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$category = $this->getDataGenerator()->create_category();
|
||||
$course = $this->getDataGenerator()->create_course(['category' => $category->id]);
|
||||
$coursecontext = \context_course::instance($course->id);
|
||||
$catcontext = \context_coursecat::instance($category->id);
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
$cat1 = $generator->create_question_category(['contextid' => $coursecontext->id]);
|
||||
$question1 = $generator->create_question('multichoice', null, ['category' => $cat1->id]);
|
||||
$question2 = $generator->create_question('multichoice', null, ['category' => $cat1->id]);
|
||||
$questionanswers = new questionanswers();
|
||||
$rs = $questionanswers->find_course_areas($course->id);
|
||||
$this->assertNotNull($rs);
|
||||
|
||||
// Each multichoice question generated has four answers. So there should be eight records.
|
||||
$count = 0;
|
||||
foreach ($rs as $rec) {
|
||||
$count++;
|
||||
$this->assertEquals($coursecontext->id, $rec->contextid);
|
||||
$this->assertEquals($course->id, $rec->courseid);
|
||||
if ($count <= 4) {
|
||||
$this->assertEquals($question1->id, $rec->refid);
|
||||
} else {
|
||||
$this->assertEquals($question2->id, $rec->refid);
|
||||
}
|
||||
}
|
||||
$rs->close();
|
||||
$this->assertEquals(8, $count);
|
||||
|
||||
// Add a question to a quiz in the course.
|
||||
$quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id, 'name' => 'Quiz1']);
|
||||
$quizmodule = get_coursemodule_from_instance('quiz', $quiz->id, $course->id);
|
||||
$quizcontext = \context_module::instance($quizmodule->id);
|
||||
|
||||
// Add a question to the quiz context.
|
||||
$cat2 = $generator->create_question_category(['contextid' => $quizcontext->id]);
|
||||
$question3 = $generator->create_question('multichoice', null, ['category' => $cat2->id]);
|
||||
$rs2 = $questionanswers->find_course_areas($course->id);
|
||||
$this->assertNotNull($rs2);
|
||||
|
||||
// Each multichoice question generated has four answers. So there should be twelve records now.
|
||||
$count = 0;
|
||||
foreach ($rs2 as $rec) {
|
||||
$count++;
|
||||
if ($count <= 4) {
|
||||
$this->assertEquals($coursecontext->id, $rec->contextid);
|
||||
$this->assertEquals($course->id, $rec->courseid);
|
||||
$this->assertEquals($question1->id, $rec->refid);
|
||||
} else if ($count <= 8) {
|
||||
$this->assertEquals($coursecontext->id, $rec->contextid);
|
||||
$this->assertEquals($course->id, $rec->courseid);
|
||||
$this->assertEquals($question2->id, $rec->refid);
|
||||
} else {
|
||||
$this->assertEquals($quizcontext->id, $rec->contextid);
|
||||
$this->assertEquals($course->id, $rec->courseid);
|
||||
$this->assertEquals($question3->id, $rec->refid);
|
||||
}
|
||||
}
|
||||
$rs2->close();
|
||||
$this->assertEquals(12, $count);
|
||||
|
||||
// Add a question to the category context.
|
||||
$cat3 = $generator->create_question_category(['contextid' => $catcontext->id]);
|
||||
$question4 = $generator->create_question('multichoice', null, ['category' => $cat3->id]);
|
||||
$rs3 = $questionanswers->find_course_areas($course->id);
|
||||
$this->assertNotNull($rs3);
|
||||
|
||||
// The category level questions should not be found.
|
||||
$count = 0;
|
||||
foreach ($rs3 as $rec) {
|
||||
$count++;
|
||||
if ($count > 8) {
|
||||
$this->assertEquals($quizcontext->id, $rec->contextid);
|
||||
$this->assertEquals($course->id, $rec->courseid);
|
||||
$this->assertEquals($question3->id, $rec->refid);
|
||||
}
|
||||
}
|
||||
$rs2->close();
|
||||
$this->assertEquals(12, $count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test find relevant areas.
|
||||
*/
|
||||
@@ -128,9 +42,10 @@ class questionanswers_test extends \advanced_testcase {
|
||||
$this->setAdminUser();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$coursecontext = \context_course::instance($course->id);
|
||||
$qbank = $this->getDataGenerator()->create_module('qbank', ['course' => $course->id]);
|
||||
$qbankcontext = \context_module::instance($qbank->cmid);
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
$cat1 = $generator->create_question_category(['contextid' => $coursecontext->id]);
|
||||
$cat1 = $generator->create_question_category(['contextid' => $qbankcontext->id]);
|
||||
$question1 = $generator->create_question('multichoice', null, ['category' => $cat1->id]);
|
||||
$question2 = $generator->create_question('multichoice', null, ['category' => $cat1->id]);
|
||||
$questionanswers = new questionanswers();
|
||||
@@ -143,50 +58,11 @@ class questionanswers_test extends \advanced_testcase {
|
||||
$count = 0;
|
||||
foreach ($rs as $rec) {
|
||||
$count++;
|
||||
$this->assertEquals($coursecontext->id, $rec->contextid);
|
||||
$this->assertEquals($qbankcontext->id, $rec->contextid);
|
||||
$this->assertEquals($course->id, $rec->courseid);
|
||||
$this->assertEquals($question1->id, $rec->refid);
|
||||
}
|
||||
$rs->close();
|
||||
$this->assertEquals(4, $count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test find system areas.
|
||||
*/
|
||||
public function test_find_system_areas(): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$category = $this->getDataGenerator()->create_category();
|
||||
$catcontext = \context_coursecat::instance($category->id);
|
||||
$systemcontext = \context_system::instance();
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
$cat = $generator->create_question_category(['contextid' => $catcontext->id]);
|
||||
$cat2 = $generator->create_question_category(['contextid' => $systemcontext->id]);
|
||||
$question = $generator->create_question('multichoice', null, ['category' => $cat2->id]);
|
||||
$question2 = $generator->create_question('multichoice', null, ['category' => $cat->id]);
|
||||
$questionanswers = new questionanswers();
|
||||
$rs = $questionanswers->find_system_areas();
|
||||
$this->assertNotNull($rs);
|
||||
|
||||
// Each multichoice question generated has four answers.
|
||||
$count = 0;
|
||||
foreach ($rs as $rec) {
|
||||
$count++;
|
||||
if ($count <= 4) {
|
||||
$this->assertEquals($systemcontext->id, $rec->contextid);
|
||||
$this->assertEquals(1, $rec->courseid);
|
||||
$this->assertEquals(0, $rec->categoryid);
|
||||
$this->assertEquals($question->id, $rec->refid);
|
||||
} else {
|
||||
$this->assertEquals($catcontext->id, $rec->contextid);
|
||||
$this->assertEquals(1, $rec->courseid);
|
||||
$this->assertEquals($category->id, $rec->categoryid);
|
||||
$this->assertEquals($question2->id, $rec->refid);
|
||||
}
|
||||
}
|
||||
$rs->close();
|
||||
$this->assertEquals(8, $count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,90 +40,6 @@ class questiontext_test extends area_test_base {
|
||||
parent::setUpBeforeClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test find course areas.
|
||||
*/
|
||||
public function test_find_course_areas(): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$category = $this->getDataGenerator()->create_category();
|
||||
$course = $this->getDataGenerator()->create_course(['category' => $category->id]);
|
||||
$coursecontext = \context_course::instance($course->id);
|
||||
$catcontext = \context_coursecat::instance($category->id);
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
$cat1 = $generator->create_question_category(['contextid' => $coursecontext->id]);
|
||||
$question1 = $generator->create_question('multichoice', null, ['category' => $cat1->id]);
|
||||
$question2 = $generator->create_question('multichoice', null, ['category' => $cat1->id]);
|
||||
$questiontext = new questiontext();
|
||||
$rs = $questiontext->find_course_areas($course->id);
|
||||
$this->assertNotNull($rs);
|
||||
|
||||
$count = 0;
|
||||
foreach ($rs as $rec) {
|
||||
$count++;
|
||||
$this->assertEquals($coursecontext->id, $rec->contextid);
|
||||
$this->assertEquals($course->id, $rec->courseid);
|
||||
if ($count <= 1) {
|
||||
$this->assertEquals($question1->id, $rec->itemid);
|
||||
} else {
|
||||
$this->assertEquals($question2->id, $rec->itemid);
|
||||
}
|
||||
}
|
||||
$rs->close();
|
||||
$this->assertEquals(2, $count);
|
||||
|
||||
// Add a question to a quiz in the course.
|
||||
$quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id, 'name' => 'Quiz1']);
|
||||
$quizmodule = get_coursemodule_from_instance('quiz', $quiz->id, $course->id);
|
||||
$quizcontext = \context_module::instance($quizmodule->id);
|
||||
|
||||
// Add a question to the quiz context.
|
||||
$cat2 = $generator->create_question_category(['contextid' => $quizcontext->id]);
|
||||
$question3 = $generator->create_question('multichoice', null, ['category' => $cat2->id]);
|
||||
$rs2 = $questiontext->find_course_areas($course->id);
|
||||
$this->assertNotNull($rs2);
|
||||
|
||||
$count = 0;
|
||||
foreach ($rs2 as $rec) {
|
||||
$count++;
|
||||
if ($count <= 1) {
|
||||
$this->assertEquals($coursecontext->id, $rec->contextid);
|
||||
$this->assertEquals($course->id, $rec->courseid);
|
||||
$this->assertEquals($question1->id, $rec->itemid);
|
||||
} else if ($count <= 2) {
|
||||
$this->assertEquals($coursecontext->id, $rec->contextid);
|
||||
$this->assertEquals($course->id, $rec->courseid);
|
||||
$this->assertEquals($question2->id, $rec->itemid);
|
||||
} else {
|
||||
$this->assertEquals($quizcontext->id, $rec->contextid);
|
||||
$this->assertEquals($course->id, $rec->courseid);
|
||||
$this->assertEquals($question3->id, $rec->itemid);
|
||||
}
|
||||
}
|
||||
$rs2->close();
|
||||
$this->assertEquals(3, $count);
|
||||
|
||||
// Add a question to the category context.
|
||||
$cat3 = $generator->create_question_category(['contextid' => $catcontext->id]);
|
||||
$question4 = $generator->create_question('multichoice', null, ['category' => $cat3->id]);
|
||||
$rs3 = $questiontext->find_course_areas($course->id);
|
||||
$this->assertNotNull($rs3);
|
||||
|
||||
// The category level questions should not be found.
|
||||
$count = 0;
|
||||
foreach ($rs3 as $rec) {
|
||||
$count++;
|
||||
if ($count > 2) {
|
||||
$this->assertEquals($quizcontext->id, $rec->contextid);
|
||||
$this->assertEquals($course->id, $rec->courseid);
|
||||
$this->assertEquals($question3->id, $rec->itemid);
|
||||
}
|
||||
}
|
||||
$rs2->close();
|
||||
$this->assertEquals(3, $count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test find relevant areas.
|
||||
*/
|
||||
@@ -132,9 +48,10 @@ class questiontext_test extends area_test_base {
|
||||
$this->setAdminUser();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$coursecontext = \context_course::instance($course->id);
|
||||
$qbank = $this->getDataGenerator()->create_module('qbank', ['course' => $course->id]);
|
||||
$qbankcontext = \context_module::instance($qbank->cmid);
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
$cat1 = $generator->create_question_category(['contextid' => $coursecontext->id]);
|
||||
$cat1 = $generator->create_question_category(['contextid' => $qbankcontext->id]);
|
||||
$question1 = $generator->create_question('multichoice', null, ['category' => $cat1->id]);
|
||||
$question2 = $generator->create_question('multichoice', null, ['category' => $cat1->id]);
|
||||
$questiontext = new questiontext();
|
||||
@@ -146,7 +63,7 @@ class questiontext_test extends area_test_base {
|
||||
$count = 0;
|
||||
foreach ($rs as $rec) {
|
||||
$count++;
|
||||
$this->assertEquals($coursecontext->id, $rec->contextid);
|
||||
$this->assertEquals($qbankcontext->id, $rec->contextid);
|
||||
$this->assertEquals($course->id, $rec->courseid);
|
||||
$this->assertEquals($question1->id, $rec->itemid);
|
||||
}
|
||||
@@ -154,45 +71,6 @@ class questiontext_test extends area_test_base {
|
||||
$this->assertEquals(1, $count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test find system areas.
|
||||
*/
|
||||
public function test_find_system_areas(): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$category = $this->getDataGenerator()->create_category();
|
||||
$catcontext = \context_coursecat::instance($category->id);
|
||||
$systemcontext = \context_system::instance();
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
$component = 'core_question';
|
||||
|
||||
$cat = $generator->create_question_category(['contextid' => $catcontext->id]);
|
||||
$cat2 = $generator->create_question_category(['contextid' => $systemcontext->id]);
|
||||
$question = $generator->create_question('multichoice', null, ['category' => $cat2->id]);
|
||||
$question2 = $generator->create_question('multichoice', null, ['category' => $cat->id]);
|
||||
$questiontext = new questiontext();
|
||||
$areas = $this->array_from_recordset($questiontext->find_system_areas());
|
||||
|
||||
// Assert the core_question area exists for the individual question's context, courseid and categoryid.
|
||||
$this->assert_area_in_array(
|
||||
$areas,
|
||||
$component,
|
||||
$systemcontext->id,
|
||||
$question->id,
|
||||
SITEID,
|
||||
null
|
||||
);
|
||||
$this->assert_area_in_array(
|
||||
$areas,
|
||||
$component,
|
||||
$catcontext->id,
|
||||
$question2->id,
|
||||
SITEID,
|
||||
$category->id
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get course and category.
|
||||
*
|
||||
@@ -203,21 +81,18 @@ class questiontext_test extends area_test_base {
|
||||
$this->setAdminUser();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$coursecontext = \context_course::instance($course->id);
|
||||
$qbank = $this->getDataGenerator()->create_module('qbank', ['course' => $course->id]);
|
||||
$qbankcontext = \context_module::instance($qbank->cmid);
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
$cat1 = $generator->create_question_category(['contextid' => $coursecontext->id]);
|
||||
$cat1 = $generator->create_question_category(['contextid' => $qbankcontext->id]);
|
||||
$question1 = $generator->create_question('multichoice', null, ['category' => $cat1->id]);
|
||||
$event = \core\event\question_updated::create_from_question_instance($question1,
|
||||
\context_course::instance($course->id));
|
||||
$rs = base::get_course_and_category(CONTEXT_COURSE, $event->objectid);
|
||||
$event = \core\event\question_updated::create_from_question_instance($question1, $qbankcontext);
|
||||
$rs = base::get_course_and_category(CONTEXT_MODULE, $event->objectid);
|
||||
$this->assertNotNull($rs);
|
||||
$this->assertEquals(CONTEXT_COURSE, $rs->contextlevel);
|
||||
$this->assertNotEquals(CONTEXT_MODULE, $rs->contextlevel);
|
||||
// Invalid objectid.
|
||||
$this->assertEquals(CONTEXT_MODULE, $rs->contextlevel);
|
||||
// Invalid objectid and contextlevel.
|
||||
$rs = base::get_course_and_category(CONTEXT_COURSE, 0);
|
||||
$this->assertFalse($rs);
|
||||
// Incorrect objectid.
|
||||
$rs = base::get_course_and_category(CONTEXT_COURSE, 100);
|
||||
$this->assertFalse($rs);
|
||||
$this->assertDebuggingCalled();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5119,7 +5119,14 @@ class restore_create_categories_and_questions extends restore_structure_step {
|
||||
// As we can't create a 'Top' category in CONTEXT_COURSE we'll make a default
|
||||
// qbank module and map it to that until they are created later.
|
||||
if (empty($mapping->info->parent) && $before35) {
|
||||
$top = question_get_top_category($data->contextid, true);
|
||||
if ($context->contextlevel === CONTEXT_COURSE) {
|
||||
$course = get_course($context->instanceid);
|
||||
$defaultbank = \core_question\local\bank\question_bank_helper::get_default_open_instance_system_type($course, true);
|
||||
$bankcontextid = $defaultbank->context->id;
|
||||
} else {
|
||||
$bankcontextid = $data->contextid;
|
||||
}
|
||||
$top = question_get_top_category($bankcontextid, true);
|
||||
$data->parent = $top->id;
|
||||
}
|
||||
|
||||
@@ -5426,8 +5433,9 @@ class restore_create_categories_and_questions extends restore_structure_step {
|
||||
$newparent = 0; // No ctx match for both cats, no parent relationship
|
||||
}
|
||||
}
|
||||
$context = \core\context::instance_by_id($dbcat->contextid);
|
||||
// Here with $newparent empty, problem with contexts or remapping, set it to top cat
|
||||
if (!$newparent && $dbcat->parent) {
|
||||
if (!$newparent && $dbcat->parent && $context->contextlevel === CONTEXT_MODULE) {
|
||||
$topcat = question_get_top_category($dbcat->contextid, true);
|
||||
if ($dbcat->parent != $topcat->id) {
|
||||
$DB->set_field('question_categories', 'parent', $topcat->id, array('id' => $dbcat->id));
|
||||
|
||||
@@ -2056,9 +2056,6 @@ class core_course_category implements renderable, cacheable_object, IteratorAggr
|
||||
if (!$cb->delete_contents($this->get_context())) {
|
||||
throw new moodle_exception('errordeletingcontentfromcategory', 'contentbank', '', $this->get_formatted_name());
|
||||
}
|
||||
if (!question_delete_course_category($this, null)) {
|
||||
throw new moodle_exception('cannotdeletecategoryquestions', '', '', $this->get_formatted_name());
|
||||
}
|
||||
|
||||
// Delete all events in the category.
|
||||
$DB->delete_records('event', array('categoryid' => $this->id));
|
||||
@@ -2245,12 +2242,6 @@ class core_course_category implements renderable, cacheable_object, IteratorAggr
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!question_delete_course_category($this, $newparentcat)) {
|
||||
if ($showfeedback) {
|
||||
echo $OUTPUT->notification(get_string('errordeletingquestionsfromcategory', 'question', $catname), 'notifysuccess');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Finally delete the category and it's context.
|
||||
$categoryrecord = $this->get_db_record();
|
||||
|
||||
+3
-1
@@ -65,7 +65,6 @@ $string['cannotcreateuploaddir'] = 'Cannot create upload folder. The site admini
|
||||
$string['cannotcustomisefiltersblockuser'] = 'You cannot customise filters settings in user or block contexts.';
|
||||
$string['cannotdeletebackupids'] = 'Couldn\'t delete previous backup ids';
|
||||
$string['cannotdeletecategorycourse'] = 'Course \'{$a}\' failed to be deleted.';
|
||||
$string['cannotdeletecategoryquestions'] = 'Could not delete questions from category \'{$a}\'';
|
||||
$string['cannotdeletecourse'] = 'You do not have the permission to delete this course';
|
||||
$string['cannotdeletecustomfield'] = 'Error deleting custom field data';
|
||||
$string['cannotdeletedir'] = 'Cannot delete ({$a})';
|
||||
@@ -664,3 +663,6 @@ $string['unknownhelp'] = 'Unknown help section {$a}';
|
||||
// Deprecated since Moodle 4.5.
|
||||
$string['cannotsetpassword'] = 'Could not set user password!';
|
||||
$string['myisamproblem'] = 'Database tables are using MyISAM database engine, it is recommended to use ACID compliant engine with full transaction support such as InnoDB.';
|
||||
|
||||
// Deprecated since Moodle 5.0.
|
||||
$string['cannotdeletecategoryquestions'] = 'Could not delete questions from category \'{$a}\'';
|
||||
|
||||
@@ -131,7 +131,6 @@ $string['editthiscategory'] = 'Edit this category';
|
||||
$string['emptyxml'] = 'Unknown error - empty imsmanifest.xml';
|
||||
$string['enabled'] = 'Enabled';
|
||||
$string['erroraccessingcontext'] = 'Cannot access context';
|
||||
$string['errordeletingquestionsfromcategory'] = 'Error deleting questions from category {$a}.';
|
||||
$string['errorduringpost'] = 'Error occurred during post-processing!';
|
||||
$string['errorduringpre'] = 'Error occurred during pre-processing!';
|
||||
$string['errorduringproc'] = 'Error occurred during processing!';
|
||||
@@ -534,3 +533,6 @@ $string['version_selection'] = 'Version {$a->version}';
|
||||
$string['versioninfo'] = 'Version {$a->version} (of {$a->latestversion})';
|
||||
$string['versioninfolatest'] = 'Version {$a->version} (latest)';
|
||||
$string['question_version'] = 'Question version';
|
||||
|
||||
// Deprecated since Moodle 5.0.
|
||||
$string['errordeletingquestionsfromcategory'] = 'Error deleting questions from category {$a}.';
|
||||
|
||||
@@ -51,17 +51,11 @@ abstract class question_base extends base {
|
||||
*/
|
||||
public function get_url() {
|
||||
$cat = $this->other['categoryid'] . ',' . $this->contextid;
|
||||
if ($this->courseid) {
|
||||
if ($this->contextlevel == CONTEXT_MODULE) {
|
||||
return new \moodle_url('/question/edit.php',
|
||||
['cmid' => $this->contextinstanceid, 'cat' => $cat, 'lastchanged' => $this->objectid]);
|
||||
}
|
||||
return new \moodle_url('/question/edit.php',
|
||||
['courseid' => $this->courseid, 'cat' => $cat, 'lastchanged' => $this->objectid]);
|
||||
}
|
||||
// Lets try viewing from the frontpage for contexts above course.
|
||||
return new \moodle_url('/question/edit.php',
|
||||
['courseid' => SITEID, 'edit' => $cat, 'lastchanged' => $this->objectid]);
|
||||
|
||||
return new \moodle_url(
|
||||
'/question/edit.php',
|
||||
['cmid' => $this->contextinstanceid, 'cat' => $cat, 'lastchanged' => $this->objectid]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -51,14 +51,8 @@ abstract class question_category_base extends base {
|
||||
*/
|
||||
public function get_url() {
|
||||
$cat = $this->objectid . ',' . $this->contextid;
|
||||
if ($this->courseid) {
|
||||
if ($this->contextlevel == CONTEXT_MODULE) {
|
||||
return new \moodle_url('/question/edit.php', ['cmid' => $this->contextinstanceid, 'cat' => $cat]);
|
||||
}
|
||||
return new \moodle_url('/question/edit.php', ['courseid' => $this->courseid, 'cat' => $cat]);
|
||||
}
|
||||
// Lets try viewing from the frontpage for contexts above course.
|
||||
return new \moodle_url('/question/edit.php', ['courseid' => SITEID, 'cat' => $cat, 'edit' => $this->objectid]);
|
||||
|
||||
return new \moodle_url('/question/edit.php', ['cmid' => $this->contextinstanceid, 'cat' => $cat]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -78,17 +78,10 @@ class question_moved extends question_base {
|
||||
*/
|
||||
public function get_url() {
|
||||
$cat = $this->other['newcategoryid'] . ',' . $this->contextid;
|
||||
if ($this->courseid) {
|
||||
if ($this->contextlevel == CONTEXT_MODULE) {
|
||||
return new \moodle_url('/question/edit.php',
|
||||
['cmid' => $this->contextinstanceid, 'cat' => $cat, 'lastchanged' => $this->objectid]);
|
||||
}
|
||||
return new \moodle_url('/question/edit.php',
|
||||
['courseid' => $this->courseid, 'cat' => $cat, 'lastchanged' => $this->objectid]);
|
||||
}
|
||||
// Lets try viewing from the frontpage for contexts above course.
|
||||
|
||||
return new \moodle_url('/question/edit.php',
|
||||
['courseid' => SITEID, 'cat' => $cat, 'lastchanged' => $this->objectid]);
|
||||
['cmid' => $this->contextinstanceid, 'cat' => $cat, 'lastchanged' => $this->objectid]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -77,14 +77,8 @@ class questions_exported extends question_base {
|
||||
*/
|
||||
public function get_url() {
|
||||
$cat = $this->other['categoryid'] . ',' . $this->contextid;
|
||||
if ($this->courseid) {
|
||||
if ($this->contextlevel == CONTEXT_MODULE) {
|
||||
return new \moodle_url('/question/edit.php', ['cmid' => $this->contextinstanceid, 'cat' => $cat]);
|
||||
}
|
||||
return new \moodle_url('/question/edit.php', ['courseid' => $this->courseid, 'cat' => $cat]);
|
||||
}
|
||||
return new \moodle_url('/question/edit.php',
|
||||
['courseid' => SITEID, 'cat' => $cat]);
|
||||
|
||||
return new \moodle_url('/question/edit.php', ['cmid' => $this->contextinstanceid, 'cat' => $cat]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -77,14 +77,8 @@ class questions_imported extends question_base {
|
||||
*/
|
||||
public function get_url() {
|
||||
$cat = $this->other['categoryid'] . ',' . $this->contextid;
|
||||
if ($this->courseid) {
|
||||
if ($this->contextlevel == CONTEXT_MODULE) {
|
||||
return new \moodle_url('/question/edit.php', ['cmid' => $this->contextinstanceid, 'cat' => $cat]);
|
||||
}
|
||||
return new \moodle_url('/question/edit.php', ['courseid' => $this->courseid, 'cat' => $cat]);
|
||||
}
|
||||
return new \moodle_url('/question/edit.php',
|
||||
['courseid' => SITEID, 'cat' => $cat]);
|
||||
|
||||
return new \moodle_url('/question/edit.php', ['cmid' => $this->contextinstanceid, 'cat' => $cat]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4889,12 +4889,6 @@ function remove_course_contents($courseid, $showfeedback = true, ?array $options
|
||||
echo $OUTPUT->notification($strdeleted.get_string('type_mod_plural', 'plugin'), 'notifysuccess');
|
||||
}
|
||||
|
||||
// Delete questions and question categories.
|
||||
question_delete_course($course);
|
||||
if ($showfeedback) {
|
||||
echo $OUTPUT->notification($strdeleted.get_string('questions', 'question'), 'notifysuccess');
|
||||
}
|
||||
|
||||
// Delete content bank contents.
|
||||
$cb = new \core_contentbank\contentbank();
|
||||
$cbdeleted = $cb->delete_contents($coursecontext);
|
||||
|
||||
+54
-171
@@ -438,57 +438,6 @@ function question_delete_context($contextid): array {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* All question categories and their questions are deleted for this course.
|
||||
*
|
||||
* @param stdClass $course an object representing the activity
|
||||
* @param bool $notused this argument is not used any more. Kept for backwards compatibility.
|
||||
* @return bool always true.
|
||||
*/
|
||||
function question_delete_course($course, $notused = false): bool {
|
||||
$coursecontext = context_course::instance($course->id);
|
||||
question_delete_context($coursecontext->id);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Category is about to be deleted,
|
||||
* 1/ All question categories and their questions are deleted for this course category.
|
||||
* 2/ All questions are moved to new category
|
||||
*
|
||||
* @param stdClass|core_course_category $category course category object
|
||||
* @param stdClass|core_course_category $newcategory empty means everything deleted, otherwise id of
|
||||
* category where content moved
|
||||
* @param bool $notused this argument is no longer used. Kept for backwards compatibility.
|
||||
* @return boolean
|
||||
*/
|
||||
function question_delete_course_category($category, $newcategory, $notused=false): bool {
|
||||
global $DB;
|
||||
|
||||
$context = context_coursecat::instance($category->id);
|
||||
if (empty($newcategory)) {
|
||||
question_delete_context($context->id);
|
||||
|
||||
} else {
|
||||
// Move question categories to the new context.
|
||||
if (!$newcontext = context_coursecat::instance($newcategory->id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only move question categories if there is any question category at all!
|
||||
if ($topcategory = question_get_top_category($context->id)) {
|
||||
$newtopcategory = question_get_top_category($newcontext->id, true);
|
||||
|
||||
question_move_category_to_context($topcategory->id, $context->id, $newcontext->id);
|
||||
$DB->set_field('question_categories', 'parent', $newtopcategory->id, ['parent' => $topcategory->id]);
|
||||
// Now delete the top category.
|
||||
$DB->delete_records('question_categories', ['id' => $topcategory->id]);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new category to save the questions in use.
|
||||
*
|
||||
@@ -502,6 +451,11 @@ function question_delete_course_category($category, $newcategory, $notused=false
|
||||
function question_save_from_deletion($questionids, $newcontextid, $oldplace, $newcategory = null) {
|
||||
global $DB;
|
||||
|
||||
$newcontext = context::instance_by_id($newcontextid);
|
||||
if ($newcontext->contextlevel !== CONTEXT_MODULE) {
|
||||
throw new moodle_exception("Invalid contextlevel: {$newcontext->contextlevel} for \$newcontextid {$newcontextid}");
|
||||
}
|
||||
|
||||
// Make a category in the parent context to move the questions to.
|
||||
if (is_null($newcategory)) {
|
||||
$newcategory = new stdClass();
|
||||
@@ -539,35 +493,17 @@ function question_delete_activity($cm, $notused = false): bool {
|
||||
* This function will handle moving all tag instances to a new context for a
|
||||
* given list of questions.
|
||||
*
|
||||
* Questions can be tagged in up to two contexts:
|
||||
* 1.) The context the question exists in.
|
||||
* 2.) The course context (if the question context is a higher context.
|
||||
* E.g. course category context or system context.
|
||||
*
|
||||
* This means a question that exists in a higher context (e.g. course cat or
|
||||
* system context) may have multiple groups of tags in any number of child
|
||||
* course contexts.
|
||||
*
|
||||
* Questions in the course category context can be move "down" a context level
|
||||
* into one of their child course contexts or activity contexts which affects the
|
||||
* availability of that question in other courses / activities.
|
||||
*
|
||||
* In this case it makes the questions no longer available in the other course or
|
||||
* activity contexts so we need to make sure that the tag instances in those other
|
||||
* contexts are removed.
|
||||
*
|
||||
* @param stdClass[] $questions The list of question being moved (must include
|
||||
* the id and contextid)
|
||||
* @param context $newcontext The Moodle context the questions are being moved to
|
||||
* @param context $newcontext The Moodle context the questions are being moved to, must be module context.
|
||||
*/
|
||||
function question_move_question_tags_to_new_context(array $questions, context $newcontext): void {
|
||||
// If the questions are moving to a new course/activity context then we need to
|
||||
// find any existing tag instances from any unavailable course contexts and
|
||||
// delete them because they will no longer be applicable (we don't support
|
||||
// tagging questions across courses).
|
||||
$instancestodelete = [];
|
||||
|
||||
if ($newcontext->contextlevel !== CONTEXT_MODULE) {
|
||||
debugging("Invalid contextlevel: {$newcontext->contextlevel}", DEBUG_DEVELOPER);
|
||||
}
|
||||
|
||||
$instancesfornewcontext = [];
|
||||
$newcontextparentids = $newcontext->get_parent_context_ids();
|
||||
$questionids = array_map(function($question) {
|
||||
return $question->id;
|
||||
}, $questions);
|
||||
@@ -580,7 +516,6 @@ function question_move_question_tags_to_new_context(array $questions, context $n
|
||||
$tagid = $tagobject->taginstanceid;
|
||||
$tagcontextid = $tagobject->taginstancecontextid;
|
||||
$istaginnewcontext = $tagcontextid == $newcontext->id;
|
||||
$istaginquestioncontext = $tagcontextid == $question->contextid;
|
||||
|
||||
if ($istaginnewcontext) {
|
||||
// This tag instance is already in the correct context so we can
|
||||
@@ -588,61 +523,10 @@ function question_move_question_tags_to_new_context(array $questions, context $n
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($istaginquestioncontext) {
|
||||
// This tag instance is in the question context so it needs to be
|
||||
// updated.
|
||||
$instancesfornewcontext[] = $tagid;
|
||||
continue;
|
||||
}
|
||||
|
||||
// These tag instances are in neither the new context nor the
|
||||
// question context so we need to determine what to do based on
|
||||
// the context they are in and the new question context.
|
||||
$tagcontext = context::instance_by_id($tagcontextid);
|
||||
$tagcoursecontext = $tagcontext->get_course_context(false);
|
||||
// The tag is in a course context if get_course_context() returns
|
||||
// itself.
|
||||
$istaginstancecontextcourse = !empty($tagcoursecontext)
|
||||
&& $tagcontext->id == $tagcoursecontext->id;
|
||||
|
||||
if ($istaginstancecontextcourse) {
|
||||
// If the tag instance is in a course context we need to add some
|
||||
// special handling.
|
||||
$tagcontextparentids = $tagcontext->get_parent_context_ids();
|
||||
$isnewcontextaparent = in_array($newcontext->id, $tagcontextparentids);
|
||||
$isnewcontextachild = in_array($tagcontext->id, $newcontextparentids);
|
||||
|
||||
if ($isnewcontextaparent) {
|
||||
// If the tag instance is a course context tag and the new
|
||||
// context is still a parent context to the tag context then
|
||||
// we can leave this tag where it is.
|
||||
continue;
|
||||
} else if ($isnewcontextachild) {
|
||||
// If the new context is a child context (e.g. activity) of this
|
||||
// tag instance then we should move all of this tag instance
|
||||
// down into the activity context along with the question.
|
||||
$instancesfornewcontext[] = $tagid;
|
||||
} else {
|
||||
// If the tag is in a course context that is no longer a parent
|
||||
// or child of the new context then this tag instance should be
|
||||
// removed.
|
||||
$instancestodelete[] = $tagid;
|
||||
}
|
||||
} else {
|
||||
// This is a catch all for any tag instances not in the question
|
||||
// context or a course context. These tag instances should be
|
||||
// updated to the new context id. This will clean up old invalid
|
||||
// data.
|
||||
$instancesfornewcontext[] = $tagid;
|
||||
}
|
||||
$instancesfornewcontext[] = $tagid;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($instancestodelete)) {
|
||||
// Delete any course context tags that may no longer be valid.
|
||||
core_tag_tag::delete_instances_by_id($instancestodelete);
|
||||
}
|
||||
|
||||
if (!empty($instancesfornewcontext)) {
|
||||
// Update the tag instances to the new context id.
|
||||
core_tag_tag::change_instances_context($instancesfornewcontext, $newcontext);
|
||||
@@ -807,6 +691,11 @@ function move_question_set_references(int $oldcategoryid, int $newcatgoryid,
|
||||
function question_move_category_to_context($categoryid, $oldcontextid, $newcontextid): void {
|
||||
global $DB;
|
||||
|
||||
$newcontext = context::instance_by_id($newcontextid);
|
||||
if ($newcontext->contextlevel !== CONTEXT_MODULE) {
|
||||
debugging("Invalid contextlevel: {$newcontext->contextlevel}, must use CONTEXT_MODULE", DEBUG_DEVELOPER);
|
||||
}
|
||||
|
||||
$questions = [];
|
||||
$sql = "SELECT q.id, q.qtype
|
||||
FROM {question} q
|
||||
@@ -826,7 +715,6 @@ function question_move_category_to_context($categoryid, $oldcontextid, $newconte
|
||||
];
|
||||
}
|
||||
|
||||
$newcontext = context::instance_by_id($newcontextid);
|
||||
question_move_question_tags_to_new_context($questions, $newcontext);
|
||||
|
||||
$subcatids = $DB->get_records_menu('question_categories', ['parent' => $categoryid], '', 'id,1');
|
||||
@@ -935,9 +823,14 @@ function question_load_questions($questionids, $extrafields = '', $join = '') {
|
||||
* @param object $question the question to tidy.
|
||||
* @param stdClass $category The question_categories record for the given $question.
|
||||
* @param \core_tag_tag[]|null $tagobjects The tags for the given $question.
|
||||
* @param stdClass[]|null $filtercourses The courses to filter the course tags by.
|
||||
* @param stdClass[]|null $filtercourses deprecated argument and should not be used
|
||||
*/
|
||||
function _tidy_question($question, $category, ?array $tagobjects = null, ?array $filtercourses = null): void {
|
||||
|
||||
if ($filtercourses !== null) {
|
||||
debugging("Filtercourses is a deprecated argument in " . __FUNCTION__, DEBUG_DEVELOPER);
|
||||
}
|
||||
|
||||
// Convert numeric fields to float. This prevents these being displayed as 1.0000000.
|
||||
$question->defaultmark += 0;
|
||||
$question->penalty += 0;
|
||||
@@ -953,8 +846,6 @@ function _tidy_question($question, $category, ?array $tagobjects = null, ?array
|
||||
if (!is_null($tagobjects)) {
|
||||
$categorycontext = context::instance_by_id($category->contextid);
|
||||
$sortedtagobjects = question_sort_tags($tagobjects, $categorycontext, $filtercourses);
|
||||
$question->coursetagobjects = $sortedtagobjects->coursetagobjects;
|
||||
$question->coursetags = $sortedtagobjects->coursetags;
|
||||
$question->tagobjects = $sortedtagobjects->tagobjects;
|
||||
$question->tags = $sortedtagobjects->tags;
|
||||
}
|
||||
@@ -978,12 +869,16 @@ function _tidy_question($question, $category, ?array $tagobjects = null, ?array
|
||||
* @param mixed $questions Either an array of question objects to be updated
|
||||
* or just a single question object
|
||||
* @param bool $loadtags load the question tags from the tags table. Optional, default false.
|
||||
* @param stdClass[] $filtercourses The courses to filter the course tags by.
|
||||
* @param stdClass[] $filtercourses deprecated argument and should not be used
|
||||
* @return bool Indicates success or failure.
|
||||
*/
|
||||
function get_question_options(&$questions, $loadtags = false, $filtercourses = null) {
|
||||
global $DB;
|
||||
|
||||
if ($filtercourses !== null) {
|
||||
debugging("Filtercourses is a deprecated argument in " . __FUNCTION__, DEBUG_DEVELOPER);
|
||||
}
|
||||
|
||||
$questionlist = is_array($questions) ? $questions : [$questions];
|
||||
$categoryids = [];
|
||||
$questionids = [];
|
||||
@@ -1037,55 +932,24 @@ function get_question_options(&$questions, $loadtags = false, $filtercourses = n
|
||||
*
|
||||
* @param \core_tag_tag[] $tagobjects The tags for the given $question.
|
||||
* @param stdClass $categorycontext The question categories context.
|
||||
* @param stdClass[]|null $filtercourses The courses to filter the course tags by.
|
||||
* @param stdClass[]|null $filtercourses deprecated argument and should not be used.
|
||||
* @return stdClass $sortedtagobjects Sorted tag objects.
|
||||
*/
|
||||
function question_sort_tags($tagobjects, $categorycontext, $filtercourses = null): stdClass {
|
||||
|
||||
// Questions can have two sets of tag instances. One set at the
|
||||
// course context level and another at the context the question
|
||||
// belongs to (e.g. course category, system etc).
|
||||
if ($filtercourses !== null) {
|
||||
debugging("Filtercourses is a deprecated argument in " . __FUNCTION__, DEBUG_DEVELOPER);
|
||||
}
|
||||
|
||||
$sortedtagobjects = new stdClass();
|
||||
$sortedtagobjects->coursetagobjects = [];
|
||||
$sortedtagobjects->coursetags = [];
|
||||
$sortedtagobjects->tagobjects = [];
|
||||
$sortedtagobjects->tags = [];
|
||||
$taginstanceidstonormalise = [];
|
||||
$filtercoursecontextids = [];
|
||||
$hasfiltercourses = !empty($filtercourses);
|
||||
|
||||
if ($hasfiltercourses) {
|
||||
// If we're being asked to filter the course tags by a set of courses
|
||||
// then get the context ids to filter below.
|
||||
$filtercoursecontextids = array_map(function($course) {
|
||||
$coursecontext = context_course::instance($course->id);
|
||||
return $coursecontext->id;
|
||||
}, $filtercourses);
|
||||
}
|
||||
|
||||
foreach ($tagobjects as $tagobject) {
|
||||
$tagcontextid = $tagobject->taginstancecontextid;
|
||||
$tagcontext = context::instance_by_id($tagcontextid);
|
||||
$tagcoursecontext = $tagcontext->get_course_context(false);
|
||||
// This is a course tag if the tag context is a course context which
|
||||
// doesn't match the question's context. Any tag in the question context
|
||||
// is not considered a course tag, it belongs to the question.
|
||||
$iscoursetag = $tagcoursecontext
|
||||
&& $tagcontext->id == $tagcoursecontext->id
|
||||
&& $tagcontext->id != $categorycontext->id;
|
||||
|
||||
if ($iscoursetag) {
|
||||
// Any tag instance in a course context level is considered a course tag.
|
||||
if (!$hasfiltercourses || in_array($tagcontextid, $filtercoursecontextids)) {
|
||||
// Add the tag to the list of course tags if we aren't being
|
||||
// asked to filter or if this tag is in the list of courses
|
||||
// we're being asked to filter by.
|
||||
$sortedtagobjects->coursetagobjects[] = $tagobject;
|
||||
$sortedtagobjects->coursetags[$tagobject->id] = $tagobject->get_display_name();
|
||||
}
|
||||
} else {
|
||||
// All non course context level tag instances or tags in the question
|
||||
// context belong to the context that the question was created in.
|
||||
// All tag instances belong to the context that the question was created in.
|
||||
$sortedtagobjects->tagobjects[] = $tagobject;
|
||||
$sortedtagobjects->tags[$tagobject->id] = $tagobject->get_display_name();
|
||||
|
||||
@@ -1100,7 +964,7 @@ function question_sort_tags($tagobjects, $categorycontext, $filtercourses = null
|
||||
// happen below.
|
||||
$tagobject->taginstancecontextid = $categorycontext->id;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!empty($taginstanceidstonormalise)) {
|
||||
@@ -1232,6 +1096,15 @@ function question_get_top_category($contextid, $create = false) {
|
||||
global $DB;
|
||||
$category = $DB->get_record('question_categories', ['contextid' => $contextid, 'parent' => 0]);
|
||||
|
||||
$context = context::instance_by_id($contextid);
|
||||
if ($context->contextlevel !== CONTEXT_MODULE) {
|
||||
debugging(
|
||||
"Invalid context level: {$context->contextlevel} for question_get_top_category, must be CONTEXT_MODULE",
|
||||
DEBUG_DEVELOPER
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$category && $create) {
|
||||
// We need to make one.
|
||||
$category = new stdClass();
|
||||
@@ -1485,6 +1358,15 @@ function question_edit_url($context) {
|
||||
if (!has_any_capability(question_get_question_capabilities(), $context)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($context->contextlevel !== CONTEXT_MODULE) {
|
||||
debugging(
|
||||
"Invalid contextlevel: {$context->contextlevel} provided for question_edit_url, must be CONTEXT_MODULE",
|
||||
DEBUG_DEVELOPER
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$baseurl = $CFG->wwwroot . '/question/edit.php?';
|
||||
$defaultcategory = question_get_default_category($context->id, true);
|
||||
if ($defaultcategory) {
|
||||
@@ -1503,6 +1385,7 @@ function question_edit_url($context) {
|
||||
return $baseurl . 'cmid=' . $context->instanceid;
|
||||
}
|
||||
|
||||
return $baseurl . 'cmid=' . $context->instanceid;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -79,7 +79,7 @@ Feature: Menu navigation has accurate checkmarks in topic course format
|
||||
Given I log in as "admin"
|
||||
And I am on "Course 1" course homepage
|
||||
And I update the href of the "//*//a/following-sibling::*//a[contains(text(), 'Filters')]" "xpath" link to "#"
|
||||
And I navigate to "Question bank" in current page administration
|
||||
And I navigate to "Question banks" in current page administration
|
||||
Then menu item "Filters" should not be active
|
||||
|
||||
@javascript
|
||||
|
||||
@@ -962,7 +962,7 @@ class secondary_test extends \advanced_testcase {
|
||||
],
|
||||
"Question bank should return nothing" => [
|
||||
'/question/edit.php',
|
||||
'courseid',
|
||||
'cmid',
|
||||
false
|
||||
],
|
||||
"Reports should return nothing" => [
|
||||
|
||||
+82
-965
File diff suppressed because it is too large
Load Diff
@@ -1836,6 +1836,13 @@ class structure {
|
||||
* @throws coding_exception If the context level is unsupported.
|
||||
*/
|
||||
private function get_used_category_description(stdClass $qcategory, bool $includesubcategories): string {
|
||||
|
||||
$context = \context::instance_by_id($qcategory->contextid);
|
||||
|
||||
if ($context->contextlevel != CONTEXT_MODULE) {
|
||||
throw new coding_exception('Unsupported context.');
|
||||
}
|
||||
|
||||
if ($qcategory->name === 'top') { // This is a "top" question category.
|
||||
if (!$includesubcategories) {
|
||||
// Question categories labeled as "top" cannot directly contain questions. If the subcategories that may
|
||||
@@ -1843,26 +1850,7 @@ class structure {
|
||||
// that informs the user about the issues associated with these types of generated random questions.
|
||||
return get_string('randomfaultynosubcat', 'mod_quiz');
|
||||
}
|
||||
|
||||
$context = \context::instance_by_id($qcategory->contextid);
|
||||
|
||||
switch ($context->contextlevel) {
|
||||
case CONTEXT_MODULE:
|
||||
return get_string('randommodulewithsubcat', 'mod_quiz');
|
||||
|
||||
case CONTEXT_COURSE:
|
||||
return get_string('randomcoursewithsubcat', 'mod_quiz');
|
||||
|
||||
case CONTEXT_COURSECAT:
|
||||
$contextname = shorten_text($context->get_context_name(false), 100);
|
||||
return get_string('randomcoursecatwithsubcat', 'mod_quiz', $contextname);
|
||||
|
||||
case CONTEXT_SYSTEM:
|
||||
return get_string('randomsystemwithsubcat', 'mod_quiz');
|
||||
|
||||
default:
|
||||
throw new coding_exception('Unsupported context.');
|
||||
}
|
||||
return get_string('randommodulewithsubcat', 'mod_quiz');
|
||||
}
|
||||
// Otherwise, return the description of the used standard question category, also indicating whether subcategories
|
||||
// are included.
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ require_once($CFG->dirroot . '/question/editlib.php');
|
||||
$mdlscrollto = optional_param('mdlscrollto', '', PARAM_INT);
|
||||
|
||||
list($thispageurl, $contexts, $cmid, $cm, $quiz, $pagevars) =
|
||||
question_edit_setup('editq', '/mod/quiz/edit.php', true);
|
||||
question_edit_setup('editq', '/mod/quiz/edit.php');
|
||||
|
||||
$PAGE->set_url($thispageurl);
|
||||
$PAGE->set_secondary_active_tab("mod_quiz_edit");
|
||||
|
||||
@@ -37,7 +37,7 @@ require_once($CFG->dirroot . '/mod/quiz/locallib.php');
|
||||
require_once($CFG->dirroot . '/question/editlib.php');
|
||||
|
||||
list($thispageurl, $contexts, $cmid, $cm, $quiz, $pagevars) =
|
||||
question_edit_setup('editq', '/mod/quiz/editgrading.php', true);
|
||||
question_edit_setup('editq', '/mod/quiz/editgrading.php');
|
||||
|
||||
$PAGE->set_url($thispageurl);
|
||||
$PAGE->set_secondary_active_tab('mod_quiz_edit');
|
||||
|
||||
@@ -5,3 +5,6 @@ attemptsdeleted,mod_quiz
|
||||
gradesdeleted,mod_quiz
|
||||
useroverridesdeleted,mod_quiz
|
||||
groupoverridesdeleted,mod_quiz
|
||||
randomcoursecatwithsubcat,mod_quiz
|
||||
randomcoursewithsubcat,mod_quiz
|
||||
randomsystemwithsubcat,mod_quiz
|
||||
|
||||
@@ -844,8 +844,7 @@ $string['quiztimer'] = 'Quiz Timer';
|
||||
$string['quizwillopen'] = 'This quiz will open {$a}';
|
||||
$string['random'] = 'Random question';
|
||||
$string['randomcatwithsubcat'] = '{$a} and subcategories';
|
||||
$string['randomcoursecatwithsubcat'] = 'Any category inside course category {$a}';
|
||||
$string['randomcoursewithsubcat'] = 'Any category in this course';
|
||||
|
||||
$string['randomcreate'] = 'Create random questions';
|
||||
$string['randomediting'] = 'Editing a random question';
|
||||
$string['randomfaultynosubcat'] = 'Faulty question';
|
||||
@@ -867,7 +866,6 @@ $string['randomquestiontags_help'] = 'You can restrict the selection criteria fu
|
||||
|
||||
The "random" questions will be selected from the questions that have all these tags.';
|
||||
$string['randomquestionusinganewcategory'] = 'Random question using a new category';
|
||||
$string['randomsystemwithsubcat'] = 'Any system-level category';
|
||||
$string['randomwithsubcat'] = 'Questions from this category and its subcategories.';
|
||||
$string['readytosend'] = 'You are about to send your whole quiz to be graded. Are you sure you want to continue?';
|
||||
$string['reattemptquiz'] = 'Re-attempt quiz';
|
||||
@@ -1141,3 +1139,8 @@ $string['attemptsdeleted'] = 'Quiz attempts deleted';
|
||||
$string['gradesdeleted'] = 'Quiz grades deleted';
|
||||
$string['useroverridesdeleted'] = 'User overrides deleted';
|
||||
$string['groupoverridesdeleted'] = 'Group overrides deleted';
|
||||
|
||||
// Deprecated since Moodle 5.0.
|
||||
$string['randomcoursecatwithsubcat'] = 'Any category inside course category {$a}';
|
||||
$string['randomcoursewithsubcat'] = 'Any category in this course';
|
||||
$string['randomsystemwithsubcat'] = 'Any system-level category';
|
||||
|
||||
@@ -20,12 +20,12 @@ Feature: Regrading quiz attempts using the Grades report
|
||||
| student1 | C1 | student |
|
||||
| student2 | C1 | student |
|
||||
| student3 | C1 | student |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Quiz for testing regrading | C1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name |
|
||||
| Test questions | truefalse | TF |
|
||||
|
||||
@@ -14,9 +14,16 @@ Feature: Attempt a quiz
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student | C1 | student |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | grade | navmethod |
|
||||
| quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 | 100 | free |
|
||||
| quiz | Quiz 2 | Quiz 2 description | C1 | quiz2 | 6 | free |
|
||||
| quiz | Quiz 3 | Quiz 3 description | C1 | quiz3 | 100 | free |
|
||||
| quiz | Quiz 4 | Quiz 4 description | C1 | quiz4 | 100 | sequential |
|
||||
| qbank | Qbank 1 | Question bank 1 | C1 | qbank1 | | |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | TF1 | First question |
|
||||
@@ -25,12 +32,6 @@ Feature: Attempt a quiz
|
||||
| Test questions | truefalse | TF4 | Fourth question |
|
||||
| Test questions | truefalse | TF5 | Fifth question |
|
||||
| Test questions | truefalse | TF6 | Sixth question |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | grade | navmethod |
|
||||
| quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 | 100 | free |
|
||||
| quiz | Quiz 2 | Quiz 2 description | C1 | quiz2 | 6 | free |
|
||||
| quiz | Quiz 3 | Quiz 3 description | C1 | quiz3 | 100 | free |
|
||||
| quiz | Quiz 4 | Quiz 4 description | C1 | quiz4 | 100 | sequential |
|
||||
And quiz "Quiz 1" contains the following questions:
|
||||
| question | page | maxmark |
|
||||
| TF1 | 1 | |
|
||||
|
||||
@@ -11,12 +11,15 @@ Feature: The various checks that may happen when an attept is started
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| qbank | Qbank 1 | Question bank 1 | C1 | qbank1 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student | C1 | student |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | qbank1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | TF1 | Text of the first question |
|
||||
|
||||
@@ -14,12 +14,12 @@ Feature: Attempt a quiz with multiple grades
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student | C1 | student |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course |
|
||||
| quiz | Quiz 1 | C1 |
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Quiz 1 | C1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
|
||||
@javascript
|
||||
Scenario: Navigation to, and display of, grading setup
|
||||
|
||||
@@ -12,13 +12,16 @@ Feature: Attempt a quiz where some questions require that the previous question
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| qbank | Qbank 1 | Question bank 1 | C1 | qbank1 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student | C1 | student |
|
||||
| teacher | C1 | editingteacher |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | qbank1 | Test questions |
|
||||
|
||||
@javascript
|
||||
Scenario Outline: A question that requires the previous one is initially blocked
|
||||
|
||||
@@ -16,9 +16,12 @@ Feature: Allow settings to show Max marks and Marks, Max marks only, or hide the
|
||||
| user | course | role |
|
||||
| teacher | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| qbank | Qbank 1 | Question bank 1 | C1 | qbank1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | qbank1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | TF1 | First question |
|
||||
|
||||
@@ -14,18 +14,18 @@ Feature: Attempt a quiz in a sequential mode
|
||||
| user | course | role |
|
||||
| student | C1 | student |
|
||||
| teacher | C1 | teacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | preferredbehaviour | navmethod |
|
||||
| quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 | immediatefeedback | sequential |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | TF1 | First question |
|
||||
| Test questions | truefalse | TF2 | Second question |
|
||||
| Test questions | truefalse | TF3 | Third question |
|
||||
| Test questions | truefalse | TF4 | Fourth question |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | preferredbehaviour | navmethod |
|
||||
| quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 | immediatefeedback | sequential |
|
||||
And quiz "Quiz 1" contains the following questions:
|
||||
| question | page | requireprevious |
|
||||
| TF1 | 1 | 1 |
|
||||
|
||||
@@ -155,7 +155,10 @@ class behat_mod_quiz extends behat_question_base {
|
||||
return new moodle_url('/question/edit.php', [
|
||||
'cmid' => $this->get_cm_by_quiz_name($identifier)->id,
|
||||
]);
|
||||
|
||||
case 'question categories':
|
||||
return new moodle_url('/question/bank/managecategories/category.php', [
|
||||
'cmid' => $this->get_cm_by_quiz_name($identifier)->id,
|
||||
]);
|
||||
|
||||
default:
|
||||
throw new Exception('Unrecognised quiz page type "' . $type . '."');
|
||||
|
||||
@@ -16,15 +16,15 @@ Feature: Set a quiz to be marked complete when the student uses all attempts all
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | First question | Answer the first question |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | idnumber | attempts | gradepass | completion | completionusegrade | completionpassgrade | completionattemptsexhausted |
|
||||
| quiz | Test quiz name | C1 | quiz1 | 2 | 5.00 | 2 | 1 | 1 | 1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | First question | Answer the first question |
|
||||
And quiz "Test quiz name" contains the following questions:
|
||||
| question | page |
|
||||
| First question | 1 |
|
||||
|
||||
@@ -16,15 +16,15 @@ Feature: Manually complete a quiz
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | First question | Answer the first question |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | idnumber | completion |
|
||||
| quiz | Test quiz name | C1 | quiz1 | 1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | First question | Answer the first question |
|
||||
And quiz "Test quiz name" contains the following questions:
|
||||
| question | page |
|
||||
| First question | 1 |
|
||||
|
||||
@@ -17,7 +17,9 @@ Feature: Edit quiz page - adding things
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| quiz | Quiz 1 | Quiz 1 for testing the Add menu | C1 | quiz1 |
|
||||
| qbank | Qbank 1 | Question bank 1 for testing the Add menu | C1 | qbank1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And I am on the "Quiz 1" "mod_quiz > Edit" page logged in as "teacher1"
|
||||
|
||||
@javascript
|
||||
@@ -100,21 +102,11 @@ Feature: Edit quiz page - adding things
|
||||
in various categories and add them to the question bank.
|
||||
|
||||
# Create a couple of sub categories.
|
||||
When I am on the "Course 1" "core_question > course question categories" page
|
||||
Then I should see "Add category"
|
||||
And I follow "Add category"
|
||||
Then I set the field "Parent category" to "Default for Bank 1"
|
||||
And I set the field "Name" to "Subcat 1"
|
||||
And I set the field "Category info" to "This is sub category 1"
|
||||
And I press "id_submitbutton"
|
||||
And I should see "Subcat 1"
|
||||
|
||||
And I follow "Add category"
|
||||
Then I set the field "Parent category" to "Default for C1"
|
||||
And I set the field "Name" to "Subcat 2"
|
||||
And I set the field "Category info" to "This is sub category 2"
|
||||
And I press "id_submitbutton"
|
||||
And I should see "Subcat 2"
|
||||
Given the following "question categories" exist:
|
||||
| contextlevel | reference | questioncategory | name |
|
||||
| Activity module | quiz1 | Test questions | Subcat 1 |
|
||||
| Activity module | quiz1 | Test questions | Subcat 2 |
|
||||
When I am on the "Quiz 1" "mod_quiz > question categories" page
|
||||
|
||||
And I select "Questions" from the "Question bank tertiary navigation" singleselect
|
||||
And I should see "Question bank"
|
||||
@@ -240,10 +232,7 @@ Feature: Edit quiz page - adding things
|
||||
|
||||
@accessibility @javascript
|
||||
Scenario: Check the accessibility of the quiz questions page
|
||||
Given the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
Given the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | First question | Answer the first question |
|
||||
| Test questions | truefalse | Other question | Answer the first question |
|
||||
|
||||
@@ -14,17 +14,17 @@ Feature: Edit quiz page - drag-and-drop
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Quiz 1 | C1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | Question A | This is question 01 |
|
||||
| Test questions | truefalse | Question B | This is question 02 |
|
||||
| Test questions | truefalse | Question C | This is question 03 |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Quiz 1 | C1 | quiz1 |
|
||||
And quiz "Quiz 1" contains the following questions:
|
||||
| question | page |
|
||||
| Question A | 1 |
|
||||
|
||||
@@ -14,18 +14,18 @@ Feature: Setup multiple grades for a quiz
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Quiz 1 | C1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | description | Info | Some information |
|
||||
| Test questions | truefalse | Question A | This is question 01 |
|
||||
| Test questions | truefalse | Question B | This is question 02 |
|
||||
| Test questions | truefalse | Question C | This is question 03 |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course |
|
||||
| quiz | Quiz 1 | C1 |
|
||||
|
||||
@javascript
|
||||
Scenario: Navigation to, and display of, grading setup
|
||||
|
||||
@@ -15,13 +15,14 @@ Feature: Editing question numbering of the existing questions already in a quiz
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| quiz | Quiz 1 | Quiz 1 for testing | C1 | quiz1 |
|
||||
| quiz | Quiz 2 | Quiz 2 for testing | C1 | quiz2 |
|
||||
| activity | name | intro | course | idnumber |
|
||||
| quiz | Quiz 1 | Quiz 1 for testing | C1 | quiz1 |
|
||||
| quiz | Quiz 2 | Quiz 2 for testing | C1 | quiz2 |
|
||||
| qbank | Qbank 1 | Qbank for testing | C1 | qbank1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Questions Category 1|
|
||||
| Course | C1 | Questions Category 2|
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | qbank1 | Questions Category 1|
|
||||
| Activity module | qbank1 | Questions Category 2|
|
||||
Given the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Questions Category 1 | description | Description | This is decription ... |
|
||||
|
||||
@@ -14,12 +14,12 @@ Feature: Edit quiz page - remove multiple questions
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Quiz 1 | C1 | quiz1 |
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Quiz 1 | C1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And I log in as "teacher1"
|
||||
|
||||
@javascript
|
||||
|
||||
@@ -14,12 +14,12 @@ Feature: Edit quiz page - remove questions
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Quiz 1 | C1 | quiz1 |
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Quiz 1 | C1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And I log in as "teacher1"
|
||||
|
||||
@javascript
|
||||
|
||||
@@ -14,9 +14,12 @@ Feature: Edit quizzes where some questions require the previous one to have been
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | idnumber |
|
||||
| qbank | Qbank 1 | C1 | qbank1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | qbank1 | Test questions |
|
||||
And I log in as "teacher1"
|
||||
|
||||
@javascript
|
||||
|
||||
@@ -15,9 +15,12 @@ Feature: Edit quiz page - section headings
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | idnumber |
|
||||
| qbank | Qbank 1 | C1 | qbank1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | qbank1 | Test questions |
|
||||
And I log in as "teacher1"
|
||||
|
||||
@javascript
|
||||
|
||||
@@ -15,12 +15,12 @@ Feature: Edit quiz marks with no attempts
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | idnumber | grade | decimalpoints | questiondecimalpoints |
|
||||
| quiz | Quiz 1 | C1 | quiz1 | 20 | 2 | -1 |
|
||||
| activity | name | course | idnumber | grade | decimalpoints | questiondecimalpoints |
|
||||
| quiz | Quiz 1 | C1 | quiz1 | 20 | 2 | -1 |
|
||||
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | First question | Answer me |
|
||||
|
||||
@@ -31,13 +31,6 @@ Feature: Switching question bank when adding questions to a quiz
|
||||
| Activity module | qbank3 | Test questions 3 |
|
||||
| Activity module | qbank4 | Test questions 4 |
|
||||
| Activity module | quiz1 | Test questions 5 |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | user | questiontext | idnumber |
|
||||
| Test questions 1 | essay | question 01 name | admin | Question 01 text | qidnum1 |
|
||||
| Test questions 2 | essay | question 02 name | teacher1 | Question 02 text | qidnum2 |
|
||||
| Test questions 3 | essay | question 03 name | teacher1 | Question 03 text | qidnum3 |
|
||||
| Test questions 4 | essay | question 04 name | admin | Question 04 text | qidnum4 |
|
||||
| Test questions 5 | essay | question 05 name | teacher1 | Question 05 text | qidnum5 |
|
||||
And I log in as "teacher1"
|
||||
And I am on the "Quiz 1" "mod_quiz > Edit" page
|
||||
|
||||
|
||||
@@ -16,15 +16,15 @@ Feature: Teachers see correct answers when overriding marks
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Quiz 1 | C1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext | generalfeedback |
|
||||
| Test questions | shortanswer | Kermit | What kind of animal is Kermit? | |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Quiz 1 | C1 | quiz1 |
|
||||
And quiz "Quiz 1" contains the following questions:
|
||||
| question | page |
|
||||
| Kermit | 1 |
|
||||
|
||||
@@ -16,14 +16,6 @@ Feature: Flag quiz questions
|
||||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
| teacher1 | C1 | teacher |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | TF1 | First question |
|
||||
| Test questions | truefalse | TF2 | Second question |
|
||||
| Test questions | truefalse | TF3 | Third question |
|
||||
And the following "activity" exists:
|
||||
| activity | quiz |
|
||||
| name | Quiz 1 |
|
||||
@@ -36,6 +28,15 @@ Feature: Flag quiz questions
|
||||
| generalfeedbackimmediately | 1 |
|
||||
| rightanswerimmediately | 1 |
|
||||
| overallfeedbackimmediately | 1 |
|
||||
| idnumber | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | TF1 | First question |
|
||||
| Test questions | truefalse | TF2 | Second question |
|
||||
| Test questions | truefalse | TF3 | Third question |
|
||||
And quiz "Quiz 1" contains the following questions:
|
||||
| question | page |
|
||||
| TF1 | 1 |
|
||||
|
||||
@@ -42,9 +42,10 @@ Feature: Viewing results by group
|
||||
| activity | name | intro | course | idnumber | groupmode |
|
||||
| quiz | Separate quiz | quiz with separate groups | C1 | quiz1 | 1 |
|
||||
| quiz | Visible quiz | quiz with visible groups | C1 | quiz2 | 2 |
|
||||
| qbank | Qbank 1 | | C1 | qbank1 | |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | qbank1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | TF1 | First question |
|
||||
|
||||
@@ -14,9 +14,12 @@ Feature: Display of information before starting a quiz
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student | C1 | student |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | idnumber |
|
||||
| qbank | Qbank 1 | C1 | qbank1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | qbank1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | TF1 | Text of the first question |
|
||||
|
||||
@@ -16,15 +16,16 @@ Feature: Teachers can override the grade for any question
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | grade |
|
||||
| quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 | 20 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext | defaultmark |
|
||||
| Test questions | essay | TF1 | First question | 20 |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | grade |
|
||||
| quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 | 20 |
|
||||
|
||||
And quiz "Quiz 1" contains the following questions:
|
||||
| question | page |
|
||||
| TF1 | 1 |
|
||||
|
||||
@@ -14,12 +14,12 @@ Feature: Preview a quiz as a teacher
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher | C1 | editingteacher |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 |
|
||||
| activity | name | intro | course | idnumber |
|
||||
| quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | TF1 | First question |
|
||||
|
||||
@@ -16,9 +16,12 @@ Feature: Quiz availability can be set
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | idnumber |
|
||||
| qbank | Qbank 1 | C1 | qbank1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | qbank1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | TF1 | First question |
|
||||
|
||||
@@ -16,17 +16,17 @@ Feature: Set a quiz with certainty-based marking
|
||||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Quiz 1 | C1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | TF1 | First question |
|
||||
| Test questions | truefalse | TF2 | Second question |
|
||||
| Test questions | truefalse | TF3 | Third question |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course |
|
||||
| quiz | Quiz 1 | C1 |
|
||||
And quiz "Quiz 1" contains the following questions:
|
||||
| question | page |
|
||||
| TF1 | 1 |
|
||||
|
||||
@@ -16,12 +16,6 @@ Feature: View activity completion in the quiz activity
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | First question | Answer the first question |
|
||||
And the following "activity" exists:
|
||||
| activity | quiz |
|
||||
| course | C1 |
|
||||
@@ -37,6 +31,12 @@ Feature: View activity completion in the quiz activity
|
||||
| completionattemptsexhausted | 1 |
|
||||
| completionminattemptsenabled | 1 |
|
||||
| completionminattempts | 1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | First question | Answer the first question |
|
||||
And quiz "Test quiz name" contains the following questions:
|
||||
| question | page |
|
||||
| First question | 1 |
|
||||
|
||||
@@ -17,12 +17,6 @@ Feature: Ensure saving a quiz does not modify the completion settings.
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | First question | Answer the first question |
|
||||
And the following "activity" exists:
|
||||
| activity | quiz |
|
||||
| course | C1 |
|
||||
@@ -36,6 +30,12 @@ Feature: Ensure saving a quiz does not modify the completion settings.
|
||||
| completionusegrade | 1 |
|
||||
| completionpassgrade | 1 |
|
||||
| completionattemptsexhausted | 1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | First question | Answer the first question |
|
||||
And quiz "Test quiz" contains the following questions:
|
||||
| question | page |
|
||||
| First question | 1 |
|
||||
|
||||
@@ -16,13 +16,6 @@ Feature: Activity completion in the quiz activity with unlocked and re-grading.
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext | defaultmark |
|
||||
| Test questions | truefalse | First question | Answer the first question | 8 |
|
||||
| Test questions | truefalse | Second question | Answer the second question | 2 |
|
||||
And the following "activity" exists:
|
||||
| activity | quiz |
|
||||
| course | C1 |
|
||||
@@ -35,6 +28,13 @@ Feature: Activity completion in the quiz activity with unlocked and re-grading.
|
||||
| completion | 2 |
|
||||
| completionusegrade | 1 |
|
||||
| completionpassgrade | 1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext | defaultmark |
|
||||
| Test questions | truefalse | First question | Answer the first question | 8 |
|
||||
| Test questions | truefalse | Second question | Answer the second question | 2 |
|
||||
And quiz "Test quiz name" contains the following questions:
|
||||
| question | page |
|
||||
| First question | 1 |
|
||||
|
||||
@@ -15,9 +15,12 @@ Feature: Enable deferred or immediate feedback for quiz
|
||||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | idnumber |
|
||||
| qbank | Qbank 1 | C1 | qbank1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | qbank1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | TF1 | First question |
|
||||
|
||||
@@ -16,16 +16,16 @@ Feature: Set a quiz to be interactive with multiple tries
|
||||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | preferredbehaviour | specificfeedbackduring | idnumber |
|
||||
| quiz | Quiz 1 | C1 | interactive | 1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext | template | hint1 | hint2 | shuffleanswers |
|
||||
| Test questions | multichoice | MC1 | First question | one_of_four | Hint 1 | Hint 2 | 0 |
|
||||
| Test questions | multichoice | MC2 | Second question | one_of_four | Hint 1 | Hint 2 | 0 |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | preferredbehaviour | specificfeedbackduring |
|
||||
| quiz | Quiz 1 | C1 | interactive | 1 |
|
||||
And quiz "Quiz 1" contains the following questions:
|
||||
| question | page |
|
||||
| MC1 | 1 |
|
||||
|
||||
@@ -14,12 +14,12 @@ Feature: Quiz question versioning
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher | C1 | editingteacher |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Quiz 1 | C1 | quiz1 |
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Quiz 1 | C1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | First question | Answer the first question |
|
||||
|
||||
@@ -20,15 +20,15 @@ Feature: Quiz reset
|
||||
| name | course | idnumber |
|
||||
| Group 1 | C1 | G1 |
|
||||
| Group 2 | C1 | G2 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | TF1 | First question |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| quiz | Test quiz name | Test quiz description | C1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | TF1 | First question |
|
||||
And quiz "Test quiz name" contains the following questions:
|
||||
| question | page |
|
||||
| TF1 | 1 |
|
||||
|
||||
@@ -16,14 +16,15 @@ Feature: Moving a question to another category should not affect random question
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| quiz | Quiz 1 | Quiz 1 for testing the Add random question form | C1 | quiz1 |
|
||||
| activity | name | intro | course | idnumber |
|
||||
| quiz | Quiz 1 | Quiz 1 for testing the Add random question form | C1 | quiz1 |
|
||||
| qbank | Qbank 1 | Question bank 1 | C1 | qbank1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | questioncategory | name |
|
||||
| Course | C1 | Top | top |
|
||||
| Course | C1 | top | Default for C1 |
|
||||
| Course | C1 | Default for C1 | Subcategory |
|
||||
| Course | C1 | top | Used category |
|
||||
| contextlevel | reference | questioncategory | name |
|
||||
| Activity module | qbank1 | Top | top |
|
||||
| Activity module | qbank1 | top | Default for Qbank 1 |
|
||||
| Activity module | qbank1 | Default for Qbank 1 | Subcategory |
|
||||
| Activity module | qbank1 | top | Used category |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Used category | essay | Test question to be moved | Write about whatever you want |
|
||||
@@ -33,21 +34,27 @@ Feature: Moving a question to another category should not affect random question
|
||||
Given I am on the "Quiz 1" "mod_quiz > Edit" page logged in as "teacher1"
|
||||
When I open the "last" add to quiz menu
|
||||
And I follow "a random question"
|
||||
And I click on "Switch bank" "button"
|
||||
And I click on "Qbank 1" "link" in the "Select question bank" "dialogue"
|
||||
And I apply question bank filter "Category" with value "Used category"
|
||||
And I press "Add random question"
|
||||
And I should see "Random (Used category) based on filter condition" on quiz page "1"
|
||||
And I click on "Configure question" "link" in the "Random (Used category) based on filter condition" "list_item"
|
||||
And I should see "Used category"
|
||||
And I am on "Course 1" course homepage
|
||||
And I navigate to "Question bank" in current page administration
|
||||
And I navigate to "Question banks" in current page administration
|
||||
And I click on "Qbank 1" "link"
|
||||
And I apply question bank filter "Category" with value "Used category"
|
||||
And I click on "Test question to be moved" "checkbox" in the "Test question to be moved" "table_row"
|
||||
And I click on "With selected" "button"
|
||||
And I click on question bulk action "move"
|
||||
And I set the field "Question category" to "Subcategory"
|
||||
And I press "Move to"
|
||||
Then I should see "Test question to be moved"
|
||||
And I should see "Subcategory (1)"
|
||||
And I open the autocomplete suggestions list in the ".search-categories" "css_element"
|
||||
And I click on "Subcategory" item in the autocomplete list
|
||||
And I click on "Move questions" "button"
|
||||
And I should see "Are you sure you want to move these questions?"
|
||||
And I click on "Confirm" "button"
|
||||
And I wait until the page is ready
|
||||
Then I should see "Subcategory (1)"
|
||||
And I am on the "Quiz 1" "mod_quiz > Edit" page
|
||||
And I should see "Random (Used category) based on filter condition" on quiz page "1"
|
||||
And I click on "Configure question" "link" in the "Random (Used category) based on filter condition" "list_item"
|
||||
@@ -58,10 +65,12 @@ Feature: Moving a question to another category should not affect random question
|
||||
Given I am on the "Quiz 1" "mod_quiz > Edit" page logged in as "teacher1"
|
||||
When I open the "last" add to quiz menu
|
||||
And I follow "a random question"
|
||||
Then I click on "Switch bank" "button"
|
||||
And I click on "Qbank 1" "link" in the "Select question bank" "dialogue"
|
||||
And I apply question bank filter "Category" with value "Used category"
|
||||
And I press "Add random question"
|
||||
And I should see "Random (Used category) based on filter condition" on quiz page "1"
|
||||
And I am on the "Course 1" "core_question > course question categories" page
|
||||
And I am on the "Qbank 1" "core_question > question categories" page
|
||||
And I open the action menu in "Used category" "list_item"
|
||||
And I choose "Edit" in the open action menu
|
||||
And I set the following fields to these values:
|
||||
|
||||
@@ -18,16 +18,16 @@ Feature: Several attempts in a quiz
|
||||
| student1 | C1 | student |
|
||||
| student2 | C1 | student |
|
||||
| teacher | C1 | teacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | preferredbehaviour | navmethod |
|
||||
| quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 | immediatefeedback | free |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | TF1 | First question |
|
||||
| Test questions | truefalse | TF2 | Second question |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | preferredbehaviour | navmethod |
|
||||
| quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 | immediatefeedback | free |
|
||||
And quiz "Quiz 1" contains the following questions:
|
||||
| question | page | requireprevious |
|
||||
| TF1 | 1 | 1 |
|
||||
|
||||
@@ -125,11 +125,12 @@ Feature: Settings form fields disabled if not required
|
||||
@javascript
|
||||
Scenario: If there are quiz attempts, there is not option to repaginate.
|
||||
Given the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 |
|
||||
| activity | name | intro | course | idnumber |
|
||||
| quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 |
|
||||
| qbank | Qbank 1 | Qbank for testing | C1 | qbank1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | qbank1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | TF1 | First question |
|
||||
|
||||
@@ -151,19 +151,20 @@ class quiz_question_restore_test extends \advanced_testcase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a duplicate does not duplicate questions in course question bank.
|
||||
* Test if a duplicate does not duplicate questions from a shared question bank.
|
||||
*
|
||||
* @covers ::duplicate_module
|
||||
*/
|
||||
public function test_quiz_duplicate_does_not_duplicate_course_question_bank_questions(): void {
|
||||
public function test_quiz_duplicate_does_not_duplicate_questions_from_shared_banks(): void {
|
||||
$this->resetAfterTest();
|
||||
$quiz = $this->create_test_quiz($this->course);
|
||||
// Test for questions from a different context.
|
||||
$context = \context_course::instance($this->course->id);
|
||||
$qbank = self::getDataGenerator()->create_module('qbank', ['course' => $this->course->id]);
|
||||
// Test for questions from a qbank context.
|
||||
$context = \context_module::instance($qbank->cmid);
|
||||
$questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
$this->add_two_regular_questions($questiongenerator, $quiz, ['contextid' => $context->id]);
|
||||
$this->add_one_random_question($questiongenerator, $quiz, ['contextid' => $context->id]);
|
||||
// Count the questions in course context.
|
||||
// Count the questions in qbank context.
|
||||
$this->assertEquals(7, $this->question_count($context->id));
|
||||
$newquiz = $this->duplicate_quiz($this->course, $quiz);
|
||||
$this->assertEquals(7, $this->question_count($context->id));
|
||||
|
||||
@@ -184,7 +184,7 @@ class column_manager extends column_manager_base {
|
||||
$contexts,
|
||||
new moodle_url('/question/bank/columnsortorder/sortcolumns.php'),
|
||||
$course,
|
||||
null,
|
||||
$cm,
|
||||
$params
|
||||
);
|
||||
return $questionbank;
|
||||
|
||||
@@ -137,7 +137,7 @@ Feature: Set question bank column order and size
|
||||
And I click on "Disable" "link" in the "Question statistics" "table_row"
|
||||
And I click on "Enable" "link" in the "Question statistics" "table_row"
|
||||
And I click on "Disable" "link" in the "Question statistics" "table_row"
|
||||
And I am on the "Course 1" "core_question > course question bank" page
|
||||
And I am on the "Test quiz Q001" "mod_quiz > question bank" page
|
||||
Then I should see "Question bank"
|
||||
And "Create a new question" "button" should exist
|
||||
# Really, we are just checking the question bank displayed without errors.
|
||||
|
||||
@@ -48,10 +48,12 @@ class column_manager_test extends advanced_testcase {
|
||||
protected static function get_question_bank(): view {
|
||||
$course = self::getDataGenerator()->create_course();
|
||||
$qbank = self::getDataGenerator()->create_module('qbank', ['course' => $course->id]);
|
||||
$cm = get_coursemodule_from_id('qbank', $qbank->cmid);
|
||||
$questionbank = new view(
|
||||
new question_edit_contexts(\context_module::instance($qbank->cmid)),
|
||||
new moodle_url('/'),
|
||||
$course
|
||||
$course,
|
||||
$cm
|
||||
);
|
||||
return $questionbank;
|
||||
}
|
||||
|
||||
@@ -74,7 +74,8 @@ class backup_test extends \advanced_testcase {
|
||||
// Question initial set up.
|
||||
$this->category = $this->getDataGenerator()->create_category();
|
||||
$this->course = $this->getDataGenerator()->create_course(['category' => $this->category->id]);
|
||||
$context = \context_coursecat::instance($this->category->id);
|
||||
$qbank = self::getDataGenerator()->create_module('qbank', ['course' => $this->course->id]);
|
||||
$context = \context_module::instance($qbank->cmid);
|
||||
$this->qgen = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
$qcat = $this->qgen->create_question_category(['contextid' => $context->id]);
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ Feature: A Teacher can comment in a question
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Test quiz | C1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | First question | Answer the first question |
|
||||
|
||||
@@ -10,8 +10,8 @@ Feature: Use the qbank plugin manager page for comment
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Test quiz | C1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | First question | Answer the first question |
|
||||
|
||||
@@ -84,7 +84,8 @@ class lib_test extends \advanced_testcase {
|
||||
$category = $this->getDataGenerator()->create_category();
|
||||
$course = $this->getDataGenerator()->create_course(['category' => $category->id]);
|
||||
$qgen = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
$context = \context_coursecat::instance($category->id);
|
||||
$qbank = self::getDataGenerator()->create_module('qbank', ['course' => $course->id]);
|
||||
$context = \context_module::instance($qbank->cmid);
|
||||
$qcat = $qgen->create_question_category(['contextid' => $context->id]);
|
||||
$question = $qgen->create_question('shortanswer', null, ['category' => $qcat->id, 'idnumber' => 'q1']);
|
||||
|
||||
@@ -111,8 +112,9 @@ class lib_test extends \advanced_testcase {
|
||||
// Make a test question.
|
||||
$category = $this->getDataGenerator()->create_category();
|
||||
$course = $this->getDataGenerator()->create_course(['category' => $category->id]);
|
||||
$qbank = self::getDataGenerator()->create_module('qbank', ['course' => $course->id]);
|
||||
$context = \context_module::instance($qbank->cmid);
|
||||
$qgen = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
$context = \context_coursecat::instance($category->id);
|
||||
$qcat = $qgen->create_question_category(['contextid' => $context->id]);
|
||||
$question = $qgen->create_question('shortanswer', null, ['category' => $qcat->id, 'idnumber' => 'q1']);
|
||||
$args = [
|
||||
|
||||
@@ -91,7 +91,8 @@ class customfield_test extends \advanced_testcase {
|
||||
// Question initial set up.
|
||||
$this->category = $this->getDataGenerator()->create_category();
|
||||
$this->course = $this->getDataGenerator()->create_course(['category' => $this->category->id]);
|
||||
$context = \context_coursecat::instance($this->category->id);
|
||||
$qbank = self::getDataGenerator()->create_module('qbank', ['course' => $this->course->id]);
|
||||
$context = \context_module::instance($qbank->cmid);
|
||||
$this->qgen = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
$qcat = $this->qgen->create_question_category(['contextid' => $context->id]);
|
||||
|
||||
|
||||
@@ -33,9 +33,10 @@ class question_handler_test extends \advanced_testcase {
|
||||
* @throws coding_exception
|
||||
*/
|
||||
protected function setup_question(): int {
|
||||
$category = $this->getDataGenerator()->create_category();
|
||||
$course = self::getDataGenerator()->create_course();
|
||||
$qbank = self::getDataGenerator()->create_module('qbank', ['course' => $course->id]);
|
||||
$questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
$context = \context_coursecat::instance($category->id);
|
||||
$context = \context_module::instance($qbank->cmid);
|
||||
$questioncategory = $questiongenerator->create_question_category(['contextid' => $context->id]);
|
||||
$questiondata = ['category' => $questioncategory->id, 'idnumber' => 'q1'];
|
||||
$question = $questiongenerator->create_question('shortanswer', null, $questiondata);
|
||||
|
||||
@@ -64,12 +64,8 @@ class delete_action extends question_action_base {
|
||||
$this->strdelete = get_string('delete');
|
||||
$this->strrestore = get_string('restore');
|
||||
$this->deletequestionurl = new \moodle_url('/question/bank/deletequestion/delete.php');
|
||||
if (!empty($this->qbank->cm->id)) {
|
||||
$this->returnparams['cmid'] = $this->qbank->cm->id;
|
||||
}
|
||||
if (!empty($this->qbank->course->id)) {
|
||||
$this->returnparams['courseid'] = $this->qbank->course->id;
|
||||
}
|
||||
$this->returnparams['cmid'] = $this->qbank->cm->id;
|
||||
|
||||
if (!empty($this->qbank->returnurl)) {
|
||||
$this->returnparams['returnurl'] = $this->qbank->returnurl;
|
||||
}
|
||||
|
||||
@@ -31,8 +31,7 @@ global $DB, $OUTPUT, $PAGE, $COURSE;
|
||||
|
||||
$deleteselected = optional_param('deleteselected', false, PARAM_BOOL);
|
||||
$returnurl = optional_param('returnurl', 0, PARAM_LOCALURL);
|
||||
$cmid = optional_param('cmid', 0, PARAM_INT);
|
||||
$courseid = optional_param('courseid', 0, PARAM_INT);
|
||||
$cmid = required_param('cmid', PARAM_INT);
|
||||
$deleteall = optional_param('deleteall', false, PARAM_BOOL);
|
||||
|
||||
if ($returnurl) {
|
||||
@@ -41,16 +40,9 @@ if ($returnurl) {
|
||||
|
||||
\core_question\local\bank\helper::require_plugin_enabled('qbank_deletequestion');
|
||||
|
||||
if ($cmid) {
|
||||
list($module, $cm) = get_module_from_cmid($cmid);
|
||||
require_login($cm->course, false, $cm);
|
||||
$thiscontext = context_module::instance($cmid);
|
||||
} else if ($courseid) {
|
||||
require_login($courseid, false);
|
||||
$thiscontext = context_course::instance($courseid);
|
||||
} else {
|
||||
throw new moodle_exception('missingcourseorcmid', 'question');
|
||||
}
|
||||
[$module, $cm] = get_module_from_cmid($cmid);
|
||||
require_login($cm->course, false, $cm);
|
||||
$thiscontext = context_module::instance($cmid);
|
||||
|
||||
$contexts = new core_question\local\bank\question_edit_contexts($thiscontext);
|
||||
$url = new moodle_url('/question/bank/deletequestion/delete.php');
|
||||
@@ -115,7 +107,6 @@ if ($deleteselected) {
|
||||
'sesskey' => sesskey(),
|
||||
'returnurl' => $returnurl->out_as_local_url(false),
|
||||
'cmid' => $cmid,
|
||||
'courseid' => $courseid,
|
||||
],
|
||||
);
|
||||
$continue = new \single_button($deleteurl, get_string('delete'), 'post');
|
||||
|
||||
@@ -10,8 +10,8 @@ Feature: Use the qbank plugin manager page for deletequestion
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Test quiz | C1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | First question | Answer the first question |
|
||||
@@ -58,6 +58,7 @@ Feature: Use the qbank plugin manager page for deletequestion
|
||||
@javascript
|
||||
Scenario: I should be able to delete a question when filtered using tags
|
||||
Given I am on the "First question" "core_question > edit" page logged in as "admin"
|
||||
And I change window size to "large"
|
||||
And I set the following fields to these values:
|
||||
| Tags | foo |
|
||||
And I click on "Save changes" "button"
|
||||
|
||||
@@ -29,8 +29,7 @@ use qbank_editquestion\editquestion_helper;
|
||||
|
||||
// Read URL parameters.
|
||||
$categoryid = required_param('category', PARAM_INT);
|
||||
$cmid = optional_param('cmid', 0, PARAM_INT);
|
||||
$courseid = optional_param('courseid', 0, PARAM_INT);
|
||||
$cmid = required_param('cmid', PARAM_INT);
|
||||
$returnurl = optional_param('returnurl', 0, PARAM_LOCALURL);
|
||||
$appendqnumstring = optional_param('appendqnumstring', '', PARAM_ALPHA);
|
||||
$validationerror = optional_param('validationerror', false, PARAM_BOOL);
|
||||
@@ -45,20 +44,10 @@ if (!$category = $DB->get_record('question_categories', array('id' => $categoryi
|
||||
throw new moodle_exception('categorydoesnotexist', 'question', $returnurl);
|
||||
}
|
||||
|
||||
if ($cmid) {
|
||||
list($module, $cm) = get_module_from_cmid($cmid);
|
||||
require_login($cm->course, false, $cm);
|
||||
$thiscontext = context_module::instance($cmid);
|
||||
$hiddenparams['cmid'] = $cmid;
|
||||
} else if ($courseid) {
|
||||
require_login($courseid, false);
|
||||
$thiscontext = context_course::instance($courseid);
|
||||
$module = null;
|
||||
$cm = null;
|
||||
$hiddenparams['courseid'] = $courseid;
|
||||
} else {
|
||||
throw new moodle_exception('missingcourseorcmid', 'question');
|
||||
}
|
||||
list($module, $cm) = get_module_from_cmid($cmid);
|
||||
require_login($cm->course, false, $cm);
|
||||
$thiscontext = context_module::instance($cmid);
|
||||
$hiddenparams['cmid'] = $cmid;
|
||||
|
||||
// Check permissions.
|
||||
$categorycontext = context::instance_by_id($category->contextid);
|
||||
@@ -73,11 +62,9 @@ if (!empty($appendqnumstring)) {
|
||||
}
|
||||
|
||||
$PAGE->set_url('/question/bank/editquestion/addquestion.php', $hiddenparams);
|
||||
if ($cmid) {
|
||||
$questionbankurl = new moodle_url('/question/edit.php', array('cmid' => $cmid));
|
||||
} else {
|
||||
$questionbankurl = new moodle_url('/question/edit.php', array('courseid' => $courseid));
|
||||
}
|
||||
|
||||
$questionbankurl = new moodle_url('/question/edit.php', ['cmid' => $cmid]);
|
||||
|
||||
navigation_node::override_active_url($questionbankurl);
|
||||
|
||||
$chooseqtype = get_string('chooseqtypetoadd', 'question');
|
||||
|
||||
@@ -50,11 +50,7 @@ class copy_action extends question_action_base {
|
||||
$this->strcopy = get_string('duplicate');
|
||||
$this->duplicatequestionurl = new \moodle_url('/question/bank/editquestion/question.php',
|
||||
array('returnurl' => $this->qbank->returnurl));
|
||||
if ($this->qbank->cm !== null) {
|
||||
$this->duplicatequestionurl->param('cmid', $this->qbank->cm->id);
|
||||
} else {
|
||||
$this->duplicatequestionurl->param('courseid', $this->qbank->course->id);
|
||||
}
|
||||
$this->duplicatequestionurl->param('cmid', $this->qbank->cm->id);
|
||||
}
|
||||
|
||||
public function get_menu_position(): int {
|
||||
|
||||
@@ -60,11 +60,7 @@ class edit_action extends question_action_base {
|
||||
$this->strview = get_string('view');
|
||||
$this->editquestionurl = new \moodle_url('/question/bank/editquestion/question.php',
|
||||
array('returnurl' => $this->qbank->returnurl));
|
||||
if ($this->qbank->cm !== null) {
|
||||
$this->editquestionurl->param('cmid', $this->qbank->cm->id);
|
||||
} else {
|
||||
$this->editquestionurl->param('courseid', $this->qbank->course->id);
|
||||
}
|
||||
$this->editquestionurl->param('cmid', $this->qbank->cm->id);
|
||||
}
|
||||
|
||||
public function get_menu_position(): int {
|
||||
|
||||
@@ -31,8 +31,7 @@ $id = optional_param('id', 0, PARAM_INT); // Question id.
|
||||
$makecopy = optional_param('makecopy', 0, PARAM_BOOL);
|
||||
$qtype = optional_param('qtype', '', PARAM_COMPONENT);
|
||||
$categoryid = optional_param('category', 0, PARAM_INT);
|
||||
$cmid = optional_param('cmid', 0, PARAM_INT);
|
||||
$courseid = optional_param('courseid', 0, PARAM_INT);
|
||||
$cmid = required_param('cmid', PARAM_INT);
|
||||
$wizardnow = optional_param('wizardnow', '', PARAM_ALPHA);
|
||||
$originalreturnurl = optional_param('returnurl', 0, PARAM_LOCALURL);
|
||||
$appendqnumstring = optional_param('appendqnumstring', '', PARAM_ALPHA);
|
||||
@@ -57,9 +56,6 @@ if ($categoryid !== 0) {
|
||||
if ($cmid !== 0) {
|
||||
$url->param('cmid', $cmid);
|
||||
}
|
||||
if ($courseid !== 0) {
|
||||
$url->param('courseid', $courseid);
|
||||
}
|
||||
if ($wizardnow !== '') {
|
||||
$url->param('wizardnow', $wizardnow);
|
||||
}
|
||||
@@ -77,11 +73,8 @@ if ($mdlscrollto) {
|
||||
}
|
||||
$PAGE->set_url($url);
|
||||
|
||||
if ($cmid) {
|
||||
$questionbankurl = new moodle_url('/question/edit.php', array('cmid' => $cmid));
|
||||
} else {
|
||||
$questionbankurl = new moodle_url('/question/edit.php', array('courseid' => $courseid));
|
||||
}
|
||||
$questionbankurl = new moodle_url('/question/edit.php', ['cmid' => $cmid]);
|
||||
|
||||
navigation_node::override_active_url($questionbankurl);
|
||||
|
||||
if ($originalreturnurl) {
|
||||
@@ -96,18 +89,10 @@ if ($mdlscrollto) {
|
||||
$returnurl->param('mdlscrollto', $mdlscrollto);
|
||||
}
|
||||
|
||||
if ($cmid) {
|
||||
list($module, $cm) = get_module_from_cmid($cmid);
|
||||
require_login($cm->course, false, $cm);
|
||||
$thiscontext = context_module::instance($cmid);
|
||||
} else if ($courseid) {
|
||||
require_login($courseid, false);
|
||||
$thiscontext = context_course::instance($courseid);
|
||||
$module = null;
|
||||
$cm = null;
|
||||
} else {
|
||||
throw new moodle_exception('missingcourseorcmid', 'question');
|
||||
}
|
||||
list($module, $cm) = get_module_from_cmid($cmid);
|
||||
require_login($cm->course, false, $cm);
|
||||
$thiscontext = context_module::instance($cmid);
|
||||
|
||||
$contexts = new core_question\local\bank\question_edit_contexts($thiscontext);
|
||||
$PAGE->set_pagelayout('admin');
|
||||
|
||||
@@ -119,10 +104,7 @@ if ($id) {
|
||||
if (!$question = $DB->get_record('question', array('id' => $id))) {
|
||||
throw new moodle_exception('questiondoesnotexist', 'question', $returnurl);
|
||||
}
|
||||
// We can use $COURSE here because it's been initialised as part of the
|
||||
// require_login above. Passing it as the third parameter tells the function
|
||||
// to filter the course tags by that course.
|
||||
get_question_options($question, true, [$COURSE]);
|
||||
get_question_options($question, true);
|
||||
|
||||
} else if ($categoryid && $qtype) { // Only for creating new questions.
|
||||
$question = new stdClass();
|
||||
|
||||
@@ -10,8 +10,8 @@ Feature: Use the qbank plugin manager page for editquestion
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Test quiz | C1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | First question | Answer the first question |
|
||||
|
||||
@@ -10,8 +10,8 @@ Feature: Use the qbank base view to test the status change using
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Test quiz | C1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | First question | Answer the first question |
|
||||
|
||||
@@ -35,22 +35,10 @@ class helper {
|
||||
* @return \moodle_url the requested URL.
|
||||
*/
|
||||
public static function question_get_export_single_question_url($question): \moodle_url {
|
||||
$params = ['id' => $question->id, 'sesskey' => sesskey()];
|
||||
$context = \context::instance_by_id($question->contextid);
|
||||
switch ($context->contextlevel) {
|
||||
case CONTEXT_MODULE:
|
||||
$params['cmid'] = $context->instanceid;
|
||||
break;
|
||||
|
||||
case CONTEXT_COURSE:
|
||||
$params['courseid'] = $context->instanceid;
|
||||
break;
|
||||
|
||||
default:
|
||||
$params['courseid'] = SITEID;
|
||||
}
|
||||
|
||||
return new \moodle_url('/question/bank/exporttoxml/exportone.php', $params);
|
||||
return new \moodle_url('/question/bank/exporttoxml/exportone.php',
|
||||
['id' => $question->id, 'sesskey' => sesskey(), 'cmid' => $context->instanceid]
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,24 +29,16 @@ require_once($CFG->dirroot . '/question/format/xml/format.php');
|
||||
|
||||
// Get the parameters from the URL.
|
||||
$questionid = required_param('id', PARAM_INT);
|
||||
$cmid = optional_param('cmid', 0, PARAM_INT);
|
||||
$courseid = optional_param('courseid', 0, PARAM_INT);
|
||||
$cmid = required_param('cmid', PARAM_INT);
|
||||
$urlparams = ['id' => $questionid, 'sesskey' => sesskey()];
|
||||
|
||||
\core_question\local\bank\helper::require_plugin_enabled('qbank_exporttoxml');
|
||||
|
||||
if ($cmid) {
|
||||
$cm = get_coursemodule_from_id(null, $cmid);
|
||||
require_login($cm->course, false, $cm);
|
||||
$thiscontext = context_module::instance($cmid);
|
||||
$urlparams['cmid'] = $cmid;
|
||||
} else if ($courseid) {
|
||||
require_login($courseid, false);
|
||||
$thiscontext = context_course::instance($courseid);
|
||||
$urlparams['courseid'] = $courseid;
|
||||
} else {
|
||||
throw new moodle_exception('missingcourseorcmid', 'question');
|
||||
}
|
||||
$cm = get_coursemodule_from_id(null, $cmid);
|
||||
require_login($cm->course, false, $cm);
|
||||
$thiscontext = context_module::instance($cmid);
|
||||
$urlparams['cmid'] = $cmid;
|
||||
|
||||
require_sesskey();
|
||||
|
||||
// Load the necessary data.
|
||||
|
||||
@@ -10,8 +10,8 @@ Feature: Use the qbank plugin manager page for exporttoxml
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Test quiz | C1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | First question | Answer the first question |
|
||||
|
||||
@@ -14,9 +14,12 @@ Feature: A teacher can export a question as XML from the preview question screen
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | idnumber |
|
||||
| qbank | Qbank 1 | C1 | qbank1 |
|
||||
And the following "question categories" exist:
|
||||
| name | contextlevel | reference |
|
||||
| Test questions | Course | C1 |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | qbank1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name |
|
||||
| Test questions | numerical | Test question to be previewed |
|
||||
|
||||
@@ -34,8 +34,12 @@ class helper {
|
||||
* @param int $courseid id of the course
|
||||
* @param ?string $filter filter param to pass to the History view
|
||||
* @return \moodle_url
|
||||
* @deprecated since Moodle 5.0.
|
||||
* @todo MDL-82413 Final deprecation in Moodle 6.0.
|
||||
*/
|
||||
#[\core\attribute\deprecated(replacement: 'qbank_history\helper::get_question_history_url', since: '5.0', mdl: 'MDL-71378')]
|
||||
public static function question_history_url(int $entryid, string $returnrul, int $courseid, ?string $filter): \moodle_url {
|
||||
\core\deprecation::emit_deprecation_if_present([self::class, __FUNCTION__]);
|
||||
$params = [
|
||||
'entryid' => $entryid,
|
||||
'returnurl' => $returnrul,
|
||||
@@ -48,4 +52,27 @@ class helper {
|
||||
return new \moodle_url('/question/bank/history/history.php', $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the question history url.
|
||||
*
|
||||
* @param int $entryid id of the question entry
|
||||
* @param string $returnrul url of the page to return to
|
||||
* @param int $cmid id of the coursemodule holding the question bank.
|
||||
* @param ?string $filter filter param to pass to the History view
|
||||
* @return \moodle_url
|
||||
*/
|
||||
public static function get_question_history_url(int $entryid, string $returnrul, int $cmid, ?string $filter) {
|
||||
|
||||
$params = [
|
||||
'entryid' => $entryid,
|
||||
'returnurl' => $returnrul,
|
||||
'cmid' => $cmid,
|
||||
];
|
||||
if (!is_null($filter)) {
|
||||
$params['filter'] = $filter;
|
||||
}
|
||||
|
||||
return new \moodle_url('/question/bank/history/history.php', $params);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -49,10 +49,10 @@ class history_action extends question_action_base {
|
||||
}
|
||||
|
||||
if (question_has_capability_on($question, 'use')) {
|
||||
$url = helper::question_history_url(
|
||||
$url = helper::get_question_history_url(
|
||||
$question->questionbankentryid,
|
||||
$this->qbank->returnurl,
|
||||
$this->qbank->course->id,
|
||||
$this->qbank->cm->id,
|
||||
$this->qbank->base_url()->param('filter'),
|
||||
);
|
||||
return [$url, 't/log', $this->strpreview];
|
||||
|
||||
@@ -63,6 +63,10 @@ class question_history_view extends view {
|
||||
array $params = [],
|
||||
array $extraparams = [],
|
||||
) {
|
||||
if ($cm === null) {
|
||||
debugging('$cm is now a required field', DEBUG_DEVELOPER);
|
||||
}
|
||||
|
||||
$this->entryid = $extraparams['entryid'];
|
||||
$this->basereturnurl = new \moodle_url($extraparams['returnurl']);
|
||||
parent::__construct($contexts, $pageurl, $course, $cm, $params, $extraparams);
|
||||
|
||||
@@ -42,7 +42,7 @@ $PAGE->set_url($url);
|
||||
// Additional param to differentiate with other question bank view.
|
||||
$extraparams['entryid'] = $entryid;
|
||||
$extraparams['returnurl'] = $returnurl;
|
||||
$questionbank = new \qbank_history\question_history_view($contexts, $url, $COURSE, null, $pagevars, $extraparams);
|
||||
$questionbank = new \qbank_history\question_history_view($contexts, $url, $COURSE, $cm, $pagevars, $extraparams);
|
||||
|
||||
$streditingquestions = get_string('history_header', 'qbank_history');
|
||||
$PAGE->set_title($streditingquestions);
|
||||
|
||||
@@ -10,8 +10,8 @@ Feature: Use the qbank plugin manager page for question history
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Test quiz | C1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | First question | Answer the first question |
|
||||
@@ -42,8 +42,8 @@ Feature: Use the qbank plugin manager page for question history
|
||||
@javascript
|
||||
Scenario: Viewing history for a question in a non-default category
|
||||
Given the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions 2 |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions 2 |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions 2 | truefalse | Second question | Answer the second question |
|
||||
|
||||
@@ -10,8 +10,8 @@ Feature: Use the qbank plugin manager page for version column
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Test quiz | C1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | First question | Answer the first question |
|
||||
|
||||
@@ -80,16 +80,16 @@ class helper_test extends \advanced_testcase {
|
||||
public function test_question_history_url(): void {
|
||||
$this->resetAfterTest();
|
||||
$filter = urlencode('filters[]');
|
||||
$actionurl = helper::question_history_url(
|
||||
$actionurl = helper::get_question_history_url(
|
||||
$this->questiondata->questionbankentryid,
|
||||
$this->returnurl,
|
||||
$this->courseid,
|
||||
$this->context->instanceid,
|
||||
$filter,
|
||||
);
|
||||
$params = [
|
||||
'entryid' => $this->questiondata->questionbankentryid,
|
||||
'returnurl' => $this->returnurl,
|
||||
'courseid' => $this->courseid,
|
||||
'cmid' => $this->context->instanceid,
|
||||
'filter' => $filter,
|
||||
];
|
||||
$expectedurl = new \moodle_url('/question/bank/history/history.php', $params);
|
||||
@@ -103,16 +103,16 @@ class helper_test extends \advanced_testcase {
|
||||
*/
|
||||
public function test_question_history_url_null_filter(): void {
|
||||
$this->resetAfterTest();
|
||||
$actionurl = helper::question_history_url(
|
||||
$actionurl = helper::get_question_history_url(
|
||||
$this->questiondata->questionbankentryid,
|
||||
$this->returnurl,
|
||||
$this->courseid,
|
||||
$this->context->instanceid,
|
||||
null,
|
||||
);
|
||||
$params = [
|
||||
'entryid' => $this->questiondata->questionbankentryid,
|
||||
'returnurl' => $this->returnurl,
|
||||
'courseid' => $this->courseid,
|
||||
'cmid' => $this->context->instanceid,
|
||||
];
|
||||
$expectedurl = new \moodle_url('/question/bank/history/history.php', $params);
|
||||
$this->assertEquals($expectedurl, $actionurl);
|
||||
|
||||
@@ -46,6 +46,7 @@ class question_history_view_test extends \advanced_testcase {
|
||||
// Create a course.
|
||||
$course = $generator->create_course();
|
||||
$qbank = $generator->create_module('qbank', ['course' => $course->id]);
|
||||
$cm = get_coursemodule_from_id('qbank', $qbank->cmid);
|
||||
$context = \context_module::instance($qbank->cmid);
|
||||
|
||||
// Create a question in the default category.
|
||||
@@ -73,7 +74,7 @@ class question_history_view_test extends \advanced_testcase {
|
||||
'entryid' => $entry->id,
|
||||
'returnurl' => "/",
|
||||
];
|
||||
$view = new $viewclass($contexts, new \moodle_url('/'), $course, null, $pagevars, $extraparams);
|
||||
$view = new $viewclass($contexts, new \moodle_url('/'), $course, $cm, $pagevars, $extraparams);
|
||||
ob_start();
|
||||
$view->display();
|
||||
$html = ob_get_clean();
|
||||
@@ -98,6 +99,8 @@ class question_history_view_test extends \advanced_testcase {
|
||||
|
||||
// Create a course.
|
||||
$course = $generator->create_course();
|
||||
$qbank = $generator->create_module('qbank', ['course' => $course->id]);
|
||||
$cm = get_coursemodule_from_id('qbank', $qbank->cmid);
|
||||
$context = \context_course::instance($course->id);
|
||||
|
||||
// Create a question in the default category.
|
||||
@@ -120,7 +123,7 @@ class question_history_view_test extends \advanced_testcase {
|
||||
'entryid' => $entry->id,
|
||||
'returnurl' => "/",
|
||||
];
|
||||
$view = new $viewclass($contexts, new \moodle_url('/'), $course, null, $pagevars, $extraparams);
|
||||
$view = new $viewclass($contexts, new \moodle_url('/'), $course, $cm, $pagevars, $extraparams);
|
||||
ob_start();
|
||||
$view->display_question_bank_header();
|
||||
$headerhtml = ob_get_clean();
|
||||
@@ -129,7 +132,7 @@ class question_history_view_test extends \advanced_testcase {
|
||||
|
||||
$questiondata2 = $questiongenerator->update_question($questiondata1, null,
|
||||
['name' => 'Second version']);
|
||||
$view = new $viewclass($contexts, new \moodle_url('/'), $course, null, $pagevars, $extraparams);
|
||||
$view = new $viewclass($contexts, new \moodle_url('/'), $course, $cm, $pagevars, $extraparams);
|
||||
ob_start();
|
||||
$view->display_question_bank_header();
|
||||
$headerhtml = ob_get_clean();
|
||||
|
||||
@@ -48,17 +48,13 @@ if (!$category = $DB->get_record("question_categories", ['id' => $catid])) {
|
||||
|
||||
$categorycontext = context::instance_by_id($category->contextid);
|
||||
$category->context = $categorycontext;
|
||||
// This page can be called without courseid or cmid in which case.
|
||||
// This page can be called without cmid in which case.
|
||||
// We get the context from the category object.
|
||||
if ($contexts === null) { // Need to get the course from the chosen category.
|
||||
$contexts = new core_question\local\bank\question_edit_contexts($categorycontext);
|
||||
$thiscontext = $contexts->lowest();
|
||||
if ($thiscontext->contextlevel == CONTEXT_COURSE) {
|
||||
require_login($thiscontext->instanceid, false);
|
||||
} else if ($thiscontext->contextlevel == CONTEXT_MODULE) {
|
||||
list($module, $cm) = get_module_from_cmid($thiscontext->instanceid);
|
||||
require_login($cm->course, false, $cm);
|
||||
}
|
||||
[$module, $cm] = get_module_from_cmid($thiscontext->instanceid);
|
||||
require_login($cm->course, false, $cm);
|
||||
$contexts->require_one_edit_tab_cap($edittab);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,16 +37,15 @@ use qbank_managecategories\question_categories;
|
||||
require_login();
|
||||
core_question\local\bank\helper::require_plugin_enabled(helper::PLUGINNAME);
|
||||
|
||||
// Since Moodle 5.0 any request with the courseid parameter is deprecated and will redirect to the banks management page.
|
||||
if ($courseid = optional_param('courseid', 0, PARAM_INT)) {
|
||||
redirect(new moodle_url('/question/banks.php', ['courseid' => $courseid]));
|
||||
}
|
||||
|
||||
list($thispageurl, $contexts, $cmid, $cm, $module, $pagevars) =
|
||||
question_edit_setup('categories', '/question/bank/managecategories/category.php');
|
||||
$courseid = optional_param('courseid', 0, PARAM_INT);
|
||||
|
||||
if (!is_null($cmid)) {
|
||||
$thiscontext = context_module::instance($cmid)->id;
|
||||
} else {
|
||||
$course = get_course($courseid);
|
||||
$thiscontext = context_course::instance($course->id)->id;
|
||||
}
|
||||
$thiscontext = context_module::instance($cmid)->id;
|
||||
|
||||
$todelete = optional_param('delete', 0, PARAM_INT); // The ID of a category to delete.
|
||||
|
||||
@@ -112,10 +111,13 @@ if ($questionstomove) {
|
||||
echo $OUTPUT->box(get_string('categorymove', 'question', $vars), 'generalbox boxaligncenter');
|
||||
$moveform->display();
|
||||
} else {
|
||||
// Get module contexts we have capabilities to manage.
|
||||
$contextswithcaps = $contexts->having_one_edit_tab_cap('categories');
|
||||
$modcontexts = array_filter($contextswithcaps, static fn ($context) => $context->contextlevel === CONTEXT_MODULE);
|
||||
// Display the user interface.
|
||||
$questioncategories = new question_categories(
|
||||
$thispageurl,
|
||||
$contexts->having_one_edit_tab_cap('categories'),
|
||||
$modcontexts,
|
||||
$cmid,
|
||||
$courseid,
|
||||
$thiscontext,
|
||||
|
||||
@@ -32,6 +32,9 @@ class category_condition extends condition {
|
||||
/** @var \stdClass The course record. */
|
||||
protected $course;
|
||||
|
||||
/** @var \stdClass The course_modules record. */
|
||||
protected \stdClass $cm;
|
||||
|
||||
/** @var \stdClass The category record. */
|
||||
protected $category;
|
||||
|
||||
@@ -61,6 +64,7 @@ class category_condition extends condition {
|
||||
static fn($context) => $context->contextlevel === CONTEXT_MODULE
|
||||
);
|
||||
$this->course = $qbank->course;
|
||||
$this->cm = $qbank->cm;
|
||||
|
||||
[$categoryid, $contextid] = self::validate_category_param($this->cat);
|
||||
if (is_null($categoryid)) {
|
||||
@@ -74,14 +78,13 @@ class category_condition extends condition {
|
||||
}
|
||||
|
||||
/**
|
||||
* MDL-71378 TODO: Not used and to be deprecated anyway
|
||||
* Return default category
|
||||
*
|
||||
* @return \stdClass default category
|
||||
*/
|
||||
public function get_default_category(): \stdClass {
|
||||
if (empty($this->category)) {
|
||||
return question_get_default_category(\context_course::instance($this->course->id)->id);
|
||||
return question_get_default_category(\context_module::instance($this->cm->id)->id, true);
|
||||
}
|
||||
|
||||
return $this->category;
|
||||
|
||||
@@ -86,6 +86,10 @@ class question_categories {
|
||||
fields: 'contextid, id'
|
||||
);
|
||||
foreach ($contexts as $context) {
|
||||
// We can only have categories in module context.
|
||||
if ($context->contextlevel !== CONTEXT_MODULE) {
|
||||
continue;
|
||||
}
|
||||
$items = helper::get_categories_for_contexts($context->id);
|
||||
// Create an ordered tree with children correctly nested under parents.
|
||||
foreach ($items as $item) {
|
||||
|
||||
@@ -87,12 +87,8 @@ class question_category_list_item extends \list_item {
|
||||
$str = $extraargs['str'];
|
||||
$category = $this->item;
|
||||
|
||||
// Each section adds html to be displayed as part of this list item.
|
||||
$nodeparent = $PAGE->settingsnav->find('questionbank', \navigation_node::TYPE_CONTAINER);
|
||||
$questionbankurl = new moodle_url('/question/edit.php', $this->parentlist->pageurl->params());
|
||||
|
||||
// The category URL is based on the node action.
|
||||
$questionbankurl = new moodle_url($nodeparent->action->out_omit_querystring(),
|
||||
$this->parentlist->pageurl->params());
|
||||
$questionbankurl->param('cat', $category->id . ',' . $category->contextid);
|
||||
|
||||
$categoryname = format_string($category->name, true, ['context' => $this->parentlist->context]);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user