diff --git a/question/type/ddmarker/edit_ddmarker_form.php b/question/type/ddmarker/edit_ddmarker_form.php
index cb4fdee4d1b..dcb0bb32128 100644
--- a/question/type/ddmarker/edit_ddmarker_form.php
+++ b/question/type/ddmarker/edit_ddmarker_form.php
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+require_once($CFG->dirroot.'/question/type/ddimageortext/edit_ddtoimage_form_base.php');
+
/**
* Defines the editing form for the drag-and-drop images onto images question type.
*
@@ -31,351 +33,7 @@ defined('MOODLE_INTERNAL') || die();
* @copyright 2009 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class qtype_ddmarker_edit_form extends question_edit_form {
- const MAX_GROUPS = 8;
- const START_NUM_ITEMS = 6;
- const ADD_NUM_ITEMS = 3;
-
- public function qtype() {
- return 'ddmarker';
- }
-
- /**
- *
- * Options shared by all file pickers in the form.
- */
- public static function file_picker_options() {
- $filepickeroptions = array();
- $filepickeroptions['accepted_types'] = array('web_image');
- $filepickeroptions['maxbytes'] = 0;
- $filepickeroptions['maxfiles'] = 1;
- $filepickeroptions['subdirs'] = 0;
- return $filepickeroptions;
- }
-
- protected function get_drag_image_repeats() {
- $countimages = 0;
- if (isset($this->question->id)) {
- foreach ($this->question->options->drags as $drag) {
- $countimages = max($countimages, $drag->no);
- }
- }
- if ($this->question->formoptions->repeatelements) {
- $imagerepeatsatstart = max(self::START_NUM_ITEMS, $countimages + self::ADD_NUM_ITEMS);
- } else {
- $imagerepeatsatstart = $countimages;
- }
- $imagerepeats = optional_param('noitems', $imagerepeatsatstart, PARAM_INT);
- $addfields = optional_param('additems', '', PARAM_TEXT);
- if (!empty($addfields)) {
- $imagerepeats += self::ADD_NUM_ITEMS;
- }
- return array($imagerepeatsatstart, $imagerepeats);
- }
-
- /**
- * definition_inner adds all specific fields to the form.
- * @param object $mform (the form being built).
- */
- protected function definition_inner($mform) {
-
- $mform->addElement('header', 'previewareaheader',
- get_string('previewareaheader', 'qtype_ddmarker'));
- $mform->addElement('static', 'previewarea',
- get_string('previewarea', 'qtype_ddmarker'),
- get_string('previewareamessage', 'qtype_ddmarker'));
-
- $mform->registerNoSubmitButton('refresh');
- $mform->addElement('submit', 'refresh', get_string('refresh', 'qtype_ddmarker'));
- $mform->closeHeaderBefore('refresh');
-
- list($imagerepeatsatstart, $imagerepeats) = $this->get_drag_image_repeats();
- $this->definition_drop_zones($mform, $imagerepeats);
- $mform->addElement('advcheckbox', 'shuffleanswers', ' ',
- get_string('shuffleimages', 'qtype_ddmarker'));
- $mform->setDefault('shuffleanswers', 0);
- $mform->closeHeaderBefore('shuffleanswers');
- //add the draggable image fields to the form
- $this->definition_draggable_images($mform, $imagerepeatsatstart);
-
- $this->add_combined_feedback_fields(true);
- $this->add_interactive_settings(true, true);
- }
-
- protected function definition_drop_zones($mform, $imagerepeats) {
- $mform->addElement('header', 'dropzoneheader',
- get_string('dropzoneheader', 'qtype_ddmarker'));
-
- $mform->addElement('filepicker', 'bgimage', get_string('bgimage', 'qtype_ddmarker'),
- null, self::file_picker_options());
-
- $countdropzones = 0;
- if (isset($this->question->id)) {
- foreach ($this->question->options->drops as $drop) {
- $countdropzones = max($countdropzones, $drop->no);
- }
- }
- if ($this->question->formoptions->repeatelements) {
- $dropzonerepeatsatstart = max(self::START_NUM_ITEMS,
- $countdropzones + self::ADD_NUM_ITEMS);
- } else {
- $dropzonerepeatsatstart = $countdropzones;
- }
-
- $this->repeat_elements($this->drop_zone($mform, $imagerepeats), $dropzonerepeatsatstart,
- $this->drop_zones_repeated_options(),
- 'nodropzone', 'adddropzone', self::ADD_NUM_ITEMS,
- get_string('addmoredropzones', 'qtype_ddmarker'));
- }
-
- protected function drop_zone($mform, $imagerepeats) {
- $dropzoneitem = array();
-
- $grouparray = array();
- $grouparray[] = $mform->createElement('static', 'xleftlabel', '',
- ' '.get_string('xleft', 'qtype_ddmarker').' ');
- $grouparray[] = $mform->createElement('text', 'xleft',
- get_string('xleft', 'qtype_ddmarker'),
- array('size'=>5, 'class'=>'tweakcss'));
- $mform->setType('xleft', PARAM_NOTAGS);
- $grouparray[] = $mform->createElement('static', 'ytoplabel', '',
- ' '.get_string('ytop', 'qtype_ddmarker').' ');
- $grouparray[] = $mform->createElement('text', 'ytop',
- get_string('ytop', 'qtype_ddmarker'),
- array('size'=>5, 'class'=>'tweakcss'));
- $mform->setType('ytop', PARAM_NOTAGS);
- $options = array();
-
- $options[0] = '';
- for ($i = 1; $i <= $imagerepeats; $i += 1) {
- $options[$i] = $i;
- }
- $grouparray[] = $mform->createElement('static', '', '', ' ' .
- get_string('draggableitem', 'qtype_ddmarker').' ');
- $grouparray[] = $mform->createElement('select', 'choice',
- get_string('draggableitem', 'qtype_ddmarker'), $options);
- $grouparray[] = $mform->createElement('static', '', '', ' ' .
- get_string('label', 'qtype_ddmarker').' ');
- $grouparray[] = $mform->createElement('text', 'droplabel',
- get_string('label', 'qtype_ddmarker'),
- array('size'=>10, 'class'=>'tweakcss'));
- $mform->setType('droplabel', PARAM_NOTAGS);
- $dropzone = $mform->createElement('group', 'drops',
- get_string('dropzone', 'qtype_ddmarker', '{no}'), $grouparray);
- return array($dropzone);
- }
-
- protected function drop_zones_repeated_options() {
- $repeatedoptions = array();
- $repeatedoptions['choice']['default'] = '0';
- return $repeatedoptions;
- }
-
- protected function definition_draggable_images($mform, $imagerepeatsatstart) {
-
- $this->repeat_elements($this->draggable_image($mform), $imagerepeatsatstart,
- $this->draggable_images_repeated_options(),
- 'noitems', 'additems', self::ADD_NUM_ITEMS,
- get_string('addmoreimages', 'qtype_ddmarker'));
- }
-
- protected function draggable_image($mform) {
- $draggableimageitem = array();
-
- $draggableimageitem[] = $mform->createElement('header', 'draggableitemheader',
- get_string('draggableitemheader', 'qtype_ddmarker', '{no}'));
- $dragitemtypes = array('image' => get_string('draggableimage', 'qtype_ddmarker'),
- 'word' => get_string('draggableword', 'qtype_ddmarker'));
- $draggableimageitem[] = $mform->createElement('select', 'dragitemtype',
- get_string('draggableitemtype', 'qtype_ddmarker'),
- $dragitemtypes,
- array('class' => 'dragitemtype'));
- $draggableimageitem[] = $mform->createElement('filepicker', 'dragitem', '', null,
- self::file_picker_options());
-
- $grouparray = array();
- $grouparray[] = $mform->createElement('text', 'draglabel',
- get_string('label', 'qtype_ddmarker'),
- array('size'=>30, 'class'=>'tweakcss'));
- $mform->setType('draglabel', PARAM_NOTAGS);
- $options = array();
- for ($i = 1; $i <= self::MAX_GROUPS; $i += 1) {
- $options[$i] = $i;
- }
- $grouparray[] = $mform->createElement('static', '', '', ' ' .
- get_string('group', 'qtype_gapselect').' ');
- $grouparray[] = $mform->createElement('select', 'draggroup',
- get_string('group', 'qtype_gapselect'),
- $options,
- array('class' => 'draggroup'));
- $grouparray[] = $mform->createElement('advcheckbox', 'infinite', ' ',
- get_string('infinite', 'qtype_ddmarker'));
- $draggableimageitem[] = $mform->createElement('group', 'drags',
- get_string('label', 'qtype_ddmarker'), $grouparray);
- return $draggableimageitem;
- }
-
- protected function draggable_images_repeated_options() {
- $repeatedoptions = array();
- $repeatedoptions['draggroup']['default'] = '1';
- return $repeatedoptions;
- }
-
- public function data_preprocessing($question) {
- global $PAGE;
-
- $question = parent::data_preprocessing($question);
- $question = $this->data_preprocessing_combined_feedback($question, true);
- $question = $this->data_preprocessing_hints($question, true, true);
-
- $dragids = array(); // drag no -> dragid
- if (!empty($question->options)) {
- $question->shuffleanswers = $question->options->shuffleanswers;
- $question->drags = array();
- foreach ($question->options->drags as $drag) {
- $dragindex = $drag->no -1;
- $question->drags[$dragindex] = array();
- $question->drags[$dragindex]['draglabel'] = $drag->label;
- $question->drags[$dragindex]['infinite'] = $drag->infinite;
- $question->drags[$dragindex]['draggroup'] = $drag->draggroup;
- $dragids[$dragindex] = $drag->id;
- }
- $question->drops = array();
- foreach ($question->options->drops as $drop) {
- $question->drops[$drop->no -1] = array();
- $question->drops[$drop->no -1]['choice'] = $drop->choice;
- $question->drops[$drop->no -1]['droplabel'] = $drop->label;
- $question->drops[$drop->no -1]['xleft'] = $drop->xleft;
- $question->drops[$drop->no -1]['ytop'] = $drop->ytop;
- }
- }
- //initialise file picker for bgimage
- $draftitemid = file_get_submitted_draft_itemid('bgimage');
-
- file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddmarker',
- 'bgimage', !empty($question->id) ? (int) $question->id : null,
- self::file_picker_options());
- $question->bgimage = $draftitemid;
-
- //initialise file picker for dragimages
- list(, $imagerepeats) = $this->get_drag_image_repeats();
- $draftitemids = optional_param_array('dragitem', array(), PARAM_INT);
- for ($imageindex = 0; $imageindex < $imagerepeats; $imageindex++) {
- $draftitemid = isset($draftitemids[$imageindex]) ? $draftitemids[$imageindex] :0;
- //numbers not allowed in filearea name
- $itemid = isset($dragids[$imageindex]) ? $dragids[$imageindex] : null;
- file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddmarker',
- 'dragimage', $itemid, self::file_picker_options());
- $question->dragitem[$imageindex] = $draftitemid;
- }
- if (!empty($question->options)) {
- foreach ($question->options->drags as $drag) {
- $dragindex = $drag->no -1;
- if (!isset($question->dragitem[$dragindex])) {
- $fileexists = false;
- } else {
- $fileexists = self::file_uploaded($question->dragitem[$dragindex]);
- }
- $labelexists = $question->drags[$dragindex]['draglabel'];
- if ($labelexists && !$fileexists) {
- $question->dragitemtype[$dragindex] = 'word';
- } else {
- $question->dragitemtype[$dragindex] = 'image';
- }
- }
- }
- $maxsizes =new stdClass();
- $maxsizes->bgimage = new stdClass();
- $maxsizes->bgimage->width = QTYPE_ddmarker_BGIMAGE_MAXWIDTH;
- $maxsizes->bgimage->height = QTYPE_ddmarker_BGIMAGE_MAXHEIGHT;
- $maxsizes->dragimage = new stdClass();
- $maxsizes->dragimage->width = QTYPE_ddmarker_DRAGIMAGE_MAXWIDTH;
- $maxsizes->dragimage->height = QTYPE_ddmarker_DRAGIMAGE_MAXHEIGHT;
-
- $params = array('maxsizes' => $maxsizes,
- 'topnode' => 'fieldset#previewareaheader');
-
- $PAGE->requires->yui_module('moodle-qtype_ddmarker-form',
- 'M.qtype_ddmarker.init_form',
- array($params));
- return $question;
- }
-
-
- public static function file_uploaded($draftitemid) {
- $draftareafiles = file_get_drafarea_files($draftitemid);
- do {
- $draftareafile = array_shift($draftareafiles->list);
- } while ($draftareafile !== null && $draftareafile->filename == '.');
- if ($draftareafile === null) {
- return false;
- }
- return true;
- }
-
- public function validation($data, $files) {
- $errors = parent::validation($data, $files);
- if (!self::file_uploaded($data['bgimage'])) {
- $errors["bgimage"] = get_string('formerror_nobgimage', 'qtype_ddmarker');
- }
-
- $allchoices = array();
- for ($i=0; $i < $data['nodropzone']; $i++) {
- $ytoppresent = (trim($data['drops'][$i]['ytop']) !== '');
- $xleftpresent = (trim($data['drops'][$i]['ytop']) !== '');
- $labelpresent = (trim($data['drops'][$i]['droplabel']) !== '');
- $choice = $data['drops'][$i]['choice'];
- $imagechoicepresent = ($choice !== '0');
-
- if ($imagechoicepresent) {
- if (!$ytoppresent) {
- $errors["drops[$i]"] =
- get_string('formerror_noytop', 'qtype_ddmarker');
- }
- if (!$xleftpresent) {
- $errors["drops[$i]"] =
- get_string('formerror_noxleft', 'qtype_ddmarker');
- }
-
- if ($data['dragitemtype'][$choice - 1] != 'word' &&
- !self::file_uploaded($data['dragitem'][$choice - 1])) {
- $errors['dragitem['.($choice - 1).']'] =
- get_string('formerror_nofile', 'qtype_ddmarker', $i);
- }
-
- if (isset($allchoices[$choice]) && !$data['drags'][$choice-1]['infinite']) {
- $errors["drops[$i]"] =
- get_string('formerror_multipledraginstance', 'qtype_ddmarker', $choice);
- $errors['drops['.($allchoices[$choice]).']'] =
- get_string('formerror_multipledraginstance', 'qtype_ddmarker', $choice);
- $errors['drags['.($choice-1).']'] =
- get_string('formerror_multipledraginstance2', 'qtype_ddmarker', $choice);
- }
- $allchoices[$choice] = $i;
- } else {
- if ($ytoppresent || $xleftpresent || $labelpresent) {
- $errors["drops[$i]"] =
- get_string('formerror_noimageselected', 'qtype_ddmarker');
- }
- }
- }
- for ($dragindex=0; $dragindex < $data['noitems']; $dragindex++) {
- $label = $data['drags'][$dragindex]['draglabel'];
- if ($data['dragitemtype'][$dragindex] == 'word') {
- $allowedtags = '
';
- $errormessage = get_string('formerror_disallowedtags', 'qtype_ddmarker');
- } else {
- $allowedtags = '';
- $errormessage = get_string('formerror_noallowedtags', 'qtype_ddmarker');
- }
- if ($label != strip_tags($label, $allowedtags)) {
- $errors["drags[{$dragindex}]"] = $errormessage;
- }
-
- }
- return $errors;
- }
-
+class qtype_ddmarker_edit_form extends qtype_ddtoimage_edit_form_base {
}
diff --git a/question/type/ddmarker/lang/en/qtype_ddmarker.php b/question/type/ddmarker/lang/en/qtype_ddmarker.php
index 6695efdaac6..666ff349590 100644
--- a/question/type/ddmarker/lang/en/qtype_ddmarker.php
+++ b/question/type/ddmarker/lang/en/qtype_ddmarker.php
@@ -28,7 +28,7 @@ $string['addmoreimages'] = 'Blanks for {no} More Draggable Items';
$string['answer'] = 'Answer';
$string['bgimage'] = 'Background Image';
$string['correctansweris'] = 'The correct answer is: {$a}';
-$string['ddmarker'] = 'Drag and drop: images or text onto image';
+$string['ddmarker'] = 'Drag and drop: markers onto image';
$string['ddmarker_help'] = 'Select a background image file, select draggable images or enter text and define the drop zones on the background image to which they must be dragged.';
$string['ddmarkersummary'] = 'Images or text labels are dragged and dropped into drop zones on a background image.';
$string['draggableimage'] = 'Draggable image';
@@ -58,9 +58,7 @@ $string['previewareaheader'] = 'Preview';
$string['previewareamessage'] = 'Select a background image file and select draggable images or just enter text that will be made draggable. Then choose a drag item for each \'drop zone\', and drag the drag item to where the student should drag it to.';
$string['refresh'] = 'Refresh Preview';
$string['shuffleimages'] = 'Shuffle Drag Items Each Time Question Is Attempted';
-$string['summarisechoice'] = '{$a->no}. {$a->text}';
$string['summariseplace'] = '{$a->no}. {$a->text}';
-$string['summarisechoiceno'] = 'Item {$a}';
$string['summariseplaceno'] = 'Drop zone {$a}';
$string['xleft'] = 'Left';
$string['ytop'] = 'Top';
\ No newline at end of file
diff --git a/question/type/ddmarker/question.php b/question/type/ddmarker/question.php
index 54ca57b1af1..018815c5ece 100644
--- a/question/type/ddmarker/question.php
+++ b/question/type/ddmarker/question.php
@@ -26,7 +26,7 @@
defined('MOODLE_INTERNAL') || die();
-require_once($CFG->dirroot . '/question/type/gapselect/questionbase.php');
+require_once($CFG->dirroot . '/question/type/ddimageortext/questionbase.php');
/**
@@ -35,133 +35,13 @@ require_once($CFG->dirroot . '/question/type/gapselect/questionbase.php');
* @copyright 2009 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class qtype_ddmarker_question extends qtype_gapselect_question_base {
- public function clear_wrong_from_response(array $response) {
- foreach ($this->places as $place => $notused) {
- if (array_key_exists($this->field($place), $response) &&
- $response[$this->field($place)] != $this->get_right_choice_for($place)) {
- $response[$this->field($place)] = '';
- }
- }
- return $response;
- }
+class qtype_ddmarker_question extends qtype_ddtoimage_question_base {
- public function get_right_choice_for($placeno) {
- $place = $this->places[$placeno];
- foreach ($this->choiceorder[$place->group] as $choicekey => $choiceid) {
- if ($this->rightchoices[$placeno] == $choiceid) {
- return $choicekey;
- }
- }
- }
- public function summarise_response(array $response) {
- $allblank = true;
- foreach ($this->places as $placeno => $place) {
- $summariseplace = $place->summarise();
- if (array_key_exists($this->field($placeno), $response) &&
- $response[$this->field($placeno)]) {
- $selected = $this->get_selected_choice($place->group,
- $response[$this->field($placeno)]);
- $summarisechoice = $selected->summarise();
- $allblank = false;
- } else {
- $summarisechoice = '';
- }
- $choices[] = "$summariseplace -> {{$summarisechoice}}";
- }
- if ($allblank) {
- return null;
- }
- return implode(' ', $choices);
- }
-
- public function check_file_access($qa, $options, $component, $filearea, $args, $forcedownload) {
- if ($filearea == 'bgimage' || $filearea == 'dragimage') {
- $validfilearea = true;
- } else {
- $validfilearea = false;
- }
- if ($component == 'qtype_ddmarker' && $validfilearea) {
- $question = $qa->get_question();
- $itemid = reset($args);
- if ($filearea == 'bgimage') {
- return $itemid == $question->id;
- } else if ($filearea == 'dragimage') {
- foreach ($question->choices as $group) {
- foreach ($group as $drag) {
- if ($drag->id == $itemid) {
- return true;
- }
- }
- }
- return false;
- }
- } else {
- return parent::check_file_access($qa, $options, $component,
- $filearea, $args, $forcedownload);
- }
- }
- public function get_validation_error(array $response) {
- if ($this->is_complete_response($response)) {
- return '';
- }
- return get_string('pleasedraganimagetoeachdropregion', 'qtype_ddmarker');
- }
-
- public function classify_response(array $response) {
- $parts = array();
- foreach ($this->places as $placeno => $place) {
- $group = $place->group;
- if (!array_key_exists($this->field($placeno), $response) ||
- !$response[$this->field($placeno)]) {
- $parts[$placeno] = question_classified_response::no_response();
- continue;
- }
-
- $fieldname = $this->field($placeno);
- $choiceno = $this->choiceorder[$group][$response[$fieldname]];
- $choice = $this->choices[$group][$choiceno];
-
- $correct = $this->get_right_choice_for($placeno) == $response[$fieldname];
- $parts[$placeno] = new question_classified_response(
- $choiceno, $choice->summarise(), $correct?1:0);
- }
- return $parts;
- }
-
- public function get_random_guess_score() {
- $accum = 0;
-
- foreach ($this->places as $place) {
- $accum += 1 / count($this->choices[$place->group]);
- }
-
- return $accum / count($this->places);
- }
-
-
- public function get_question_summary() {
- $summary = '';
- if (!html_is_blank($this->questiontext)) {
- $question = $this->html_to_text($this->questiontext, $this->questiontextformat);
- $summary .= $question . '; ';
- }
- $places = array();
- foreach ($this->places as $place) {
- $cs = array();
- foreach ($this->choices[$place->group] as $choice) {
- $cs[] = $choice->summarise();
- }
- $places[] = '[[' . $place->summarise() . ']] -> {' . implode(' / ', $cs) . '}';
- }
- $summary .= implode('; ', $places);
- return $summary;
- }
}
/**
- * Represents one of the choices (draggable images).
+ * Represents one of the choices (draggable markers).
*
* @copyright 2009 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@@ -170,26 +50,18 @@ class qtype_ddmarker_drag_item {
public $id;
public $text;
public $no;
- public $group;
- public $isinfinite;
- public function __construct($alttextlabel, $no, $group = 1, $isinfinite = false, $id = 0) {
+ public function __construct($label, $no, $id = 0) {
$this->id = $id;
- $this->text = $alttextlabel;
+ $this->text = $label;
$this->no = $no;
- $this->group = $group;
- $this->isinfinite = $isinfinite;
}
public function choice_group() {
- return $this->group;
+ return 1;
}
public function summarise() {
- if (trim($this->text) != '') {
- return get_string('summarisechoice', 'qtype_ddmarker', $this);
- } else {
- return get_string('summarisechoiceno', 'qtype_ddmarker', $this->no);
- }
+ return $this->text;
}
}
/**
@@ -201,14 +73,14 @@ class qtype_ddmarker_drag_item {
class qtype_ddmarker_drop_zone {
public $no;
public $text;
- public $group;
- public $xy;
+ public $shape;
+ public $coords;
- public function __construct($alttextlabel, $no, $group = 1, $x = '', $y = '') {
+ public function __construct($label, $no, $shape, $coords) {
$this->no = $no;
- $this->text = $alttextlabel;
- $this->group = $group;
- $this->xy = array($x, $y);
+ $this->text = $label;
+ $this->shape = $shape;
+ $this->coords = $coords;
}
public function summarise() {
diff --git a/question/type/ddmarker/questiontype.php b/question/type/ddmarker/questiontype.php
index 106ca0f1b27..034ee131bd8 100644
--- a/question/type/ddmarker/questiontype.php
+++ b/question/type/ddmarker/questiontype.php
@@ -26,15 +26,10 @@
defined('MOODLE_INTERNAL') || die();
-require_once($CFG->libdir . '/questionlib.php');
-require_once($CFG->dirroot . '/question/engine/lib.php');
-require_once($CFG->dirroot . '/question/format/xml/format.php');
-require_once($CFG->dirroot . '/question/type/gapselect/questiontypebase.php');
+require_once($CFG->dirroot . '/question/type/ddimageortext/questiontypebase.php');
define('QTYPE_ddmarker_BGIMAGE_MAXWIDTH', 600);
define('QTYPE_ddmarker_BGIMAGE_MAXHEIGHT', 400);
-define('QTYPE_ddmarker_DRAGIMAGE_MAXWIDTH', 150);
-define('QTYPE_ddmarker_DRAGIMAGE_MAXHEIGHT', 100);
/**
* The drag-and-drop words into sentences question type class.
@@ -42,423 +37,10 @@ define('QTYPE_ddmarker_DRAGIMAGE_MAXHEIGHT', 100);
* @copyright 2009 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class qtype_ddmarker extends question_type {
- protected function choice_group_key() {
- return 'draggroup';
- }
+class qtype_ddmarker extends qtype_ddtoimage_base {
public function requires_qtypes() {
- return array('gapselect');
- }
-
- public function get_question_options($question) {
- global $DB;
- $question->options = $DB->get_record('qtype_ddmarker',
- array('questionid' => $question->id), '*', MUST_EXIST);
- $question->options->drags = $DB->get_records('qtype_ddmarker_drags',
- array('questionid' => $question->id), 'no ASC', '*');
- $question->options->drops = $DB->get_records('qtype_ddmarker_drops',
- array('questionid' => $question->id), 'no ASC', '*');
- parent::get_question_options($question);
- }
-
- protected function make_choice($dragdata) {
- return new qtype_ddmarker_drag_item($dragdata->label, $dragdata->no,
- $dragdata->draggroup, $dragdata->infinite, $dragdata->id);
- }
-
- protected function make_place($dropzonedata) {
- return new qtype_ddmarker_drop_zone($dropzonedata->label, $dropzonedata->no,
- $dropzonedata->group,
- $dropzonedata->xleft, $dropzonedata->ytop);
- }
-
- protected function make_hint($hint) {
- return question_hint_with_parts::load_from_record($hint);
- }
-
- protected function initialise_question_instance(question_definition $question, $questiondata) {
- parent::initialise_question_instance($question, $questiondata);
- $question->shufflechoices = $questiondata->options->shuffleanswers;
-
- $this->initialise_combined_feedback($question, $questiondata, true);
-
- $question->choices = array();
- $choiceindexmap= array();
-
- // Store the choices in arrays by group.
- foreach ($questiondata->options->drags as $dragdata) {
-
- $choice = $this->make_choice($dragdata);
-
- if (array_key_exists($choice->choice_group(), $question->choices)) {
- $question->choices[$choice->choice_group()][$dragdata->no] = $choice;
- } else {
- $question->choices[$choice->choice_group()][1] = $choice;
- }
-
- end($question->choices[$choice->choice_group()]);
- $choiceindexmap[$dragdata->no] = array($choice->choice_group(),
- key($question->choices[$choice->choice_group()]));
- }
-
- $question->places = array();
- $question->rightchoices = array();
-
- $i = 1;
-
- foreach ($questiondata->options->drops as $dropdata) {
- list($group, $choiceindex) = $choiceindexmap[$dropdata->choice];
- $dropdata->group = $group;
- $question->places[$dropdata->no] = $this->make_place($dropdata);
- $question->rightchoices[$dropdata->no] = $choiceindex;
- }
- }
-
- public function save_question_options($formdata) {
- global $DB, $USER;
- $context = $formdata->context;
-
- $options = $DB->get_record('qtype_ddmarker', array('questionid' => $formdata->id));
- if (!$options) {
- $options = new stdClass();
- $options->questionid = $formdata->id;
- $options->correctfeedback = '';
- $options->partiallycorrectfeedback = '';
- $options->incorrectfeedback = '';
- $options->id = $DB->insert_record('qtype_ddmarker', $options);
- }
-
- $options->shuffleanswers = !empty($formdata->shuffleanswers);
- $options = $this->save_combined_feedback_helper($options, $formdata, $context, true);
- $this->save_hints($formdata, true);
- $DB->update_record('qtype_ddmarker', $options);
- $DB->delete_records('qtype_ddmarker_drops', array('questionid' => $formdata->id));
- foreach (array_keys($formdata->drops) as $dropno) {
- if ($formdata->drops[$dropno]['choice'] == 0) {
- continue;
- }
- $drop = new stdClass();
- $drop->questionid = $formdata->id;
- $drop->no = $dropno + 1;
- $drop->xleft = $formdata->drops[$dropno]['xleft'];
- $drop->ytop = $formdata->drops[$dropno]['ytop'];
- $drop->choice = $formdata->drops[$dropno]['choice'];
- $drop->label = $formdata->drops[$dropno]['droplabel'];
-
- $DB->insert_record('qtype_ddmarker_drops', $drop);
- }
-
- //an array of drag no -> drag id
- $olddragids = $DB->get_records_menu('qtype_ddmarker_drags',
- array('questionid' => $formdata->id),
- '', 'no, id');
- foreach (array_keys($formdata->drags) as $dragno) {
- $info = file_get_draft_area_info($formdata->dragitem[$dragno]);
- if ($info['filecount'] > 0 || !empty($formdata->drags[$dragno]['draglabel'])) {
- $draftitemid = $formdata->dragitem[$dragno];
-
- $drag = new stdClass();
- $drag->questionid = $formdata->id;
- $drag->no = $dragno + 1;
- $drag->draggroup = $formdata->drags[$dragno]['draggroup'];
- $drag->infinite = empty($formdata->drags[$dragno]['infinite'])? 0 : 1;
- $drag->label = $formdata->drags[$dragno]['draglabel'];
-
- if (isset($olddragids[$dragno +1])) {
- $drag->id = $olddragids[$dragno +1];
- unset($olddragids[$dragno +1]);
- $DB->update_record('qtype_ddmarker_drags', $drag);
- } else {
- $drag->id = $DB->insert_record('qtype_ddmarker_drags', $drag);
- }
-
- if ($formdata->dragitemtype[$dragno] == 'image') {
- self::constrain_image_size_in_draft_area($draftitemid,
- QTYPE_ddmarker_DRAGIMAGE_MAXWIDTH,
- QTYPE_ddmarker_DRAGIMAGE_MAXHEIGHT);
- file_save_draft_area_files($draftitemid, $formdata->context->id,
- 'qtype_ddmarker', 'dragimage', $drag->id,
- array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1));
- } else {
- //delete any existing files for draggable text item type
- $fs = get_file_storage();
- $fs->delete_area_files($formdata->context->id, 'qtype_ddmarker',
- 'dragimage', $drag->id);
- }
-
- }
-
- }
- if (!empty($olddragids)) {
- list($sql, $params) = $DB->get_in_or_equal(array_values($olddragids));
- $DB->delete_records_select('qtype_ddmarker_drags', "id $sql", $params);
- }
-
- self::constrain_image_size_in_draft_area($formdata->bgimage,
- QTYPE_ddmarker_BGIMAGE_MAXWIDTH,
- QTYPE_ddmarker_BGIMAGE_MAXHEIGHT);
- file_save_draft_area_files($formdata->bgimage, $formdata->context->id,
- 'qtype_ddmarker', 'bgimage', $formdata->id,
- array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1));
- }
-
-
- public static function constrain_image_size_in_draft_area($draftitemid, $maxwidth, $maxheight) {
- global $USER;
- $usercontext = get_context_instance(CONTEXT_USER, $USER->id);
- $fs = get_file_storage();
- $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftitemid, 'id');
- if ($draftfiles) {
- foreach ($draftfiles as $file) {
- if ($file->is_directory()) {
- continue;
- }
- $imageinfo = $file->get_imageinfo();
- $width = $imageinfo['width'];
- $height = $imageinfo['height'];
- $mimetype = $imageinfo['mimetype'];
- switch ($mimetype) {
- case 'image/jpeg' :
- $quality = 80;
- break;
- case 'image/png' :
- $quality = 8;
- break;
- default :
- $quality = null;
- }
- $newwidth = min($maxwidth, $width);
- $newheight = min($maxheight, $height);
- if ($newwidth != $width || $newheight != $height) {
- $newimagefilename = $file->get_filename();
- $newimagefilename =
- preg_replace('!\.!', "_{$newwidth}x{$newheight}.", $newimagefilename, 1);
- $newrecord = new stdClass();
- $newrecord->contextid = $usercontext->id;
- $newrecord->component = 'user';
- $newrecord->filearea = 'draft';
- $newrecord->itemid = $draftitemid;
- $newrecord->filepath = '/';
- $newrecord->filename = $newimagefilename;
- $fs->convert_image($newrecord, $file, $newwidth, $newheight, true, $quality);
- $file->delete();
- }
- }
- }
- }
- public function move_files($questionid, $oldcontextid, $newcontextid) {
- global $DB;
- $fs = get_file_storage();
-
- parent::move_files($questionid, $oldcontextid, $newcontextid);
- $fs->move_area_files_to_new_context($oldcontextid,
- $newcontextid, 'qtype_ddmarker', 'bgimage', $questionid);
- $dragids = $DB->get_records_menu('qtype_ddmarker_drags',
- array('questionid' => $questionid), 'id', 'id,1');
- foreach ($dragids as $dragid => $notused) {
- $fs->move_area_files_to_new_context($oldcontextid,
- $newcontextid, 'qtype_ddmarker', 'dragimage', $dragid);
- }
-
- $this->move_files_in_combined_feedback($questionid, $oldcontextid, $newcontextid);
- }
-
- /**
- * Delete all the files belonging to this question.
- * @param int $questionid the question being deleted.
- * @param int $contextid the context the question is in.
- */
-
- protected function delete_files($questionid, $contextid) {
- global $DB;
- $fs = get_file_storage();
-
- parent::delete_files($questionid, $contextid);
-
- $dragids = $DB->get_records_menu('qtype_ddmarker_drags',
- array('questionid' => $questionid), 'id', 'id,1');
- foreach ($dragids as $dragid => $notused) {
- $fs->delete_area_files($contextid, 'qtype_ddmarker', 'dragimage', $dragid);
- }
-
- $this->delete_files_in_combined_feedback($questionid, $contextid);
- }
-
- public function export_to_xml($question, $format, $extra = null) {
- $fs = get_file_storage();
- $contextid = $question->contextid;
- $output = '';
-
- if ($question->options->shuffleanswers) {
- $output .= " \n";
- }
- $output .= $format->write_combined_feedback($question->options);
- $output .= $format->write_hints($question);
- $files = $fs->get_area_files($contextid, 'qtype_ddmarker', 'bgimage', $question->id);
- $output .= " ".$this->write_files($files, 2)."\n";;
-
- foreach ($question->options->drags as $drag) {
- $files =
- $fs->get_area_files($contextid, 'qtype_ddmarker', 'dragimage', $drag->id);
- $output .= " \n";
- $output .= " {$drag->no}\n";
- $output .= $format->writetext($drag->label, 3)."\n";
- $output .= " {$drag->draggroup}\n";
- if ($drag->infinite) {
- $output .= " \n";
- }
- $output .= $this->write_files($files, 3);
- $output .= " \n";
- }
- foreach ($question->options->drops as $drop) {
- $output .= " \n";
- $output .= $format->writetext($drop->label, 3);
- $output .= " {$drop->no}\n";
- $output .= " {$drop->choice}\n";
- $output .= " {$drop->xleft}\n";
- $output .= " {$drop->ytop}\n";
- $output .= " \n";
- }
-
- return $output;
- }
-
- public function import_from_xml($data, $question, $format, $extra=null) {
- if (!isset($data['@']['type']) || $data['@']['type'] != 'ddmarker') {
- return false;
- }
-
- $question = $format->import_headers($data);
- $question->qtype = 'ddmarker';
-
- $question->shuffleanswers = array_key_exists('shuffleanswers',
- $format->getpath($data, array('#'), array()));
-
- $filexml = $format->getpath($data, array('#', 'file'), array());
- $question->bgimage = $this->import_files_to_draft_file_area($format, $filexml);
- $drags = $data['#']['drag'];
- $question->drags = array();
-
- foreach ($drags as $dragxml) {
- $dragno = $format->getpath($dragxml, array('#', 'no', 0, '#'), 0);
- $dragindex = $dragno -1;
- $question->drags[$dragindex] = array();
- $question->drags[$dragindex]['draglabel'] =
- $format->getpath($dragxml, array('#', 'text', 0, '#'), '', true);
- $question->drags[$dragindex]['infinite'] = array_key_exists('infinite', $dragxml['#']);
- $question->drags[$dragindex]['draggroup'] =
- $format->getpath($dragxml, array('#', 'draggroup', 0, '#'), 1);
- $filexml = $format->getpath($dragxml, array('#', 'file'), array());
- $question->dragitem[$dragindex] =
- $this->import_files_to_draft_file_area($format, $filexml);
- if (count($filexml)) {
- $question->dragitemtype[$dragindex] = 'image';
- } else {
- $question->dragitemtype[$dragindex] = 'word';
- }
- }
-
- $drops = $data['#']['drop'];
- $question->drops = array();
- foreach ($drops as $dropxml) {
- $dropno = $format->getpath($dropxml, array('#', 'no', 0, '#'), 0);
- $dropindex = $dropno -1;
- $question->drops[$dropindex] = array();
- $question->drops[$dropindex]['choice'] =
- $format->getpath($dropxml, array('#', 'choice', 0, '#'), 0);
- $question->drops[$dropindex]['droplabel'] =
- $format->getpath($dropxml, array('#', 'text', 0, '#'), '', true);
- $question->drops[$dropindex]['xleft'] =
- $format->getpath($dropxml, array('#', 'xleft', 0, '#'), '');
- $question->drops[$dropindex]['ytop'] =
- $format->getpath($dropxml, array('#', 'ytop', 0, '#'), '');
- }
-
- $format->import_combined_feedback($question, $data, true);
- $format->import_hints($question, $data, true);
-
- return $question;
- }
-
-
- /**
- * Create a draft files area, import files into it and return the draft item id.
- * @param qformat_xml $format
- * @param array $xml an array of nodes from the the parsed XML.
- * @return integer draftitemid
- */
- public function import_files_to_draft_file_area($format, $xml) {
- global $USER;
- $fs = get_file_storage();
- $files = $format->import_files($xml);
- $usercontext = get_context_instance(CONTEXT_USER, $USER->id);
- $draftitemid = file_get_unused_draft_itemid();
- foreach ($files as $file) {
- $record = new stdClass();
- $record->contextid = $usercontext->id;
- $record->component = 'user';
- $record->filearea = 'draft';
- $record->itemid = $draftitemid;
- $record->filename = $file->name;
- $record->filepath = '/';
- $fs->create_file_from_string($record, $this->decode_file($file));
- }
- return $draftitemid;
- }
-
- /**
- * Convert files into text output in the given format.
- * This method is copied from qformat_default as a quick fix, as the method there is
- * protected.
- * @param array
- * @param string encoding method
- * @return string $string
- */
- public function write_files($files, $indent) {
- if (empty($files)) {
- return '';
- }
- $string = '';
- foreach ($files as $file) {
- if ($file->is_directory()) {
- continue;
- }
- $string .= str_repeat(' ', $indent);
- $string .= '';
- $string .= base64_encode($file->get_content());
- $string .= "\n";
- }
- return $string;
- }
-
- public function get_possible_responses($questiondata) {
- $question = $this->make_question($questiondata);
-
- $parts = array();
- foreach ($question->places as $placeno => $place) {
- $group = $place->group;
- $choices = array();
-
- foreach ($question->choices[$group] as $i => $choice) {
- $summarisechoice = $choice->summarise();
-
- $correct = $question->rightchoices[$placeno] == $i;
- $choices[$choice->no] = new question_possible_response(
- $summarisechoice,
- $correct?1:0);
- }
- $choices[null] = question_possible_response::no_response();
-
- $parts[$placeno] = $choices;
- }
-
- return $parts;
- }
-
- public function get_random_guess_score($questiondata) {
- $question = $this->make_question($questiondata);
- return $question->get_random_guess_score();
+ return array_merge(parent::requires_qtypes(), array('ddimageortext'));
}
}
diff --git a/question/type/ddmarker/renderer.php b/question/type/ddmarker/renderer.php
index da83b871c60..f7cf56007f2 100644
--- a/question/type/ddmarker/renderer.php
+++ b/question/type/ddmarker/renderer.php
@@ -26,7 +26,7 @@
defined('MOODLE_INTERNAL') || die();
-require_once($CFG->dirroot . '/question/type/gapselect/rendererbase.php');
+require_once($CFG->dirroot . '/question/type/ddimageortext/rendererbase.php');
/**
@@ -35,146 +35,6 @@ require_once($CFG->dirroot . '/question/type/gapselect/rendererbase.php');
* @copyright 2010 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class qtype_ddmarker_renderer extends qtype_with_combined_feedback_renderer {
+class qtype_ddmarker_renderer extends qtype_ddtoimage_renderer_base {
- public function head_code(question_attempt $qa) {
- return parent::head_code($qa);
- }
- public function clear_wrong(question_attempt $qa) {
- $question = $qa->get_question();
- $response = $qa->get_last_qt_data();
-
- if (!empty($response)) {
- $cleanresponse = $question->clear_wrong_from_response($response);
- } else {
- $cleanresponse = $response;
- }
- $cleanresponsehtml = '';
- foreach ($cleanresponse as $fieldname => $value) {
- list (, $html) = $this->hidden_field_for_qt_var($qa, $fieldname, $value);
- $cleanresponsehtml .= $html;
- }
- return $cleanresponsehtml;
- }
-
- public function formulation_and_controls(question_attempt $qa,
- question_display_options $options) {
- global $PAGE;
-
- $question = $qa->get_question();
- $response = $qa->get_last_qt_data();
-
- $questiontext = $question->format_questiontext($qa);
-
- $output = html_writer::tag('div', $questiontext, array('class' => 'qtext'));
-
- $bgimage = self::get_url_for_image($qa, 'bgimage');
-
- $img = html_writer::empty_tag('img', array('src'=>$bgimage, 'class'=>'dropbackground'));
- $droparea = html_writer::tag('div', $img, array('class'=>'droparea'));
-
- $dragimagehomes = '';
- foreach ($question->choices as $groupno => $group) {
- $dragimagehomesgroup = '';
- $orderedgroup = $question->get_ordered_choices($groupno);
- foreach ($orderedgroup as $choiceno => $dragimage) {
- $dragimageurl = self::get_url_for_image($qa, 'dragimage', $dragimage->id);
- $classes = array("group{$groupno}",
- 'draghome',
- "dragitemhomes{$dragimage->no}",
- "choice{$choiceno}");
- if ($dragimage->isinfinite) {
- $classes[] = 'infinite';
- }
- if ($dragimageurl === null) {
- $classes[] = 'yui3-cssfonts';
- $dragimagehomesgroup .= html_writer::tag('div',
- $dragimage->text,
- array('src'=>$dragimageurl,
- 'class'=>join(' ', $classes)));
- } else {
- $dragimagehomesgroup .= html_writer::empty_tag('img',
- array('src'=>$dragimageurl,
- 'alt' => $dragimage->text,
- 'class'=>join(' ', $classes)));
- }
- }
- $dragimagehomes .= html_writer::tag('div', $dragimagehomesgroup,
- array('class'=>'dragitemgroup'.$groupno));
- }
-
- $dragitemsclass = 'dragitems';
- if ($options->readonly) {
- $dragitemsclass .= ' readonly';
- }
- $dragitems = html_writer::tag('div', $dragimagehomes, array('class'=> $dragitemsclass));
- $dropzones = html_writer::empty_tag('div', array('class'=>'dropzones'));
- $output .= html_writer::tag('div', $droparea.$dragitems.$dropzones,
- array('class'=>'ddarea'));
- foreach ($question->places as $placeno => $place) {
- $varname = $question->field($placeno);
- list($fieldname, $html) = $this->hidden_field_for_qt_var($qa, $varname);
- $output .= $html;
- $question->places[$placeno]->fieldname = $fieldname;
- }
- $topnode = 'div#q'.$qa->get_slot().' div.ddarea';
- $params = array('drops' => $question->places,
- 'topnode' => $topnode,
- 'readonly' => $options->readonly);
-
- $PAGE->requires->yui_module('moodle-qtype_ddmarker-dd',
- 'M.qtype_ddmarker.init_question',
- array($params));
-
- if ($qa->get_state() == question_state::$invalid) {
- $output .= html_writer::nonempty_tag('div',
- $question->get_validation_error($qa->get_last_qt_data()),
- array('class' => 'validationerror'));
- }
- return $output;
- }
-
- protected static function get_url_for_image(question_attempt $qa, $filearea, $itemid = 0) {
- $question = $qa->get_question();
- $qubaid = $qa->get_usage_id();
- $slot = $qa->get_slot();
- $fs = get_file_storage();
- if ($filearea == 'bgimage') {
- $itemid = $question->id;
- }
- $draftfiles = $fs->get_area_files($question->contextid, 'qtype_ddmarker',
- $filearea, $itemid, 'id');
- if ($draftfiles) {
- foreach ($draftfiles as $file) {
- if ($file->is_directory()) {
- continue;
- }
- $url = moodle_url::make_pluginfile_url($question->contextid, 'qtype_ddmarker',
- $filearea, "$qubaid/$slot/{$itemid}", '/',
- $file->get_filename());
- return $url->out();
- }
- }
- return null;
- }
-
- protected function hidden_field_for_qt_var(question_attempt $qa, $varname, $value = null) {
- if ($value === null) {
- $value = $qa->get_last_qt_var($varname);
- }
- $fieldname = $qa->get_qt_field_name($varname);
- $attributes = array('type' => 'hidden',
- 'id' => str_replace(':', '_', $fieldname),
- 'name' => $fieldname,
- 'value' => $value);
- return array($fieldname, html_writer::empty_tag('input', $attributes)."\n");
- }
-
- public function specific_feedback(question_attempt $qa) {
- return $this->combined_feedback($qa);
- }
-
- public function correct_response(question_attempt $qa) {
- return '';
- }
}