PageRenderTime 41ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/question/type/ddmarker/edit_ddmarker_form.php

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