Skip to content

Commit 1354804

Browse files
committed
Add new question type file
1 parent 5c0dbe8 commit 1354804

File tree

16 files changed

+1002
-7
lines changed

16 files changed

+1002
-7
lines changed

classes/question/file.php

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
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+
namespace mod_questionnaire\question;
17+
use core_media_manager;
18+
use form_filemanager;
19+
use mod_questionnaire\responsetype\response\response;
20+
use moodle_url;
21+
use MoodleQuickForm;
22+
23+
/**
24+
* This file contains the parent class for text question types.
25+
*
26+
* @author Laurent David
27+
* @author Martin Cornu-Mansuy
28+
* @copyright 2023 onward CALL Learning <[email protected]>
29+
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
30+
* @package mod_questionnaire
31+
*/
32+
class file extends question {
33+
34+
/**
35+
* Get name.
36+
*
37+
* @return string
38+
*/
39+
public function helpname() {
40+
return 'file';
41+
}
42+
43+
/**
44+
* Override and return a form template if provided. Output of question_survey_display is iterpreted based on this.
45+
*
46+
* @return boolean | string
47+
*/
48+
public function question_template() {
49+
return false;
50+
}
51+
52+
/**
53+
* Override and return a response template if provided. Output of response_survey_display is iterpreted based on this.
54+
*
55+
* @return boolean | string
56+
*/
57+
public function response_template() {
58+
return false;
59+
}
60+
61+
/**
62+
* Get response class.
63+
*
64+
* @return object|string
65+
*/
66+
protected function responseclass() {
67+
return '\\mod_questionnaire\\responsetype\\file';
68+
}
69+
70+
/**
71+
* Survey display output.
72+
*
73+
* @param response $response
74+
* @param object $descendantsdata
75+
* @param bool $blankquestionnaire
76+
* @return string
77+
*/
78+
protected function question_survey_display($response, $descendantsdata, $blankquestionnaire = false) {
79+
global $CFG, $PAGE;
80+
require_once($CFG->libdir . '/filelib.php');
81+
82+
$elname = 'q' . $this->id;
83+
// Make sure there is a response, fetch the draft id from the original request.
84+
if (isset($response->answers[$this->id]) && !empty($response->answers[$this->id]) && isset($_REQUEST[$elname . 'draft'])) {
85+
$draftitemid = (int)$_REQUEST[$elname . 'draft'];
86+
} else {
87+
$draftitemid = file_get_submitted_draft_itemid($elname);
88+
}
89+
if ($draftitemid > 0) {
90+
file_prepare_draft_area($draftitemid, $this->context->id,
91+
'mod_questionnaire', 'file', $this->id, self::get_file_manager_option());
92+
} else {
93+
$draftitemid = file_get_unused_draft_itemid();
94+
}
95+
// Filemanager form element implementation is far from optimal, we need to rework this if we ever fix it...
96+
require_once("$CFG->dirroot/lib/form/filemanager.php");
97+
98+
$options = array_merge(self::get_file_manager_option(), [
99+
'client_id' => uniqid(),
100+
'itemid' => $draftitemid,
101+
'target' => $this->id,
102+
'name' => $elname,
103+
]);
104+
$fm = new form_filemanager((object)$options);
105+
$output = $PAGE->get_renderer('core', 'files');
106+
107+
$html = '<div class="form-filemanager" data-fieldtype="filemanager">' .
108+
$output->render($fm) .
109+
'<input type="hidden" name="' . $elname . '" value="' . $draftitemid . '" />' .
110+
'<input type="hidden" name="' . $elname . 'draft" value="' . $draftitemid . '" />' .
111+
'</div>';
112+
113+
return $html;
114+
}
115+
116+
/**
117+
* Check question's form data for complete response.
118+
* @param \stdClass $responsedata The data entered into the response.
119+
* @return bool
120+
*/
121+
public function response_complete($responsedata) {
122+
$answered = false;
123+
// If $responsedata is a response object, look through the answers.
124+
if (is_a($responsedata, 'mod_questionnaire\responsetype\response\response') &&
125+
isset($responsedata->answers[$this->id]) && !empty($responsedata->answers[$this->id])
126+
) {
127+
$answer = reset($responsedata->answers[$this->id]);
128+
$answered = ((int)$answer->value > 0);
129+
} else if (isset($responsedata->{'q'.$this->id})) {
130+
// If $responsedata is webform data, check that it is not empty.
131+
$draftitemid = (int)$responsedata->{'q' . $this->id};
132+
if ($draftitemid > 0) {
133+
$info = file_get_draft_area_info($draftitemid);
134+
$answered = $info['filecount'] > 0;
135+
}
136+
}
137+
return !($this->required() && ($this->deleted == 'n') && !$answered);
138+
}
139+
140+
/**
141+
* Get file manager options
142+
*
143+
* @return array
144+
*/
145+
public static function get_file_manager_option() {
146+
return [
147+
'mainfile' => '',
148+
'subdirs' => false,
149+
'accepted_types' => ['image', '.pdf'],
150+
'maxfiles' => 1,
151+
];
152+
}
153+
154+
/**
155+
* Response display output.
156+
*
157+
* @param \stdClass $data
158+
* @return string
159+
*/
160+
protected function response_survey_display($data) {
161+
global $PAGE, $CFG;
162+
require_once($CFG->libdir . '/filelib.php');
163+
require_once($CFG->libdir . '/resourcelib.php');
164+
if (isset($data->answers[$this->id])) {
165+
$answer = reset($data->answers[$this->id]);
166+
} else {
167+
return '';
168+
}
169+
$fs = get_file_storage();
170+
$file = $fs->get_file_by_id($answer->value);
171+
$code = '';
172+
173+
if ($file) {
174+
// There is a file.
175+
$moodleurl = moodle_url::make_pluginfile_url(
176+
$file->get_contextid(),
177+
$file->get_component(),
178+
$file->get_filearea(),
179+
$file->get_itemid(),
180+
$file->get_filepath(),
181+
$file->get_filename()
182+
);
183+
184+
$mimetype = $file->get_mimetype();
185+
$title = '';
186+
187+
$mediamanager = core_media_manager::instance($PAGE);
188+
$embedoptions = array(
189+
core_media_manager::OPTION_TRUSTED => true,
190+
core_media_manager::OPTION_BLOCK => true,
191+
);
192+
193+
if (file_mimetype_in_typegroup($mimetype, 'web_image')) { // It's an image.
194+
$code = resourcelib_embed_image($moodleurl->out(), $title);
195+
196+
} else if ($mimetype === 'application/pdf') {
197+
// PDF document.
198+
$code = resourcelib_embed_pdf($moodleurl->out(), $title, get_string('view'));
199+
200+
} else if ($mediamanager->can_embed_url($moodleurl, $embedoptions)) {
201+
// Media (audio/video) file.
202+
$code = $mediamanager->embed_url($moodleurl, $title, 0, 0, $embedoptions);
203+
204+
} else {
205+
// We need a way to discover if we are loading remote docs inside an iframe.
206+
$moodleurl->param('embed', 1);
207+
208+
// Anything else - just try object tag enlarged as much as possible.
209+
$code = resourcelib_embed_general($moodleurl, $title, get_string('view'), $mimetype);
210+
}
211+
}
212+
return '<div class="response text">' . $code . '</div>';
213+
}
214+
215+
/**
216+
* Add the length element as hidden.
217+
*
218+
* @param \MoodleQuickForm $mform
219+
* @param string $helpname
220+
* @return \MoodleQuickForm
221+
*/
222+
protected function form_length(MoodleQuickForm $mform, $helpname = '') {
223+
return question::form_length_hidden($mform);
224+
}
225+
226+
/**
227+
* Add the precise element as hidden.
228+
*
229+
* @param \MoodleQuickForm $mform
230+
* @param string $helpname
231+
* @return \MoodleQuickForm
232+
*/
233+
protected function form_precise(MoodleQuickForm $mform, $helpname = '') {
234+
return question::form_precise_hidden($mform);
235+
}
236+
237+
}

classes/question/question.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
define('QUESDATE', 9);
4343
define('QUESNUMERIC', 10);
4444
define('QUESSLIDER', 11);
45+
define('QUESFILE', 12);
4546
define('QUESPAGEBREAK', 99);
4647
define('QUESSECTIONTEXT', 100);
4748

@@ -123,6 +124,7 @@ abstract class question {
123124
QUESPAGEBREAK => 'pagebreak',
124125
QUESSECTIONTEXT => 'sectiontext',
125126
QUESSLIDER => 'slider',
127+
QUESFILE => 'file',
126128
];
127129

128130
/** @var array $notifications Array of extra messages for display purposes. */

0 commit comments

Comments
 (0)