mirror of
https://github.com/moodle/moodle.git
synced 2025-03-19 15:10:05 +01:00
Merge branch 'MDL-41090_rebased' of https://github.com/andrewhancox/moodle
This commit is contained in:
commit
f4a30c5fdf
@ -36,15 +36,15 @@ Feature: Teachers can override the grade for any question
|
||||
And I press "Submit all and finish"
|
||||
And I click on "Submit all and finish" "button" in the "Confirmation" "dialogue"
|
||||
And I log out
|
||||
And I log in as "teacher1"
|
||||
|
||||
@javascript @_switch_window @_bug_phantomjs
|
||||
Scenario: Validating the marking of an essay question attempt.
|
||||
When I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage
|
||||
And I follow "Quiz 1"
|
||||
And I follow "Attempts: 1"
|
||||
And I follow "Review attempt"
|
||||
|
||||
@javascript @_switch_window @_bug_phantomjs
|
||||
Scenario: Validating the marking of an essay question attempt.
|
||||
When I follow "Make comment or override mark"
|
||||
And I follow "Make comment or override mark"
|
||||
And I switch to "commentquestion" window
|
||||
And I set the field "Mark" to "25"
|
||||
And I press "Save"
|
||||
@ -57,3 +57,35 @@ Feature: Teachers can override the grade for any question
|
||||
And I should see "Complete" in the "Manually graded 10 with comment: " "table_row"
|
||||
# This time is same as time the window is open. So wait for it to close before proceeding.
|
||||
And I wait "2" seconds
|
||||
|
||||
@javascript @_switch_window @_file_upload @_bug_phantomjs
|
||||
Scenario: Comment on a response to an essay question attempt.
|
||||
When I log in as "teacher1"
|
||||
And I follow "Manage private files"
|
||||
And I upload "mod/quiz/tests/fixtures/moodle_logo.jpg" file to "Files" filemanager
|
||||
And I click on "Save changes" "button"
|
||||
And I am on "Course 1" course homepage
|
||||
And I follow "Quiz 1"
|
||||
And I follow "Attempts: 1"
|
||||
And I follow "Review attempt"
|
||||
And I follow "Make comment or override mark"
|
||||
And I switch to "commentquestion" window
|
||||
And I set the field "Comment" to "Administrator's comment"
|
||||
# Atto needs focus to add image, select empty p tag to do so.
|
||||
And I select the text in the "Comment" Atto editor
|
||||
And I click on "Image" "button" in the "[data-fieldtype=editor]" "css_element"
|
||||
And I click on "Browse repositories..." "button"
|
||||
And I click on "Private files" "link" in the ".fp-repo-area" "css_element"
|
||||
And I click on "moodle_logo.jpg" "link"
|
||||
And I click on "Select this file" "button"
|
||||
And I set the field "Describe this image for someone who cannot see it" to "It's the logo"
|
||||
And I click on "Save image" "button"
|
||||
# Editor is not inserting the html for the image correctly
|
||||
# when running under behat so line below manually inserts it.
|
||||
And I set the field "Comment" to "<img src=\"@@PLUGINFILE@@/moodle_logo.jpg\" alt=\"It's the logo\" width=\"48\" height=\"48\" class=\"img-responsive atto_image_button_text-bottom\"><!-- File hash: a8e3ffba4ab315b3fb9187ebbf122fe9 -->"
|
||||
And I press "Save" and switch to main window
|
||||
And I switch to the main window
|
||||
And I should see "It's the logo" in the "3" "table_row"
|
||||
And "//*[contains(@class, 'comment')]//img[contains(@src, 'moodle_logo.jpg')]" "xpath_element" should exist
|
||||
# This time is same as time the window is open. So wait for it to close before proceeding.
|
||||
And I wait "2" seconds
|
||||
|
BIN
mod/quiz/tests/fixtures/moodle_logo.jpg
vendored
Normal file
BIN
mod/quiz/tests/fixtures/moodle_logo.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 898 B |
@ -124,6 +124,17 @@ abstract class question_behaviour {
|
||||
*/
|
||||
public function check_file_access($options, $component, $filearea, $args, $forcedownload) {
|
||||
$this->adjust_display_options($options);
|
||||
|
||||
if ($component == 'question' && $filearea == 'response_bf_comment') {
|
||||
foreach ($this->qa->get_step_iterator() as $attemptstep) {
|
||||
if ($attemptstep->get_id() == $args[0]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->question->check_file_access($this->qa, $options, $component,
|
||||
$filearea, $args, $forcedownload);
|
||||
}
|
||||
@ -202,7 +213,7 @@ abstract class question_behaviour {
|
||||
return array();
|
||||
}
|
||||
|
||||
$vars = array('comment' => PARAM_RAW, 'commentformat' => PARAM_INT);
|
||||
$vars = array('comment' => question_attempt::PARAM_RAW_FILES, 'commentformat' => PARAM_INT);
|
||||
if ($this->qa->get_max_mark()) {
|
||||
$vars['mark'] = PARAM_RAW_TRIMMED;
|
||||
$vars['maxmark'] = PARAM_FLOAT;
|
||||
@ -507,15 +518,20 @@ abstract class question_behaviour {
|
||||
* @param $comment the comment text to format. If omitted,
|
||||
* $this->qa->get_manual_comment() is used.
|
||||
* @param $commentformat the format of the comment, one of the FORMAT_... constants.
|
||||
* @param $context the quiz context.
|
||||
* @return string the comment, ready to be output.
|
||||
*/
|
||||
public function format_comment($comment = null, $commentformat = null) {
|
||||
public function format_comment($comment = null, $commentformat = null, $context = null) {
|
||||
$formatoptions = new stdClass();
|
||||
$formatoptions->noclean = true;
|
||||
$formatoptions->para = false;
|
||||
|
||||
if (is_null($comment)) {
|
||||
list($comment, $commentformat) = $this->qa->get_manual_comment();
|
||||
list($comment, $commentformat, $commentstep) = $this->qa->get_manual_comment();
|
||||
}
|
||||
|
||||
if ($context !== null) {
|
||||
$comment = $this->qa->rewrite_response_pluginfile_urls($comment, $context->id, 'bf_comment', $commentstep);
|
||||
}
|
||||
|
||||
return format_text($comment, $commentformat, $formatoptions);
|
||||
@ -528,8 +544,9 @@ abstract class question_behaviour {
|
||||
protected function summarise_manual_comment($step) {
|
||||
$a = new stdClass();
|
||||
if ($step->has_behaviour_var('comment')) {
|
||||
$a->comment = shorten_text(html_to_text($this->format_comment(
|
||||
$step->get_behaviour_var('comment')), 0, false), 200);
|
||||
list($comment, $commentformat, $commentstep) = $this->qa->get_manual_comment();
|
||||
$comment = question_utils::to_plain_text($comment, $commentformat);
|
||||
$a->comment = shorten_text($comment, 200);
|
||||
} else {
|
||||
$a->comment = '';
|
||||
}
|
||||
|
@ -69,9 +69,14 @@ abstract class qbehaviour_renderer extends plugin_renderer_base {
|
||||
}
|
||||
|
||||
public function manual_comment_fields(question_attempt $qa, question_display_options $options) {
|
||||
global $CFG;
|
||||
|
||||
require_once($CFG->dirroot.'/lib/filelib.php');
|
||||
require_once($CFG->dirroot.'/repository/lib.php');
|
||||
|
||||
$inputname = $qa->get_behaviour_field_name('comment');
|
||||
$id = $inputname . '_id';
|
||||
list($commenttext, $commentformat) = $qa->get_current_manual_comment();
|
||||
list($commenttext, $commentformat, $commentstep) = $qa->get_current_manual_comment();
|
||||
|
||||
$editor = editors_get_preferred_editor($commentformat);
|
||||
$strformats = format_text_menu();
|
||||
@ -80,12 +85,27 @@ abstract class qbehaviour_renderer extends plugin_renderer_base {
|
||||
$formats[$fid] = $strformats[$fid];
|
||||
}
|
||||
|
||||
$draftitemareainputname = $qa->get_behaviour_field_name('comment:itemid');
|
||||
$draftitemid = optional_param($draftitemareainputname, false, PARAM_INT);
|
||||
|
||||
if (!$draftitemid && $commentstep === null) {
|
||||
$commenttext = '';
|
||||
$draftitemid = file_get_unused_draft_itemid();
|
||||
} else if (!$draftitemid) {
|
||||
list($draftitemid, $commenttext) = $commentstep->prepare_response_files_draft_itemid_with_text(
|
||||
'bf_comment', $options->context->id, $commenttext);
|
||||
}
|
||||
|
||||
$editor->set_text($commenttext);
|
||||
$editor->use_editor($id, array('context' => $options->context));
|
||||
$editor->use_editor($id, question_utils::get_editor_options($options->context),
|
||||
question_utils::get_filepicker_options($options->context, $draftitemid));
|
||||
|
||||
$commenteditor = html_writer::tag('div', html_writer::tag('textarea', s($commenttext),
|
||||
array('id' => $id, 'name' => $inputname, 'rows' => 10, 'cols' => 60)));
|
||||
|
||||
$attributes = ['type' => 'hidden', 'name' => $draftitemareainputname, 'value' => $draftitemid];
|
||||
$commenteditor .= html_writer::empty_tag('input', $attributes);
|
||||
|
||||
$editorformat = '';
|
||||
if (count($formats) == 1) {
|
||||
reset($formats);
|
||||
@ -105,7 +125,7 @@ abstract class qbehaviour_renderer extends plugin_renderer_base {
|
||||
$comment = html_writer::tag('div', html_writer::tag('div',
|
||||
html_writer::tag('label', get_string('comment', 'question'),
|
||||
array('for' => $id)), array('class' => 'fitemtitle')) .
|
||||
html_writer::tag('div', $commenteditor, array('class' => 'felement fhtmleditor')),
|
||||
html_writer::tag('div', $commenteditor, array('class' => 'felement fhtmleditor', 'data-fieldtype' => "editor")),
|
||||
array('class' => 'fitem'));
|
||||
$comment .= $editorformat;
|
||||
|
||||
@ -168,7 +188,7 @@ abstract class qbehaviour_renderer extends plugin_renderer_base {
|
||||
public function manual_comment_view(question_attempt $qa, question_display_options $options) {
|
||||
$output = '';
|
||||
if ($qa->has_manual_comment()) {
|
||||
$output .= get_string('commentx', 'question', $qa->get_behaviour()->format_comment());
|
||||
$output .= get_string('commentx', 'question', $qa->get_behaviour()->format_comment(null, null, $options->context));
|
||||
}
|
||||
if ($options->manualcommentlink) {
|
||||
$url = new moodle_url($options->manualcommentlink, array('slot' => $qa->get_slot()));
|
||||
|
@ -954,6 +954,65 @@ abstract class question_utils {
|
||||
$text = str_replace('@@PLUGINFILE@@/', 'http://example.com/', $text);
|
||||
return html_to_text(format_text($text, $format, $options), 0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the options required to configure the filepicker for one of the editor
|
||||
* toolbar buttons.
|
||||
* @param mixed $acceptedtypes array of types of '*'.
|
||||
* @param int $draftitemid the draft area item id.
|
||||
* @param object $context the context.
|
||||
* @return object the required options.
|
||||
*/
|
||||
protected static function specific_filepicker_options($acceptedtypes, $draftitemid, $context) {
|
||||
$filepickeroptions = new stdClass();
|
||||
$filepickeroptions->accepted_types = $acceptedtypes;
|
||||
$filepickeroptions->return_types = FILE_INTERNAL | FILE_EXTERNAL;
|
||||
$filepickeroptions->context = $context;
|
||||
$filepickeroptions->env = 'filepicker';
|
||||
|
||||
$options = initialise_filepicker($filepickeroptions);
|
||||
$options->context = $context;
|
||||
$options->client_id = uniqid();
|
||||
$options->env = 'editor';
|
||||
$options->itemid = $draftitemid;
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get filepicker options for question related text areas.
|
||||
* @param object $context the context.
|
||||
* @param int $draftitemid the draft area item id.
|
||||
* @return array An array of options
|
||||
*/
|
||||
public static function get_filepicker_options($context, $draftitemid) {
|
||||
return [
|
||||
'image' => self::specific_filepicker_options(['image'], $draftitemid, $context),
|
||||
'media' => self::specific_filepicker_options(['video', 'audio'], $draftitemid, $context),
|
||||
'link' => self::specific_filepicker_options('*', $draftitemid, $context),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get editor options for question related text areas.
|
||||
* @param object $context the context.
|
||||
* @return array An array of options
|
||||
*/
|
||||
public static function get_editor_options($context) {
|
||||
global $CFG;
|
||||
|
||||
$editoroptions = [
|
||||
'subdirs' => 0,
|
||||
'context' => $context,
|
||||
'maxfiles' => EDITOR_UNLIMITED_FILES,
|
||||
'maxbytes' => $CFG->maxbytes,
|
||||
'noclean' => 0,
|
||||
'trusttext' => 0,
|
||||
'autosave' => false
|
||||
];
|
||||
|
||||
return $editoroptions;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1107,8 +1107,10 @@ class question_attempt {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new question_file_saver($draftitemid, 'question', 'response_' .
|
||||
str_replace($this->get_field_prefix(), '', $name), $text);
|
||||
$filearea = str_replace($this->get_field_prefix(), '', $name);
|
||||
$filearea = str_replace('-', 'bf_', $filearea);
|
||||
$filearea = 'response_' . $filearea;
|
||||
return new question_file_saver($draftitemid, 'question', $filearea, $text);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1164,6 +1166,8 @@ class question_attempt {
|
||||
$this->behaviour->get_expected_data(), $postdata, '-');
|
||||
|
||||
$expected = $this->behaviour->get_expected_qt_data();
|
||||
$this->check_qt_var_name_restrictions($expected);
|
||||
|
||||
if ($expected === self::USE_RAW_DATA) {
|
||||
$submitteddata += $this->get_all_submitted_qt_vars($postdata);
|
||||
} else {
|
||||
@ -1172,6 +1176,23 @@ class question_attempt {
|
||||
return $submitteddata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that no reserved prefixes are being used by installed
|
||||
* question types.
|
||||
* @param array $expected An array of question type variables
|
||||
*/
|
||||
protected function check_qt_var_name_restrictions($expected) {
|
||||
global $CFG;
|
||||
|
||||
if ($CFG->debugdeveloper) {
|
||||
foreach ($expected as $key => $value) {
|
||||
if (strpos($key, 'bf_') !== false) {
|
||||
debugging('The bf_ prefix is reserved and cannot be used by question types', DEBUG_DEVELOPER);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a set of response data for this question attempt that would get the
|
||||
* best possible mark. If it is not possible to compute a correct
|
||||
@ -1370,16 +1391,17 @@ class question_attempt {
|
||||
|
||||
/**
|
||||
* @return array(string, int) the most recent manual comment that was added
|
||||
* to this question, and the FORMAT_... it is.
|
||||
* to this question, the FORMAT_... it is and the step itself.
|
||||
*/
|
||||
public function get_manual_comment() {
|
||||
foreach ($this->get_reverse_step_iterator() as $step) {
|
||||
if ($step->has_behaviour_var('comment')) {
|
||||
return array($step->get_behaviour_var('comment'),
|
||||
$step->get_behaviour_var('commentformat'));
|
||||
$step->get_behaviour_var('commentformat'),
|
||||
$step);
|
||||
}
|
||||
}
|
||||
return array(null, null);
|
||||
return array(null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1399,7 +1421,7 @@ class question_attempt {
|
||||
if ($commentformat === null) {
|
||||
$commentformat = FORMAT_HTML;
|
||||
}
|
||||
return array($comment, $commentformat);
|
||||
return array($comment, $commentformat, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -358,28 +358,27 @@ class qtype_essay_format_editorfilepicker_renderer extends qtype_essay_format_ed
|
||||
$name, $context->id, $step->get_qt_var($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get editor options for question response text area.
|
||||
* @param object $context the context the attempt belongs to.
|
||||
* @return array options for the editor.
|
||||
*/
|
||||
protected function get_editor_options($context) {
|
||||
// Disable the text-editor autosave because quiz has it's own auto save function.
|
||||
return array(
|
||||
'subdirs' => 0,
|
||||
'maxbytes' => 0,
|
||||
'maxfiles' => -1,
|
||||
'context' => $context,
|
||||
'noclean' => 0,
|
||||
'trusttext'=> 0,
|
||||
'autosave' => false
|
||||
);
|
||||
return question_utils::get_editor_options($context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the options required to configure the filepicker for one of the editor
|
||||
* toolbar buttons.
|
||||
* @deprecated since 3.5
|
||||
* @param mixed $acceptedtypes array of types of '*'.
|
||||
* @param int $draftitemid the draft area item id.
|
||||
* @param object $context the context.
|
||||
* @return object the required options.
|
||||
*/
|
||||
protected function specific_filepicker_options($acceptedtypes, $draftitemid, $context) {
|
||||
debugging('specific_filepicker_options() is deprecated, use get_filepicker_options instead.', DEBUG_DEVELOPER);
|
||||
|
||||
$filepickeroptions = new stdClass();
|
||||
$filepickeroptions->accepted_types = $acceptedtypes;
|
||||
$filepickeroptions->return_types = FILE_INTERNAL | FILE_EXTERNAL;
|
||||
@ -395,17 +394,13 @@ class qtype_essay_format_editorfilepicker_renderer extends qtype_essay_format_ed
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object $context the context the attempt belongs to.
|
||||
* @param int $draftitemid draft item id.
|
||||
* @return array filepicker options for the editor.
|
||||
*/
|
||||
protected function get_filepicker_options($context, $draftitemid) {
|
||||
global $CFG;
|
||||
|
||||
return array(
|
||||
'image' => $this->specific_filepicker_options(array('image'),
|
||||
$draftitemid, $context),
|
||||
'media' => $this->specific_filepicker_options(array('video', 'audio'),
|
||||
$draftitemid, $context),
|
||||
'link' => $this->specific_filepicker_options('*',
|
||||
$draftitemid, $context),
|
||||
);
|
||||
return question_utils::get_filepicker_options($context, $draftitemid);
|
||||
}
|
||||
|
||||
protected function filepicker_html($inputname, $draftitemid) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user