MDL-20636 Can now display the attachments to an essay question that has attachments.
This commit is contained in:
+78
-1
@@ -466,6 +466,11 @@ class question_display_options {
|
||||
*/
|
||||
public $history = self::HIDDEN;
|
||||
|
||||
/**
|
||||
* @var int the context the attempt being output belongs to.
|
||||
*/
|
||||
public $contextid;
|
||||
|
||||
/**
|
||||
* Set all the feedback-related fields {@link $feedback}, {@link generalfeedback},
|
||||
* {@link rightanswer} and {@link manualcomment} to
|
||||
@@ -916,6 +921,7 @@ class question_usage_by_activity {
|
||||
* @return string HTML fragment representing the question.
|
||||
*/
|
||||
public function render_question($slot, $options, $number = null) {
|
||||
$options->contextid = $this->context->id;
|
||||
return $this->get_question_attempt($slot)->render($options, $number);
|
||||
}
|
||||
|
||||
@@ -926,6 +932,7 @@ class question_usage_by_activity {
|
||||
* @return string HTML fragment.
|
||||
*/
|
||||
public function render_question_head_html($slot) {
|
||||
$options->contextid = $this->context->id;
|
||||
return $this->get_question_attempt($slot)->render_head_html();
|
||||
}
|
||||
|
||||
@@ -941,6 +948,7 @@ class question_usage_by_activity {
|
||||
* @return string HTML fragment representing the question.
|
||||
*/
|
||||
public function render_question_at_step($slot, $seq, $options, $number = null) {
|
||||
$options->contextid = $this->context->id;
|
||||
return $this->get_question_attempt($slot)->render_at_step($seq, $options, $number, $this->preferredbehaviour);
|
||||
}
|
||||
|
||||
@@ -1333,6 +1341,12 @@ class question_attempt {
|
||||
*/
|
||||
const PARAM_MARK = 'parammark';
|
||||
|
||||
/**
|
||||
* @var string special value used by manual grading because {@link PARAM_NUMBER}
|
||||
* converts '' to 0.
|
||||
*/
|
||||
const PARAM_FILES = 'paramfiles';
|
||||
|
||||
/** @var integer if this attempts is stored in the question_attempts table, the id of that row. */
|
||||
protected $id = null;
|
||||
|
||||
@@ -1666,6 +1680,39 @@ class question_attempt {
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest set of files for a particular question type variable of
|
||||
* type question_attempt::PARAM_FILES.
|
||||
*
|
||||
* @param string $name the name of the associated variable.
|
||||
* @return array of {@link stored_files}.
|
||||
*/
|
||||
public function get_last_qt_files($name, $contextid) {
|
||||
foreach ($this->get_reverse_step_iterator() as $step) {
|
||||
if ($step->has_qt_var($name)) {
|
||||
return $step->get_qt_files($name, $contextid);
|
||||
}
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL of a file that belongs to a response variable of this
|
||||
* question_attempt.
|
||||
* @param stored_file $file the file to link to.
|
||||
* @return string the URL of that file.
|
||||
*/
|
||||
public function get_response_file_url(stored_file $file) {
|
||||
return file_encode_url(new moodle_url('/pluginfile.php'), '/' . implode('/', array(
|
||||
$file->get_contextid(),
|
||||
$file->get_component(),
|
||||
$file->get_filearea(),
|
||||
$this->usageid,
|
||||
$this->slot,
|
||||
$file->get_itemid())) .
|
||||
$file->get_filepath() . $file->get_filename());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest value of a particular behaviour variable. That is,
|
||||
* get the value from the latest step that has it set. Return null if it is
|
||||
@@ -1997,9 +2044,11 @@ class question_attempt {
|
||||
} else {
|
||||
$var = null;
|
||||
}
|
||||
|
||||
if (is_string($var)) {
|
||||
$var = stripslashes($var);
|
||||
$var = $var;
|
||||
}
|
||||
|
||||
return $var;
|
||||
}
|
||||
|
||||
@@ -2488,6 +2537,9 @@ class question_attempt_step {
|
||||
/** @var array name => value pairs. The submitted data. */
|
||||
private $data;
|
||||
|
||||
/** @var array name => array of {@link stored_file}s. Caches the contents of file areas. */
|
||||
private $files = array();
|
||||
|
||||
/**
|
||||
* You should not need to call this constructor in your own code. Steps are
|
||||
* normally created by {@link question_attempt} methods like
|
||||
@@ -2582,6 +2634,30 @@ class question_attempt_step {
|
||||
$this->data[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest set of files for a particular question type variable of
|
||||
* type question_attempt::PARAM_FILES.
|
||||
*
|
||||
* @param string $name the name of the associated variable.
|
||||
* @return array of {@link stored_files}.
|
||||
*/
|
||||
public function get_qt_files($name, $contextid) {
|
||||
if (array_key_exists($name, $this->files)) {
|
||||
return $this->files[$name];
|
||||
}
|
||||
|
||||
if (!$this->has_qt_var($name)) {
|
||||
$this->files[$name] = array();
|
||||
return array();
|
||||
}
|
||||
|
||||
$fs = get_file_storage();
|
||||
$this->files[$name] = $fs->get_area_files($contextid, 'question',
|
||||
'response_' . $name, $this->id, 'sortorder', false);
|
||||
|
||||
return $this->files[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the question type variables.
|
||||
* @param array name => value pairs.
|
||||
@@ -2697,6 +2773,7 @@ class question_attempt_step {
|
||||
|
||||
$step = new question_attempt_step_read_only($data, $record->timecreated, $record->userid);
|
||||
$step->state = question_state::get($record->state);
|
||||
$step->id = $record->attemptstepid;
|
||||
if (!is_null($record->fraction)) {
|
||||
$step->fraction = $record->fraction + 0;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,11 @@ class qtype_essay_question extends question_with_responses {
|
||||
}
|
||||
|
||||
public function get_expected_data() {
|
||||
return array('answer' => PARAM_CLEANHTML);
|
||||
$expecteddata = array('answer' => PARAM_CLEANHTML);
|
||||
if ($this->attachments != 0) {
|
||||
$expecteddata['attachments'] = question_attempt::PARAM_FILES;
|
||||
}
|
||||
return $expecteddata;
|
||||
}
|
||||
|
||||
public function summarise_response(array $response) {
|
||||
@@ -80,4 +84,14 @@ class qtype_essay_question extends question_with_responses {
|
||||
return question_utils::arrays_same_at_key_missing_is_blank(
|
||||
$prevresponse, $newresponse, 'answer');
|
||||
}
|
||||
|
||||
public function check_file_access($qa, $options, $component, $filearea, $args, $forcedownload) {
|
||||
if ($component == 'question' && $filearea == 'response_attachments') {
|
||||
// Response attachments visible if the question has them.
|
||||
return $this->attachments != 0;
|
||||
|
||||
} else {
|
||||
return parent::check_file_access($qa, $options, $component, $filearea, $args, $forcedownload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ class qtype_essay_renderer extends qtype_renderer {
|
||||
$inputname = $qa->get_qt_field_name('answer');
|
||||
$response = $qa->get_last_qt_var('answer', '');
|
||||
if (empty($options->readonly)) {
|
||||
$answer =$responseoutput->response_area_input($inputname,
|
||||
$answer = $responseoutput->response_area_input($inputname,
|
||||
$response, $question->responsefieldlines);
|
||||
|
||||
} else {
|
||||
@@ -56,13 +56,13 @@ class qtype_essay_renderer extends qtype_renderer {
|
||||
$files = '';
|
||||
if (empty($options->readonly)) {
|
||||
if ($question->attachments == 1) {
|
||||
$files = $this->filepicker_input();
|
||||
$files = $this->filepicker_input($qa, $options);
|
||||
} else if ($question->attachments != 0) {
|
||||
$files = $this->filemanager_input();
|
||||
$files = $this->filemanager_input($qa, $options);
|
||||
}
|
||||
|
||||
} else if ($question->attachments != 0) {
|
||||
$files = $this->files_read_only();
|
||||
$files = $this->files_read_only($qa, $options);
|
||||
}
|
||||
|
||||
$result = '';
|
||||
@@ -71,6 +71,7 @@ class qtype_essay_renderer extends qtype_renderer {
|
||||
|
||||
$result .= html_writer::start_tag('div', array('class' => 'ablock'));
|
||||
$result .= html_writer::tag('div', $answer, array('class' => 'answer'));
|
||||
$result .= html_writer::tag('div', $files, array('class' => 'attachments'));
|
||||
$result .= html_writer::end_tag('div');
|
||||
|
||||
return $result;
|
||||
@@ -79,21 +80,30 @@ class qtype_essay_renderer extends qtype_renderer {
|
||||
/**
|
||||
* Displays any attached files when the question is in read-only mode.
|
||||
*/
|
||||
public function files_read_only() {
|
||||
return '';
|
||||
public function files_read_only(question_attempt $qa, question_display_options $options) {
|
||||
$files = $qa->get_last_qt_files('attachments', $options->contextid);
|
||||
$output = array();
|
||||
|
||||
foreach ($files as $file) {
|
||||
$mimetype = $file->get_mimetype();
|
||||
$output[] = html_writer::tag('p', html_writer::link($qa->get_response_file_url($file),
|
||||
$this->output->pix_icon(file_mimetype_icon($mimetype), $mimetype,
|
||||
'moodle', array('class' => 'icon')) . ' ' . s($file->get_filename())));
|
||||
}
|
||||
return implode($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the input control for when the student should upload a single file.
|
||||
*/
|
||||
public function filepicker_input() {
|
||||
public function filepicker_input(question_attempt $qa, question_display_options $options) {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the input control for when the student should upload a number of files.
|
||||
*/
|
||||
public function filemanager_input() {
|
||||
public function filemanager_input(question_attempt $qa, question_display_options $options) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,4 +11,5 @@
|
||||
}
|
||||
.que.essay .qtype_essay_response.qtype_essay_editor {
|
||||
background-color: white;
|
||||
min-height: 3em;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user