Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]
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 parent::definition_inner($mform); 49 50 $mform->addHelpButton('drops[0]', 'dropzones', 'qtype_ddmarker'); 51 } 52 53 public function js_call() { 54 global $PAGE; 55 $PAGE->requires->js_call_amd('qtype_ddmarker/form', 'init'); 56 } 57 58 59 protected function definition_draggable_items($mform, $itemrepeatsatstart) { 60 $mform->addElement('header', 'draggableitemheader', 61 get_string('markers', 'qtype_ddmarker')); 62 $mform->addElement('advcheckbox', 'shuffleanswers', get_string('shuffleimages', 'qtype_'.$this->qtype())); 63 $mform->setDefault('shuffleanswers', 0); 64 $this->repeat_elements($this->draggable_item($mform), $itemrepeatsatstart, 65 $this->draggable_items_repeated_options(), 66 'noitems', 'additems', self::ADD_NUM_ITEMS, 67 get_string('addmoreitems', 'qtype_ddmarker'), true); 68 } 69 70 protected function draggable_item($mform) { 71 $draggableimageitem = array(); 72 73 $grouparray = array(); 74 $grouparray[] = $mform->createElement('text', 'label', '', 75 array('size' => 30, 'class' => 'tweakcss')); 76 $mform->setType('text', PARAM_RAW_TRIMMED); 77 78 $noofdragoptions = array(0 => get_string('infinite', 'qtype_ddmarker')); 79 foreach (range(1, 6) as $option) { 80 $noofdragoptions[$option] = $option; 81 } 82 $grouparray[] = $mform->createElement('select', 'noofdrags', get_string('noofdrags', 'qtype_ddmarker'), $noofdragoptions); 83 84 $draggableimageitem[] = $mform->createElement('group', 'drags', 85 get_string('marker_n', 'qtype_ddmarker'), $grouparray); 86 return $draggableimageitem; 87 } 88 89 protected function draggable_items_repeated_options() { 90 $repeatedoptions = array(); 91 $repeatedoptions['drags[label]']['type'] = PARAM_RAW; 92 return $repeatedoptions; 93 } 94 95 protected function drop_zone($mform, $imagerepeats) { 96 $grouparray = array(); 97 $shapearray = qtype_ddmarker_shape::shape_options(); 98 $grouparray[] = $mform->createElement('select', 'shape', 99 get_string('shape', 'qtype_ddmarker'), $shapearray); 100 $markernos = array(); 101 $markernos[0] = ''; 102 for ($i = 1; $i <= $imagerepeats; $i += 1) { 103 $markernos[$i] = $i; 104 } 105 $grouparray[] = $mform->createElement('select', 'choice', 106 get_string('marker', 'qtype_ddmarker'), $markernos); 107 $grouparray[] = $mform->createElement('text', 'coords', 108 get_string('coords', 'qtype_ddmarker'), 109 array('size' => 30, 'class' => 'tweakcss')); 110 $mform->setType('coords', PARAM_RAW); // These are validated manually. 111 $dropzone = $mform->createElement('group', 'drops', 112 get_string('dropzone', 'qtype_ddmarker', '{no}'), $grouparray); 113 return array($dropzone); 114 } 115 116 protected function drop_zones_repeated_options() { 117 $repeatedoptions = array(); 118 $repeatedoptions['drops[coords]']['type'] = PARAM_RAW; 119 return $repeatedoptions; 120 } 121 122 protected function get_hint_fields($withclearwrong = false, $withshownumpartscorrect = false) { 123 $mform = $this->_form; 124 125 $repeated = array(); 126 $repeated[] = $mform->createElement('editor', 'hint', get_string('hintn', 'question'), 127 array('rows' => 5), $this->editoroptions); 128 $repeatedoptions['hint']['type'] = PARAM_RAW; 129 130 $repeated[] = $mform->createElement('checkbox', 'hintshownumcorrect', 131 get_string('options', 'question'), 132 get_string('shownumpartscorrect', 'question')); 133 $repeated[] = $mform->createElement('checkbox', 'hintoptions', 134 '', 135 get_string('stateincorrectlyplaced', 'qtype_ddmarker')); 136 $repeated[] = $mform->createElement('checkbox', 'hintclearwrong', 137 '', 138 get_string('clearwrongparts', 'qtype_ddmarker')); 139 140 return array($repeated, $repeatedoptions); 141 } 142 143 public function data_preprocessing($question) { 144 145 $question = parent::data_preprocessing($question); 146 $question = $this->data_preprocessing_combined_feedback($question, true); 147 $question = $this->data_preprocessing_hints($question, true, true); 148 149 $dragids = array(); // Drag no -> dragid. 150 if (!empty($question->options)) { 151 $question->shuffleanswers = $question->options->shuffleanswers; 152 $question->showmisplaced = $question->options->showmisplaced; 153 $question->drags = array(); 154 foreach ($question->options->drags as $drag) { 155 $dragindex = $drag->no - 1; 156 $question->drags[$dragindex] = array(); 157 $question->drags[$dragindex]['label'] = $drag->label; 158 if ($drag->infinite == 1) { 159 $question->drags[$dragindex]['noofdrags'] = 0; 160 } else { 161 $question->drags[$dragindex]['noofdrags'] = $drag->noofdrags; 162 } 163 $dragids[$dragindex] = $drag->id; 164 } 165 $question->drops = array(); 166 foreach ($question->options->drops as $drop) { 167 $droparray = (array)$drop; 168 unset($droparray['id']); 169 unset($droparray['no']); 170 unset($droparray['questionid']); 171 $question->drops[$drop->no - 1] = $droparray; 172 } 173 } 174 // Initialise file picker for bgimage. 175 $draftitemid = file_get_submitted_draft_itemid('bgimage'); 176 177 file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddmarker', 178 'bgimage', !empty($question->id) ? (int) $question->id : null, 179 self::file_picker_options()); 180 $question->bgimage = $draftitemid; 181 182 $this->js_call(); 183 184 return $question; 185 } 186 187 /** 188 * Perform the necessary preprocessing for the hint fields. 189 * 190 * @param object $question The data being passed to the form. 191 * @param bool $withclearwrong Clear wrong hints. 192 * @param bool $withshownumpartscorrect Show number correct. 193 * @return object The modified data. 194 */ 195 protected function data_preprocessing_hints($question, $withclearwrong = false, 196 $withshownumpartscorrect = false) { 197 if (empty($question->hints)) { 198 return $question; 199 } 200 parent::data_preprocessing_hints($question, $withclearwrong, $withshownumpartscorrect); 201 202 $question->hintoptions = array(); 203 foreach ($question->hints as $hint) { 204 $question->hintoptions[] = $hint->options; 205 } 206 207 return $question; 208 } 209 210 public function validation($data, $files) { 211 $errors = parent::validation($data, $files); 212 $bgimagesize = $this->get_image_size_in_draft_area($data['bgimage']); 213 if ($bgimagesize === null) { 214 $errors["bgimage"] = get_string('formerror_nobgimage', 'qtype_ddmarker'); 215 } 216 217 for ($i = 0; $i < $data['nodropzone']; $i++) { 218 $choice = $data['drops'][$i]['choice']; 219 $choicepresent = ($choice !== '0'); 220 221 if ($choicepresent) { 222 // Test coords here. 223 if ($bgimagesize !== null) { 224 $shape = $data['drops'][$i]['shape']; 225 $coordsstring = $data['drops'][$i]['coords']; 226 $shapeobj = qtype_ddmarker_shape::create($shape, $coordsstring); 227 $interpretererror = $shapeobj->get_coords_interpreter_error(); 228 if ($interpretererror !== false) { 229 $errors["drops[{$i}]"] = $interpretererror; 230 } else if (!$shapeobj->inside_width_height($bgimagesize)) { 231 $errorcode = 'shapeoutsideboundsofbgimage'; 232 $errors["drops[{$i}]"] = 233 get_string('formerror_'.$errorcode, 'qtype_ddmarker'); 234 } 235 } 236 } else { 237 if (trim($data['drops'][$i]['coords']) !== '') { 238 $errorcode = 'noitemselected'; 239 $errors["drops[{$i}]"] = get_string('formerror_'.$errorcode, 'qtype_ddmarker'); 240 } 241 } 242 243 } 244 for ($dragindex = 0; $dragindex < $data['noitems']; $dragindex++) { 245 $label = $data['drags'][$dragindex]['label']; 246 if ($label != strip_tags($label, QTYPE_DDMARKER_ALLOWED_TAGS_IN_MARKER)) { 247 $errors["drags[{$dragindex}]"] 248 = get_string('formerror_onlysometagsallowed', 'qtype_ddmarker', 249 s(QTYPE_DDMARKER_ALLOWED_TAGS_IN_MARKER)); 250 } 251 } 252 return $errors; 253 } 254 255 /** 256 * Gets the width and height of a draft image. 257 * 258 * @param int $draftitemid ID of the draft image 259 * @return array Return array of the width and height of the draft image. 260 */ 261 public function get_image_size_in_draft_area($draftitemid) { 262 global $USER; 263 $usercontext = context_user::instance($USER->id); 264 $fs = get_file_storage(); 265 $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftitemid, 'id'); 266 if ($draftfiles) { 267 foreach ($draftfiles as $file) { 268 if ($file->is_directory()) { 269 continue; 270 } 271 // Just return the data for the first good file, there should only be one. 272 $imageinfo = $file->get_imageinfo(); 273 $width = $imageinfo['width']; 274 $height = $imageinfo['height']; 275 return array($width, $height); 276 } 277 } 278 return null; 279 } 280 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body