Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Defines the editing form for the drag-and-drop images onto images question type. 19 * 20 * @package qtype_ddmarker 21 * @copyright 2012 The Open University 22 * @author Jamie Pratt <me@jamiep.org> 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 require_once($CFG->dirroot.'/question/type/ddimageortext/edit_ddtoimage_form_base.php'); 30 require_once($CFG->dirroot.'/question/type/ddmarker/shapes.php'); 31 32 define('QTYPE_DDMARKER_ALLOWED_TAGS_IN_MARKER', '<br><i><em><b><strong><sup><sub><u><span>'); 33 34 35 /** 36 * Drag-and-drop images onto images editing form definition. 37 * 38 * @copyright 2009 The Open University 39 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 40 */ 41 class qtype_ddmarker_edit_form extends qtype_ddtoimage_edit_form_base { 42 public function qtype() { 43 return 'ddmarker'; 44 } 45 46 protected function definition_inner($mform) { 47 $mform->addElement('advcheckbox', 'showmisplaced', get_string('showmisplaced', 'qtype_ddmarker')); 48 $mform->setDefault('showmisplaced', $this->get_default_value('showmisplaced', 0)); 49 parent::definition_inner($mform); 50 51 $mform->addHelpButton('drops[0]', 'dropzones', 'qtype_ddmarker'); 52 } 53 54 public function js_call() { 55 global $PAGE; 56 $PAGE->requires->js_call_amd('qtype_ddmarker/form', 'init'); 57 } 58 59 60 protected function definition_draggable_items($mform, $itemrepeatsatstart) { 61 $mform->addElement('header', 'draggableitemheader', 62 get_string('markers', 'qtype_ddmarker')); 63 $mform->addElement('advcheckbox', 'shuffleanswers', get_string('shuffleimages', 'qtype_'.$this->qtype())); 64 $mform->setDefault('shuffleanswers', $this->get_default_value('shuffleanswers', 0)); 65 $this->repeat_elements($this->draggable_item($mform), $itemrepeatsatstart, 66 $this->draggable_items_repeated_options(), 67 'noitems', 'additems', self::ADD_NUM_ITEMS, 68 get_string('addmoreitems', 'qtype_ddmarker'), true); 69 } 70 71 protected function draggable_item($mform) { 72 $draggableimageitem = array(); 73 74 $grouparray = array(); 75 $grouparray[] = $mform->createElement('text', 'label', '', 76 array('size' => 30, 'class' => 'tweakcss')); 77 $mform->setType('text', PARAM_RAW_TRIMMED); 78 79 $noofdragoptions = array(0 => get_string('infinite', 'qtype_ddmarker')); 80 foreach (range(1, 6) as $option) { 81 $noofdragoptions[$option] = $option; 82 } 83 $grouparray[] = $mform->createElement('select', 'noofdrags', get_string('noofdrags', 'qtype_ddmarker'), $noofdragoptions); 84 85 $draggableimageitem[] = $mform->createElement('group', 'drags', 86 get_string('marker_n', 'qtype_ddmarker'), $grouparray); 87 return $draggableimageitem; 88 } 89 90 protected function draggable_items_repeated_options() { 91 $repeatedoptions = array(); 92 $repeatedoptions['drags[label]']['type'] = PARAM_RAW; 93 return $repeatedoptions; 94 } 95 96 protected function drop_zone($mform, $imagerepeats) { 97 $grouparray = array(); 98 $shapearray = qtype_ddmarker_shape::shape_options(); 99 $grouparray[] = $mform->createElement('select', 'shape', 100 get_string('shape', 'qtype_ddmarker'), $shapearray); 101 $markernos = array(); 102 $markernos[0] = ''; 103 for ($i = 1; $i <= $imagerepeats; $i += 1) { 104 $markernos[$i] = $i; 105 } 106 $grouparray[] = $mform->createElement('select', 'choice', 107 get_string('marker', 'qtype_ddmarker'), $markernos); 108 $grouparray[] = $mform->createElement('text', 'coords', 109 get_string('coords', 'qtype_ddmarker'), 110 array('size' => 30, 'class' => 'tweakcss')); 111 $mform->setType('coords', PARAM_RAW); // These are validated manually. 112 $dropzone = $mform->createElement('group', 'drops', 113 get_string('dropzone', 'qtype_ddmarker', '{no}'), $grouparray); 114 return array($dropzone); 115 } 116 117 protected function drop_zones_repeated_options() { 118 $repeatedoptions = array(); 119 $repeatedoptions['drops[coords]']['type'] = PARAM_RAW; 120 return $repeatedoptions; 121 } 122 123 protected function get_hint_fields($withclearwrong = false, $withshownumpartscorrect = false) { 124 $mform = $this->_form; 125 126 $repeated = array(); 127 $repeated[] = $mform->createElement('editor', 'hint', get_string('hintn', 'question'), 128 array('rows' => 5), $this->editoroptions); 129 $repeatedoptions['hint']['type'] = PARAM_RAW; 130 131 $repeated[] = $mform->createElement('checkbox', 'hintshownumcorrect', 132 get_string('options', 'question'), 133 get_string('shownumpartscorrect', 'question')); 134 $repeated[] = $mform->createElement('checkbox', 'hintoptions', 135 '', 136 get_string('stateincorrectlyplaced', 'qtype_ddmarker')); 137 $repeated[] = $mform->createElement('checkbox', 'hintclearwrong', 138 '', 139 get_string('clearwrongparts', 'qtype_ddmarker')); 140 141 return array($repeated, $repeatedoptions); 142 } 143 144 public function data_preprocessing($question) { 145 146 $question = parent::data_preprocessing($question); 147 $question = $this->data_preprocessing_combined_feedback($question, true); 148 $question = $this->data_preprocessing_hints($question, true, true); 149 150 $dragids = array(); // Drag no -> dragid. 151 if (!empty($question->options)) { 152 $question->shuffleanswers = $question->options->shuffleanswers; 153 $question->showmisplaced = $question->options->showmisplaced; 154 $question->drags = array(); 155 foreach ($question->options->drags as $drag) { 156 $dragindex = $drag->no - 1; 157 $question->drags[$dragindex] = array(); 158 $question->drags[$dragindex]['label'] = $drag->label; 159 if ($drag->infinite == 1) { 160 $question->drags[$dragindex]['noofdrags'] = 0; 161 } else { 162 $question->drags[$dragindex]['noofdrags'] = $drag->noofdrags; 163 } 164 $dragids[$dragindex] = $drag->id; 165 } 166 $question->drops = array(); 167 foreach ($question->options->drops as $drop) { 168 $droparray = (array)$drop; 169 unset($droparray['id']); 170 unset($droparray['no']); 171 unset($droparray['questionid']); 172 $question->drops[$drop->no - 1] = $droparray; 173 } 174 } 175 // Initialise file picker for bgimage. 176 $draftitemid = file_get_submitted_draft_itemid('bgimage'); 177 178 file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddmarker', 179 'bgimage', !empty($question->id) ? (int) $question->id : null, 180 self::file_picker_options()); 181 $question->bgimage = $draftitemid; 182 183 $this->js_call(); 184 185 return $question; 186 } 187 188 /** 189 * Perform the necessary preprocessing for the hint fields. 190 * 191 * @param object $question The data being passed to the form. 192 * @param bool $withclearwrong Clear wrong hints. 193 * @param bool $withshownumpartscorrect Show number correct. 194 * @return object The modified data. 195 */ 196 protected function data_preprocessing_hints($question, $withclearwrong = false, 197 $withshownumpartscorrect = false) { 198 if (empty($question->hints)) { 199 return $question; 200 } 201 parent::data_preprocessing_hints($question, $withclearwrong, $withshownumpartscorrect); 202 203 $question->hintoptions = array(); 204 foreach ($question->hints as $hint) { 205 $question->hintoptions[] = $hint->options; 206 } 207 208 return $question; 209 } 210 211 public function validation($data, $files) { 212 $errors = parent::validation($data, $files); 213 $bgimagesize = $this->get_image_size_in_draft_area($data['bgimage']); 214 if ($bgimagesize === null) { 215 $errors["bgimage"] = get_string('formerror_nobgimage', 'qtype_ddmarker'); 216 } 217 218 for ($i = 0; $i < $data['nodropzone']; $i++) { 219 $choice = $data['drops'][$i]['choice']; 220 $choicepresent = ($choice !== '0'); 221 222 if ($choicepresent) { 223 // Test coords here. 224 if ($bgimagesize !== null) { 225 $shape = $data['drops'][$i]['shape']; 226 $coordsstring = $data['drops'][$i]['coords']; 227 $shapeobj = qtype_ddmarker_shape::create($shape, $coordsstring); 228 $interpretererror = $shapeobj->get_coords_interpreter_error(); 229 if ($interpretererror !== false) { 230 $errors["drops[{$i}]"] = $interpretererror; 231 } else if (!$shapeobj->inside_width_height($bgimagesize)) { 232 $errorcode = 'shapeoutsideboundsofbgimage'; 233 $errors["drops[{$i}]"] = 234 get_string('formerror_'.$errorcode, 'qtype_ddmarker'); 235 } 236 } 237 } else { 238 if (trim($data['drops'][$i]['coords']) !== '') { 239 $errorcode = 'noitemselected'; 240 $errors["drops[{$i}]"] = get_string('formerror_'.$errorcode, 'qtype_ddmarker'); 241 } 242 } 243 244 } 245 for ($dragindex = 0; $dragindex < $data['noitems']; $dragindex++) { 246 $label = $data['drags'][$dragindex]['label']; 247 if ($label != strip_tags($label, QTYPE_DDMARKER_ALLOWED_TAGS_IN_MARKER)) { 248 $errors["drags[{$dragindex}]"] 249 = get_string('formerror_onlysometagsallowed', 'qtype_ddmarker', 250 s(QTYPE_DDMARKER_ALLOWED_TAGS_IN_MARKER)); 251 } 252 } 253 return $errors; 254 } 255 256 /** 257 * Gets the width and height of a draft image. 258 * 259 * @param int $draftitemid ID of the draft image 260 * @return array Return array of the width and height of the draft image. 261 */ 262 public function get_image_size_in_draft_area($draftitemid) { 263 global $USER; 264 $usercontext = context_user::instance($USER->id); 265 $fs = get_file_storage(); 266 $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftitemid, 'id'); 267 if ($draftfiles) { 268 foreach ($draftfiles as $file) { 269 if ($file->is_directory()) { 270 continue; 271 } 272 // Just return the data for the first good file, there should only be one. 273 $imageinfo = $file->get_imageinfo(); 274 $width = $imageinfo['width']; 275 $height = $imageinfo['height']; 276 return array($width, $height); 277 } 278 } 279 return null; 280 } 281 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body