MDL-47494 qtype: Fix the behat tests for OU dd question types
[moodle.git] / question / type / ddimageortext / questiontypebase.php
CommitLineData
d2c112fd
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/**
c109c901 18 * Question type class for the drag-and-drop onto image question type.
d2c112fd 19 *
c109c901 20 * @package qtype_ddimageortext
d2c112fd
JP
21 * @copyright 2009 The Open University
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25
26defined('MOODLE_INTERNAL') || die();
27
28require_once($CFG->libdir . '/questionlib.php');
29require_once($CFG->dirroot . '/question/engine/lib.php');
30require_once($CFG->dirroot . '/question/format/xml/format.php');
31require_once($CFG->dirroot . '/question/type/gapselect/questiontypebase.php');
32
33/**
c109c901 34 * The drag-and-drop onto image question type class.
d2c112fd
JP
35 *
36 * @copyright 2009 The Open University
37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38 */
39class qtype_ddtoimage_base extends question_type {
40 protected function choice_group_key() {
41 return 'draggroup';
42 }
43
d2c112fd
JP
44 public function get_question_options($question) {
45 global $DB;
eaabb891
JP
46 $dbprefix = 'qtype_'.$this->name();
47 $question->options = $DB->get_record($dbprefix,
d2c112fd 48 array('questionid' => $question->id), '*', MUST_EXIST);
eaabb891 49 $question->options->drags = $DB->get_records($dbprefix.'_drags',
d2c112fd 50 array('questionid' => $question->id), 'no ASC', '*');
eaabb891 51 $question->options->drops = $DB->get_records($dbprefix.'_drops',
d2c112fd
JP
52 array('questionid' => $question->id), 'no ASC', '*');
53 parent::get_question_options($question);
54 }
55
d2c112fd
JP
56 protected function initialise_question_instance(question_definition $question, $questiondata) {
57 parent::initialise_question_instance($question, $questiondata);
58 $question->shufflechoices = $questiondata->options->shuffleanswers;
59
60 $this->initialise_combined_feedback($question, $questiondata, true);
61
62 $question->choices = array();
13ee9a26 63 $choiceindexmap = array();
d2c112fd
JP
64
65 // Store the choices in arrays by group.
2bf2e46c
TH
66 // This code is weird. The first choice in each group gets key 1 in the
67 // $question->choices[$choice->choice_group()] array, and the others get
68 // key $choice->no. Therefore you need to think carefully whether you
69 // are using the key, or $choice->no. This is presumably a mistake, but
70 // one that is now essentially un-fixable, since many questions of this
71 // type have been attempted, and theys keys get stored in the attempt data.
d2c112fd
JP
72 foreach ($questiondata->options->drags as $dragdata) {
73
74 $choice = $this->make_choice($dragdata);
75
76 if (array_key_exists($choice->choice_group(), $question->choices)) {
77 $question->choices[$choice->choice_group()][$dragdata->no] = $choice;
78 } else {
79 $question->choices[$choice->choice_group()][1] = $choice;
80 }
81
82 end($question->choices[$choice->choice_group()]);
83 $choiceindexmap[$dragdata->no] = array($choice->choice_group(),
84 key($question->choices[$choice->choice_group()]));
85 }
86
87 $question->places = array();
88 $question->rightchoices = array();
89
90 $i = 1;
91
92 foreach ($questiondata->options->drops as $dropdata) {
93 list($group, $choiceindex) = $choiceindexmap[$dropdata->choice];
94 $dropdata->group = $group;
95 $question->places[$dropdata->no] = $this->make_place($dropdata);
96 $question->rightchoices[$dropdata->no] = $choiceindex;
97 }
98 }
99
d2c112fd
JP
100 public static function constrain_image_size_in_draft_area($draftitemid, $maxwidth, $maxheight) {
101 global $USER;
86687aad 102 $usercontext = context_user::instance($USER->id);
d2c112fd
JP
103 $fs = get_file_storage();
104 $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftitemid, 'id');
105 if ($draftfiles) {
106 foreach ($draftfiles as $file) {
107 if ($file->is_directory()) {
108 continue;
109 }
110 $imageinfo = $file->get_imageinfo();
111 $width = $imageinfo['width'];
112 $height = $imageinfo['height'];
113 $mimetype = $imageinfo['mimetype'];
114 switch ($mimetype) {
115 case 'image/jpeg' :
116 $quality = 80;
117 break;
118 case 'image/png' :
119 $quality = 8;
120 break;
121 default :
122 $quality = null;
123 }
124 $newwidth = min($maxwidth, $width);
125 $newheight = min($maxheight, $height);
126 if ($newwidth != $width || $newheight != $height) {
127 $newimagefilename = $file->get_filename();
128 $newimagefilename =
129 preg_replace('!\.!', "_{$newwidth}x{$newheight}.", $newimagefilename, 1);
130 $newrecord = new stdClass();
131 $newrecord->contextid = $usercontext->id;
132 $newrecord->component = 'user';
133 $newrecord->filearea = 'draft';
134 $newrecord->itemid = $draftitemid;
135 $newrecord->filepath = '/';
136 $newrecord->filename = $newimagefilename;
137 $fs->convert_image($newrecord, $file, $newwidth, $newheight, true, $quality);
138 $file->delete();
139 }
140 }
141 }
142 }
d2c112fd 143
d2c112fd
JP
144 /**
145 * Convert files into text output in the given format.
146 * This method is copied from qformat_default as a quick fix, as the method there is
147 * protected.
148 * @param array
149 * @param string encoding method
150 * @return string $string
151 */
152 public function write_files($files, $indent) {
153 if (empty($files)) {
154 return '';
155 }
156 $string = '';
157 foreach ($files as $file) {
158 if ($file->is_directory()) {
159 continue;
160 }
161 $string .= str_repeat(' ', $indent);
162 $string .= '<file name="' . $file->get_filename() . '" encoding="base64">';
163 $string .= base64_encode($file->get_content());
164 $string .= "</file>\n";
165 }
166 return $string;
167 }
168
169 public function get_possible_responses($questiondata) {
170 $question = $this->make_question($questiondata);
171
172 $parts = array();
173 foreach ($question->places as $placeno => $place) {
d2c112fd
JP
174 $choices = array();
175
13ee9a26 176 foreach ($question->choices[$place->group] as $i => $choice) {
d2c112fd 177 $correct = $question->rightchoices[$placeno] == $i;
13ee9a26 178 $choices[$choice->no] = new question_possible_response($choice->summarise(), $correct ? 1 : 0);
d2c112fd
JP
179 }
180 $choices[null] = question_possible_response::no_response();
181
182 $parts[$placeno] = $choices;
183 }
184
185 return $parts;
186 }
187
188 public function get_random_guess_score($questiondata) {
189 $question = $this->make_question($questiondata);
190 return $question->get_random_guess_score();
191 }
cb5c4e62
JP
192 public function delete_question($questionid, $contextid) {
193 global $DB;
5b7d9dec 194 $DB->delete_records('qtype_'.$this->name(), array('questionid' => $questionid));
cb5c4e62
JP
195 $DB->delete_records('qtype_'.$this->name().'_drags', array('questionid' => $questionid));
196 $DB->delete_records('qtype_'.$this->name().'_drops', array('questionid' => $questionid));
197 return parent::delete_question($questionid, $contextid);
198 }
d2c112fd 199}