diff --git a/renderer.php b/renderer.php
index 014a9f2..21740ff 100644
--- a/renderer.php
+++ b/renderer.php
@@ -64,8 +64,65 @@ public function formulation_and_controls(question_attempt $qa, question_display_
]);
}
- $renderer = new question_ui_renderer($question->ui->formulation, $question->ui->placeholders, $options, $qa);
- return $renderer->render();
+ global $PAGE, $OUTPUT;
+ $oldpage = $PAGE;
+ $oldoutput = $OUTPUT; // Class moodle_page also modifies global $OUTPUT variable.
+
+ try {
+ $PAGE = new moodle_page();
+ $PAGE->set_context($options->context);
+ $PAGE->set_pagelayout('embedded');
+ $PAGE->set_pagetype($oldpage->pagetype);
+ $PAGE->set_url($oldpage->url);
+
+ $qformulation = new question_ui_renderer($question->ui->formulation, $question->ui->placeholders, $options,
+ $qa);
+ $feedback = html_writer::nonempty_tag('div', $this->feedback_in_iframe($qa, $options),
+ ['class' => 'outcome clearfix']);
+
+ $editor = editors_get_preferred_editor(FORMAT_HTML); // Only for testing purposes!
+ $editor->use_editor('mytextareaid', [
+ 'context' => $options->context,
+ 'enable_filemanagement' => true,
+ 'maxfiles' => EDITOR_UNLIMITED_FILES,
+ ], question_utils::get_filepicker_options($options->context, 0));
+
+ $questionsrc = $this->output->render_from_template('qtype_questionpy/iframe_content', [
+ 'question' => $qformulation->render(),
+ 'feedback' => $feedback,
+ 'filepicker' => $this->get_file_picker_test($options->context),
+ ]);
+
+ $outputrenderer = $PAGE->get_renderer('core', null);
+ $iframesrc = $outputrenderer->header();
+ $iframesrc .= $questionsrc;
+ $iframesrc .= $outputrenderer->footer();
+ return '';
+
+ } finally {
+ $PAGE = $oldpage;
+ $OUTPUT = $oldoutput;
+ }
+
+ return '';
+ }
+
+ protected function get_file_picker_test($context) {
+ global $CFG, $PAGE;
+ require_once($CFG->dirroot . '/lib/form/filemanager.php');
+
+ $pickeroptions = new stdClass();
+ $pickeroptions->mainfile = null;
+ $pickeroptions->maxfiles = 10;
+ $pickeroptions->itemid = 1;
+ $pickeroptions->context = $context;
+ $pickeroptions->return_types = FILE_INTERNAL | FILE_CONTROLLED_LINK;
+ $pickeroptions->accepted_types = '*';
+
+ $fm = new form_filemanager($pickeroptions);
+ $fm->options->maxbytes = 10*1024*1024;
+ $filesrenderer = $PAGE->get_renderer('core', 'files');
+ return $filesrenderer->render($fm);
}
/**
@@ -80,7 +137,7 @@ public function formulation_and_controls(question_attempt $qa, question_display_
* @return string HTML fragment.
* @throws coding_exception
*/
- public function feedback(question_attempt $qa, question_display_options $options): string {
+ protected function feedback_in_iframe(question_attempt $qa, question_display_options $options): string {
$question = $qa->get_question();
assert($question instanceof qtype_questionpy_question);
@@ -128,6 +185,30 @@ public function feedback(question_attempt $qa, question_display_options $options
);
}
+ if ($output) {
+ // Copied from \core_question_renderer::question.
+ $output = html_writer::tag('h4', get_string('feedback', 'question'),
+ ['class' => 'accesshide']) . $output;
+ }
+
return $output;
}
+
+ /**
+ * Generate the display of the outcome part of the question. This is the
+ * area that contains the various forms of feedback. This function generates
+ * the content of this area belonging to the question type.
+ *
+ * Subclasses will normally want to override the more specific methods
+ * {specific_feedback()}, {general_feedback()} and {correct_response()}
+ * that this method calls.
+ *
+ * @param question_attempt $qa the question attempt to display.
+ * @param question_display_options $options controls what should and should not be displayed.
+ * @return string HTML fragment.
+ */
+ public function feedback(question_attempt $qa, question_display_options $options) {
+ // We display all feedbacks in the iframe.
+ return '';
+ }
}
diff --git a/styles.css b/styles.css
index bfd2995..3e9b440 100644
--- a/styles.css
+++ b/styles.css
@@ -25,6 +25,26 @@
display: none;
}
+/* Make question iframe seamless. */
+.que.questionpy .formulation {
+ padding: 0;
+ border: 0;
+ border-radius: unset;
+ margin: 0;
+ background: unset;
+}
+
+.que.questionpy iframe {
+ border: 0;
+ padding: 0;
+ width: 100%;
+ height: 500px;
+}
+
+.que .questionpy-iframe-content.content {
+ margin: 0;
+}
+
/* Style package selection container */
.qpy-tab-content {
diff --git a/templates/iframe_content.mustache b/templates/iframe_content.mustache
new file mode 100644
index 0000000..f637eec
--- /dev/null
+++ b/templates/iframe_content.mustache
@@ -0,0 +1,44 @@
+{{!
+ This file is part of the QuestionPy Moodle plugin - https://questionpy.org
+
+ Moodle is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Moodle is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Moodle. If not, see