diff --git a/question/engine/questionattempt.php b/question/engine/questionattempt.php
index 705594dc3f0..c45d78d7e29 100644
--- a/question/engine/questionattempt.php
+++ b/question/engine/questionattempt.php
@@ -359,6 +359,17 @@ class question_attempt {
return 'q' . $this->usageid . ':' . $this->slot . '_';
}
+ /**
+ * When the question is rendered, this unique id is added to the
+ * outer div of the question. It can be used to uniquely reference
+ * the question from JavaScript.
+ *
+ * @return string id added to the outer
when the question is rendered.
+ */
+ public function get_outer_question_div_unique_id() {
+ return 'question-' . $this->usageid . '-' . $this->slot;
+ }
+
/**
* Get one of the steps in this attempt.
*
diff --git a/question/engine/renderer.php b/question/engine/renderer.php
index 17246d59044..6d19acbf753 100644
--- a/question/engine/renderer.php
+++ b/question/engine/renderer.php
@@ -89,7 +89,7 @@ class core_question_renderer extends plugin_renderer_base {
$output = '';
$output .= html_writer::start_tag('div', array(
- 'id' => 'q' . $qa->get_slot(),
+ 'id' => $qa->get_outer_question_div_unique_id(),
'class' => implode(' ', array(
'que',
$qa->get_question()->qtype->name(),
diff --git a/question/engine/upgrade.txt b/question/engine/upgrade.txt
index 65378001928..60c32052695 100644
--- a/question/engine/upgrade.txt
+++ b/question/engine/upgrade.txt
@@ -1,5 +1,18 @@
This files describes API changes for the core question engine.
+=== 3.7 ===
+
+1) When a question is rendered, the outer div of the question has an id="q123"
+ added. Unfortunately, this id was not actually unique, leading to bugs like
+ MDL-52572. Therefore, we have had to change it. The id used now is what
+ is returned by the new method $qa->get_outer_question_div_unique_id().
+ The old code that you need to search for and replace with a call to this
+ method is "'q' . $qa->get_slot()"
+
+ Note, the new method has also been added to Moodle 3.5.6 and 3.6.4, but
+ returning the old id. This is to help question types that want to support
+ multiple Moodle versions.
+
=== 3.1, 3.0.3, 2.9.5 ===
1) The field question_display_options::$extrainfocontent is now displayed in the
diff --git a/question/type/ddimageortext/rendererbase.php b/question/type/ddimageortext/rendererbase.php
index 9d1f779b22f..c2722da555f 100644
--- a/question/type/ddimageortext/rendererbase.php
+++ b/question/type/ddimageortext/rendererbase.php
@@ -115,7 +115,7 @@ class qtype_ddtoimage_renderer_base extends qtype_with_combined_feedback_rendere
$PAGE->requires->string_for_js('blank', 'qtype_ddimageortext');
$PAGE->requires->js_call_amd('qtype_ddimageortext/question', 'init',
- ['q' . $qa->get_slot(), $options->readonly, $question->places]);
+ [$qa->get_outer_question_div_unique_id(), $options->readonly, $question->places]);
if ($qa->get_state() == question_state::$invalid) {
$output .= html_writer::nonempty_tag('div',
diff --git a/question/type/ddmarker/renderer.php b/question/type/ddmarker/renderer.php
index 971acfc3541..f26d512f02c 100644
--- a/question/type/ddmarker/renderer.php
+++ b/question/type/ddmarker/renderer.php
@@ -97,7 +97,7 @@ class qtype_ddmarker_renderer extends qtype_ddtoimage_renderer_base {
}
$PAGE->requires->js_call_amd('qtype_ddmarker/question', 'init',
- ['q' . $qa->get_slot(), $bgimage, $options->readonly, $visibledropzones]);
+ [$qa->get_outer_question_div_unique_id(), $bgimage, $options->readonly, $visibledropzones]);
if ($qa->get_state() == question_state::$invalid) {
$output .= html_writer::nonempty_tag('div',
diff --git a/question/type/ddwtos/renderer.php b/question/type/ddwtos/renderer.php
index 5e53cbf9331..b511662f48b 100644
--- a/question/type/ddwtos/renderer.php
+++ b/question/type/ddwtos/renderer.php
@@ -43,7 +43,7 @@ class qtype_ddwtos_renderer extends qtype_elements_embedded_in_question_text_ren
$result = parent::formulation_and_controls($qa, $options);
$PAGE->requires->js_call_amd('qtype_ddwtos/ddwtos', 'init',
- ['q' . $qa->get_slot(), $options->readonly]);
+ [$qa->get_outer_question_div_unique_id(), $options->readonly]);
return $result;
}