Merge branch 'MDL-70248-310' of https://github.com/HuongNV13/moodle into MOODLE_310_S...
[moodle.git] / question / type / ddmarker / edit_ddmarker_form.php
CommitLineData
b3878dbd
JP
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 *
5263d6d7
TH
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
b3878dbd
JP
24 */
25
5263d6d7 26
b3878dbd
JP
27defined('MOODLE_INTERNAL') || die();
28
5263d6d7
TH
29require_once($CFG->dirroot.'/question/type/ddimageortext/edit_ddtoimage_form_base.php');
30require_once($CFG->dirroot.'/question/type/ddmarker/shapes.php');
31
096a5b99 32define('QTYPE_DDMARKER_ALLOWED_TAGS_IN_MARKER', '<br><i><em><b><strong><sup><sub><u><span>');
5263d6d7
TH
33
34
b3878dbd
JP
35/**
36 * Drag-and-drop images onto images editing form definition.
37 *
5263d6d7
TH
38 * @copyright 2009 The Open University
39 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
b3878dbd 40 */
dda954a2 41class qtype_ddmarker_edit_form extends qtype_ddtoimage_edit_form_base {
d2ac6cea
JP
42 public function qtype() {
43 return 'ddmarker';
44 }
45
46 protected function definition_inner($mform) {
47 $mform->addElement('advcheckbox', 'showmisplaced', ' ',
48 get_string('showmisplaced', 'qtype_ddmarker'));
49 parent::definition_inner($mform);
2870a500
TH
50
51 $mform->addHelpButton('drops[0]', 'dropzones', 'qtype_ddmarker');
d2ac6cea
JP
52 }
53
54 public function js_call() {
55 global $PAGE;
d0311165 56 $PAGE->requires->js_call_amd('qtype_ddmarker/form', 'init');
d2ac6cea
JP
57 }
58
8bc1d28b 59
d2ac6cea 60 protected function definition_draggable_items($mform, $itemrepeatsatstart) {
d2ac6cea
JP
61 $mform->addElement('header', 'draggableitemheader',
62 get_string('markers', 'qtype_ddmarker'));
26492f70
CC
63 $mform->addElement('advcheckbox', 'shuffleanswers', ' ',
64 get_string('shuffleimages', 'qtype_'.$this->qtype()));
65 $mform->setDefault('shuffleanswers', 0);
d2ac6cea
JP
66 $this->repeat_elements($this->draggable_item($mform), $itemrepeatsatstart,
67 $this->draggable_items_repeated_options(),
68 'noitems', 'additems', self::ADD_NUM_ITEMS,
26492f70 69 get_string('addmoreitems', 'qtype_ddmarker'), true);
d2ac6cea
JP
70 }
71
72 protected function draggable_item($mform) {
73 $draggableimageitem = array();
74
f8bb5fdc
TH
75 $grouparray = array();
76 $grouparray[] = $mform->createElement('text', 'label', '',
77 array('size' => 30, 'class' => 'tweakcss'));
d2ac6cea
JP
78 $mform->setType('text', PARAM_RAW_TRIMMED);
79
e1f5f601
JP
80 $noofdragoptions = array(0 => get_string('infinite', 'qtype_ddmarker'));
81 foreach (range(1, 6) as $option) {
82 $noofdragoptions[$option] = $option;
83 }
84 $grouparray[] = $mform->createElement('select', 'noofdrags', get_string('noofdrags', 'qtype_ddmarker'), $noofdragoptions);
85
d2ac6cea
JP
86 $draggableimageitem[] = $mform->createElement('group', 'drags',
87 get_string('marker_n', 'qtype_ddmarker'), $grouparray);
88 return $draggableimageitem;
89 }
90
91 protected function draggable_items_repeated_options() {
26492f70 92 $repeatedoptions = array();
eff03a8b 93 $repeatedoptions['drags[label]']['type'] = PARAM_RAW;
26492f70 94 return $repeatedoptions;
d2ac6cea
JP
95 }
96
d2ac6cea 97 protected function drop_zone($mform, $imagerepeats) {
d2ac6cea 98 $grouparray = array();
6f789d3d 99 $shapearray = qtype_ddmarker_shape::shape_options();
d2ac6cea 100 $grouparray[] = $mform->createElement('select', 'shape',
26492f70 101 get_string('shape', 'qtype_ddmarker'), $shapearray);
d2ac6cea
JP
102 $markernos = array();
103 $markernos[0] = '';
104 for ($i = 1; $i <= $imagerepeats; $i += 1) {
105 $markernos[$i] = $i;
106 }
d2ac6cea
JP
107 $grouparray[] = $mform->createElement('select', 'choice',
108 get_string('marker', 'qtype_ddmarker'), $markernos);
5d4b3421
JB
109 $grouparray[] = $mform->createElement('text', 'coords',
110 get_string('coords', 'qtype_ddmarker'),
111 array('size' => 30, 'class' => 'tweakcss'));
112 $mform->setType('coords', PARAM_RAW); // These are validated manually.
d2ac6cea
JP
113 $dropzone = $mform->createElement('group', 'drops',
114 get_string('dropzone', 'qtype_ddmarker', '{no}'), $grouparray);
115 return array($dropzone);
116 }
117
118 protected function drop_zones_repeated_options() {
119 $repeatedoptions = array();
eff03a8b 120 $repeatedoptions['drops[coords]']['type'] = PARAM_RAW;
d2ac6cea
JP
121 return $repeatedoptions;
122 }
123
124 protected function get_hint_fields($withclearwrong = false, $withshownumpartscorrect = false) {
125 $mform = $this->_form;
126
127 $repeated = array();
80f02993 128 $repeated[] = $mform->createElement('editor', 'hint', get_string('hintn', 'question'),
d2ac6cea
JP
129 array('rows' => 5), $this->editoroptions);
130 $repeatedoptions['hint']['type'] = PARAM_RAW;
131
132 $repeated[] = $mform->createElement('checkbox', 'hintshownumcorrect',
133 get_string('options', 'question'),
134 get_string('shownumpartscorrect', 'question'));
fd1be85c 135 $repeated[] = $mform->createElement('checkbox', 'hintoptions',
d2ac6cea
JP
136 '',
137 get_string('stateincorrectlyplaced', 'qtype_ddmarker'));
138 $repeated[] = $mform->createElement('checkbox', 'hintclearwrong',
139 '',
140 get_string('clearwrongparts', 'qtype_ddmarker'));
141
142 return array($repeated, $repeatedoptions);
143 }
144
145 public function data_preprocessing($question) {
146
147 $question = parent::data_preprocessing($question);
148 $question = $this->data_preprocessing_combined_feedback($question, true);
326d8f8d 149 $question = $this->data_preprocessing_hints($question, true, true);
d2ac6cea 150
5263d6d7 151 $dragids = array(); // Drag no -> dragid.
d2ac6cea
JP
152 if (!empty($question->options)) {
153 $question->shuffleanswers = $question->options->shuffleanswers;
154 $question->showmisplaced = $question->options->showmisplaced;
155 $question->drags = array();
156 foreach ($question->options->drags as $drag) {
f8bb5fdc 157 $dragindex = $drag->no - 1;
d2ac6cea
JP
158 $question->drags[$dragindex] = array();
159 $question->drags[$dragindex]['label'] = $drag->label;
e1f5f601
JP
160 if ($drag->infinite == 1) {
161 $question->drags[$dragindex]['noofdrags'] = 0;
162 } else {
163 $question->drags[$dragindex]['noofdrags'] = $drag->noofdrags;
164 }
d2ac6cea
JP
165 $dragids[$dragindex] = $drag->id;
166 }
167 $question->drops = array();
168 foreach ($question->options->drops as $drop) {
169 $droparray = (array)$drop;
170 unset($droparray['id']);
171 unset($droparray['no']);
172 unset($droparray['questionid']);
f8bb5fdc 173 $question->drops[$drop->no - 1] = $droparray;
d2ac6cea
JP
174 }
175 }
5263d6d7 176 // Initialise file picker for bgimage.
d2ac6cea
JP
177 $draftitemid = file_get_submitted_draft_itemid('bgimage');
178
179 file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddmarker',
180 'bgimage', !empty($question->id) ? (int) $question->id : null,
181 self::file_picker_options());
182 $question->bgimage = $draftitemid;
183
6a69507b 184 $this->js_call();
d2ac6cea
JP
185
186 return $question;
187 }
8bc1d28b 188
d2ac6cea
JP
189 /**
190 * Perform the necessary preprocessing for the hint fields.
8bc1d28b
EM
191 *
192 * @param object $question The data being passed to the form.
193 * @param bool $withclearwrong Clear wrong hints.
194 * @param bool $withshownumpartscorrect Show number correct.
195 * @return object The modified data.
d2ac6cea 196 */
326d8f8d
JP
197 protected function data_preprocessing_hints($question, $withclearwrong = false,
198 $withshownumpartscorrect = false) {
d2ac6cea
JP
199 if (empty($question->hints)) {
200 return $question;
201 }
326d8f8d 202 parent::data_preprocessing_hints($question, $withclearwrong, $withshownumpartscorrect);
d2ac6cea
JP
203
204 $question->hintoptions = array();
205 foreach ($question->hints as $hint) {
fd1be85c 206 $question->hintoptions[] = $hint->options;
d2ac6cea
JP
207 }
208
209 return $question;
210 }
211
212 public function validation($data, $files) {
213 $errors = parent::validation($data, $files);
8aae74a4
JP
214 $bgimagesize = $this->get_image_size_in_draft_area($data['bgimage']);
215 if ($bgimagesize === null) {
d2ac6cea
JP
216 $errors["bgimage"] = get_string('formerror_nobgimage', 'qtype_ddmarker');
217 }
218
f8bb5fdc 219 for ($i = 0; $i < $data['nodropzone']; $i++) {
d2ac6cea
JP
220 $choice = $data['drops'][$i]['choice'];
221 $choicepresent = ($choice !== '0');
222
223 if ($choicepresent) {
5263d6d7 224 // Test coords here.
8aae74a4 225 if ($bgimagesize !== null) {
6f789d3d
JP
226 $shape = $data['drops'][$i]['shape'];
227 $coordsstring = $data['drops'][$i]['coords'];
228 $shapeobj = qtype_ddmarker_shape::create($shape, $coordsstring);
229 $interpretererror = $shapeobj->get_coords_interpreter_error();
33164c04 230 if ($interpretererror !== false) {
6f789d3d
JP
231 $errors["drops[{$i}]"] = $interpretererror;
232 } else if (!$shapeobj->inside_width_height($bgimagesize)) {
233 $errorcode = 'shapeoutsideboundsofbgimage';
234 $errors["drops[{$i}]"] =
235 get_string('formerror_'.$errorcode, 'qtype_ddmarker');
8aae74a4
JP
236 }
237 }
d2ac6cea
JP
238 } else {
239 if (trim($data['drops'][$i]['coords']) !== '') {
6f789d3d
JP
240 $errorcode = 'noitemselected';
241 $errors["drops[{$i}]"] = get_string('formerror_'.$errorcode, 'qtype_ddmarker');
d2ac6cea
JP
242 }
243 }
6f789d3d 244
d2ac6cea 245 }
f8bb5fdc 246 for ($dragindex = 0; $dragindex < $data['noitems']; $dragindex++) {
d2ac6cea 247 $label = $data['drags'][$dragindex]['label'];
5a34e0b0 248 if ($label != strip_tags($label, QTYPE_DDMARKER_ALLOWED_TAGS_IN_MARKER)) {
d2ac6cea 249 $errors["drags[{$dragindex}]"]
5a34e0b0 250 = get_string('formerror_onlysometagsallowed', 'qtype_ddmarker',
5263d6d7 251 s(QTYPE_DDMARKER_ALLOWED_TAGS_IN_MARKER));
d2ac6cea 252 }
d2ac6cea
JP
253 }
254 return $errors;
255 }
8aae74a4 256
8bc1d28b
EM
257 /**
258 * Gets the width and height of a draft image.
259 *
260 * @param int $draftitemid ID of the draft image
261 * @return array Return array of the width and height of the draft image.
262 */
8aae74a4
JP
263 public function get_image_size_in_draft_area($draftitemid) {
264 global $USER;
18be442c 265 $usercontext = context_user::instance($USER->id);
8aae74a4
JP
266 $fs = get_file_storage();
267 $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftitemid, 'id');
268 if ($draftfiles) {
269 foreach ($draftfiles as $file) {
270 if ($file->is_directory()) {
271 continue;
272 }
5263d6d7 273 // Just return the data for the first good file, there should only be one.
8aae74a4
JP
274 $imageinfo = $file->get_imageinfo();
275 $width = $imageinfo['width'];
276 $height = $imageinfo['height'];
277 return array($width, $height);
278 }
279 }
280 return null;
281 }
b3878dbd 282}