MDL-79863 qtype_ordering: qtype/ordering allow full HTML editors on answers in order to allow images and pictures

This commit is contained in:
Gordon Bateson 2015-11-18 18:56:38 +09:00 committed by Mathew May
parent 072c95122b
commit b71ca209ce
6 changed files with 147 additions and 22 deletions

View File

@ -36,14 +36,14 @@ defined('MOODLE_INTERNAL') || die();
*/
class qtype_ordering_edit_form extends question_edit_form {
const NUM_ANS_ROWS = 2;
const NUM_ANS_ROWS = 2;
const NUM_ANS_COLS = 60;
const NUM_ANS_START = 6;
const NUM_ANS_ADD = 2;
const NUM_ANS_START = 6;
const NUM_ANS_ADD = 3;
// this functionality is currently disabled
// because it is not fully functional
protected $use_editor_for_answers = false;
protected $use_editor_for_answers = true;
/**
* unique name for this question type
@ -112,6 +112,8 @@ class qtype_ordering_edit_form extends question_edit_form {
$label = get_string($name, $plugin);
if ($this->use_editor_for_answers) {
$elements[] = $mform->createElement('editor', $name, $label, $this->get_editor_attributes(), $this->get_editor_options());
$elements[] = $mform->createElement('submit', $name.'removeeditor', get_string('removeeditor', $plugin));
//$elements[] = $mform->createElement('submit', $name.'removeitem', get_string('removeitem', $plugin));
} else {
$elements[] = $mform->createElement('textarea', $name, $label, array('rows' => self::NUM_ANS_ROWS, 'cols' => self::NUM_ANS_COLS));
}
@ -128,6 +130,9 @@ class qtype_ordering_edit_form extends question_edit_form {
$buttontext = get_string('addmoreanswers', $plugin, self::NUM_ANS_ADD);
$this->repeat_elements($elements, $start, $options, 'countanswers', 'addanswers', self::NUM_ANS_ADD, $buttontext);
// adjust HTML editor and removal buttons
$this->adjust_html_editors($mform, $name);
// feedback
$this->add_ordering_feedback_fields(true);
@ -156,6 +161,66 @@ class qtype_ordering_edit_form extends question_edit_form {
);
}
/**
* adjust_html_editors
*/
protected function adjust_html_editors($mform, $name) {
// check whether or not we are using editors
if (! $this->use_editor_for_answers) {
return;
}
// cache the number of supported formats
// for the preferred editor for each format
$count = array();
$ids = array_keys($this->question->options->answers);
foreach ($ids as $i => $id) {
$editor = $name.'['.$i.']';
if (! $mform->elementExists($editor)) {
continue;
}
$editor = $mform->getElement($editor);
// the old/new name of the button to remove the HTML editor
// old : the name of the button when added by repeat_elements
// new : the simplified name of the button to satisfy
// "no_submit_button_pressed()" in lib/formslib.php
$oldname = $name.'removeeditor['.$i.']';
$newname = $name.'removeeditor_'.$i;
// remove HTML editor, if necessary
if (optional_param($newname, 0, PARAM_RAW)) {
$value = $editor->getValue();
$value['format'] = FORMAT_MOODLE;
$value = $editor->setValue($value);
$format = $editor->getFormat();
// override incoming format value
$_POST['answer'][$i]['format'] = $format;
} else {
$format = $this->question->options->answers[$id]->answerformat;
}
// check we have a submit button - it should always be there !!
if ($mform->elementExists($oldname)) {
if (! isset($count[$format])) {
$editor = editors_get_preferred_editor($format);
$count[$format] = $editor->get_supported_formats();
$count[$format] = count($count[$format]);
}
if ($count[$format] > 1) {
$mform->removeElement($oldname);
} else {
$submit = $mform->getElement($oldname);
$submit->setName($newname);
}
$mform->registerNoSubmitButton($newname);
}
}
}
/**
* data_preprocessing
*/
@ -174,20 +239,14 @@ class qtype_ordering_edit_form extends question_edit_form {
if (isset($question->options->answers)) {
$i = 0;
foreach ($question->options->answers as $answer) {
foreach ($question->options->answers as $answerid => $answer) {
if (trim($answer->answer)=='') {
continue; // skip empty answers
}
if ($this->use_editor_for_answers) {
$draftid = file_get_submitted_draft_itemid("answer[$i]");
if (isset($answer->id)) {
$itemid = $answer->id;
} else {
$itemid = null;
}
$itemid = file_get_submitted_draft_itemid("answer[$i]");
if (isset($answer->answer)) {
$text = $answer->answer;
@ -201,12 +260,12 @@ class qtype_ordering_edit_form extends question_edit_form {
$format = FORMAT_MOODLE;
}
$text = file_prepare_draft_area($draftid, $this->context->id, 'qtype_ordering',
'answer', $itemid, $this->editoroptions, $text);
$text = file_prepare_draft_area($itemid, $this->context->id, 'question', 'answer',
$answerid, $this->editoroptions, $text);
$question->answer[$i] = array('text' => $text,
'format' => $format,
'itemid' => $draftid);
'itemid' => $itemid);
} else {
$question->answer[$i]= $answer->answer;
}
@ -246,7 +305,7 @@ class qtype_ordering_edit_form extends question_edit_form {
$answercount = 0;
foreach ($data['answer'] as $answer){
if ($this->use_editor_for_answers) {
if (is_array($answer)) {
$answer = $answer['text'];
}
if (trim($answer)=='') {

View File

@ -25,6 +25,8 @@ $string['layouttype_help'] = 'Choose whether to display the items vertically or
$string['layouttype'] = 'Layout of items';
$string['noresponsedetails'] = 'Sorry, no details of the response to this question are available.';
$string['notenoughanswers'] = 'Ordering questions must have more than {$a} answers.';
$string['removeeditor'] = 'Remove HTML editor';
$string['removeitem'] = 'Remove draggable item';
$string['selectall'] = 'Select all items';
$string['selectcontiguous'] = 'Select a contiguous subset of items';
$string['selectcount_help'] = 'The number of items that will be displayed when the question is appears in a quiz.';

View File

@ -167,6 +167,24 @@ class qtype_ordering_question extends question_graded_automatically {
return array($fraction, question_state::graded_state_for_fraction($fraction));
}
public function check_file_access($qa, $options, $component, $filearea, $args, $forcedownload) {
if ($component=='question') {
if ($filearea=='answer') {
$answerid = reset($args); // "itemid" is answer id
return array_key_exists($answerid, $this->answers);
}
if (in_array($filearea, $this->qtype->feedback_fields)) {
return $this->check_combined_feedback_file_access($qa, $options, $filearea);
}
if ($filearea=='hint') {
return $this->check_hint_file_access($qa, $options, $args);
}
}
return parent::check_file_access($qa, $options, $component, $filearea, $args, $forcedownload);
}
////////////////////////////////////////////////////////////////////
// custom methods
////////////////////////////////////////////////////////////////////

View File

@ -115,6 +115,7 @@ class qtype_ordering extends question_type {
$result = new stdClass();
$context = $question->context;
//$context = $this->get_context_by_category_id($question->category);
// remove empty answers
$question->answer = array_filter($question->answer, array($this, 'is_not_blank'));
@ -123,6 +124,14 @@ class qtype_ordering extends question_type {
// count how many answers we have
$countanswers = count($question->answer);
// search/replace strings to reduce simple <p>...</p> to plain text
$p_search = '/^\s*<p>\s*(.*?)(\s*<br\s*\/?>)*\s*<\/p>\s*$/';
$p_replace = '$1';
// search/replace strings to standardize vertical align of <img> tags
$img_search = '/(<img[^>]*)\bvertical-align:\s*[a-zA-Z0-9_-]+([^>]*>)/';
$img_replace = '$1'.'vertical-align:text-top'.'$2';
// check at least two answers exist
if ($countanswers < 2) {
$result->notice = get_string('notenoughanswers', 'qtype_ordering', '2');
@ -138,16 +147,40 @@ class qtype_ordering extends question_type {
}
// Insert all the new answers
foreach ($question->answer as $i => $answer) {
// extract $answer fields
if (is_array($answer)) {
// editor
$answertext = $answer['text'];
$answerformat = $answer['format'];
$answeritemid = $answer['itemid'];
} else {
// textarea
$answertext = $answer;
$answerformat = FORMAT_MOODLE;
$answeritemid = 0; // i.e. no editor
}
// reduce simple <p>...</p> to plain text
if (substr_count($answertext, '<p>')==1) {
$answertext = preg_replace($p_search, $p_replace, $answertext);
}
// standardize vertical align of img tags
$answertext = preg_replace($img_search, $img_replace, $answertext);
// prepare the $answer object
$answer = (object)array(
'question' => $question->id,
'fraction' => ($i + 1), // start at 1
'answer' => (is_array($answer) ? $answer['text'] : $answer),
'answerformat' => (is_array($answer) ? $answer['format'] : FORMAT_MOODLE),
'answer' => $answertext,
'answerformat' => $answerformat,
'feedback' => '',
'feedbackformat' => FORMAT_MOODLE,
);
// add/insert $answer into the database
if ($answer->id = array_shift($answerids)) {
if (! $DB->update_record('question_answers', $answer)) {
$result->error = get_string('cannotupdaterecord', 'error', 'question_answers (id='.$answer->id.')');
@ -160,6 +193,14 @@ class qtype_ordering extends question_type {
return $result;
}
}
// copy files across from draft files area
// Note: we must do this AFTER inserting the answer record
// because the answer id is used as the file's "itemid"
if ($answeritemid) {
$answertext = file_save_draft_area_files($answeritemid, $context->id, 'question', 'answer', $answer->id, $this->fileoptions, $answertext);
$DB->set_field('question_answers', 'answer', $answertext, array('id' => $answer->id));
}
}
// create $options for this ordering question
@ -187,7 +228,11 @@ class qtype_ordering extends question_type {
// delete old answer records, if any
if (count($answerids)) {
$DB->delete_records_list('question_answers', 'id', $answerids);
$fs = get_file_storage();
foreach ($answerids as $answerid) {
$fs->delete_area_files($context->id, 'question', 'answer', $answerid);
$DB->delete_records('question_answers', array('id' => $answerid));
}
}
return true;

View File

@ -136,6 +136,7 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer {
// because $answer->fraction holds the correct order number
// $id = 'ordering_item_'.$answerid.'_'.intval($question->answers[$answerid]->fraction);
$answer = $question->answers[$answerid];
$answer->answer = $question->format_text($answer->answer, $answer->answerformat, $qa, 'question', 'answer', $answerid);
$params = array('class' => $class, 'id' => $answer->md5key);
$result .= html_writer::tag('li', $img.$answer->answer, $params);
}

View File

@ -30,6 +30,6 @@ defined('MOODLE_INTERNAL') || die();
$plugin->cron = 0;
$plugin->component = 'qtype_ordering';
$plugin->maturity = MATURITY_STABLE; // ALPHA=50, BETA=100, RC=150, STABLE=200
$plugin->release = '2015-11-15 (30)';
$plugin->version = 2015111530;
$plugin->release = '2015-11-18 (31)';
$plugin->version = 2015111831;
$plugin->requires = 2010112400; // Moodle 2.0