PageRenderTime 58ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 0ms

/question/type/fileresponse/questiontype.php

https://github.com/galitush2005/RTL-BIDI-Hebrew-Moodle-Plugins
PHP | 340 lines | 201 code | 52 blank | 87 comment | 39 complexity | 3da455abfcc78a2241132a726ed60d5f MD5 | raw file
  1. <?php
  2. /**
  3. * The question type class for the fileresponse question type.
  4. *
  5. * The fileresponse question type allows a student to upload one file
  6. * as the answer to a question. The file is uploaded to the directory
  7. * specified by:
  8. *
  9. * $CFG->dirroot/questionattempt/attempt#/question#
  10. *
  11. * Only one file is allowed, so each submission replaces the previous file.
  12. * Once a file has been uploaded, the student can submit again to replace
  13. * the file, but he/she cannot delete the file.
  14. *
  15. * @copyright &copy; 2007 Adriane Boyd
  16. * @author Adriane Boyd adrianeboyd@gmail.com
  17. * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
  18. * @package aab_fileresponse
  19. *
  20. */
  21. // include library routines for this question type
  22. require_once(dirname(__FILE__) . '/locallib.php');
  23. class fileresponse_qtype extends default_questiontype {
  24. function name() {
  25. return 'fileresponse';
  26. }
  27. function is_manual_graded() {
  28. return true;
  29. }
  30. function is_usable_by_random() {
  31. return false;
  32. }
  33. /**
  34. * Loads the question type specific options for the question.
  35. *
  36. * @return boolean to indicate success or failure
  37. */
  38. function get_question_options(&$question) {
  39. // Get additional information from database
  40. // and attach it to the question object
  41. if (!$question->options = get_record('question_fileresponse', 'question', $question->id)) {
  42. notify('Error: Missing question options!');
  43. return false;
  44. }
  45. // Get data from question_answers (for feedback)
  46. parent::get_question_options($question);
  47. return true;
  48. }
  49. /**
  50. * Save the units and the answers associated with this question.
  51. * @return boolean to indicate success or failure.
  52. */
  53. function save_question_options($question) {
  54. // Save question options in question_answers
  55. $result = true;
  56. $update = true;
  57. $answer = get_record("question_answers", "question", $question->id);
  58. if (!$answer) {
  59. $answer = new stdClass;
  60. $answer->question = $question->id;
  61. $update = false;
  62. }
  63. $answer->answer = $question->feedback;
  64. $answer->feedback = $question->feedback;
  65. $answer->fraction = $question->fraction;
  66. if ($update) {
  67. if (!update_record("question_answers", $answer)) {
  68. $result = new stdClass;
  69. $result->error = "Could not update quiz answer!";
  70. }
  71. } else {
  72. if (!$answer->id = insert_record("question_answers", $answer)) {
  73. $result = new stdClass;
  74. $result->error = "Could not insert quiz answer!";
  75. }
  76. }
  77. // If the previous step succeeded, save question options in
  78. // question_fileresponse table
  79. if ($result) {
  80. if ($options = get_record("question_fileresponse", "question", $question->id)) {
  81. $options->maxbytes = $question->maxbytes;
  82. $options->essay = $question->essay;
  83. if (!update_record("question_fileresponse", $options)) {
  84. $result = new stdClass;
  85. $result->error = "Could not update quiz fileresponse options! (id=$options->id)";
  86. }
  87. } else {
  88. unset($options);
  89. $options->question = $question->id;
  90. $options->maxbytes = $question->maxbytes;
  91. $options->essay = $question->essay;
  92. if (!insert_record("question_fileresponse", $options)) {
  93. $result = new stdClass;
  94. $result->error = "Could not insert quiz fileresponse options!";
  95. }
  96. }
  97. }
  98. return $result;
  99. }
  100. /**
  101. * Deletes question from the question-type specific tables
  102. *
  103. * @param integer $questionid The question being deleted
  104. * @return boolean to indicate success or failure.
  105. */
  106. function delete_question($questionid) {
  107. delete_records("question_fileresponse", "question", $questionid);
  108. return true;
  109. }
  110. /**
  111. * Deletes files submitted in these states
  112. *
  113. * @param string $stateslist Comma separated list of state ids to be deleted
  114. * @return boolean to indicate success or failure.
  115. */
  116. function delete_states($stateslist) {
  117. global $CFG;
  118. $states = explode(',', $stateslist);
  119. foreach ($states as $stateid) {
  120. $state = get_record("question_states", "id", "$stateid");
  121. $attemptid = $state->attempt;
  122. $questionid = $state->question;
  123. // delete any files submitted in this attempt
  124. $dir = quiz_file_area_name($attemptid, $questionid);
  125. if (file_exists($CFG->dataroot.'/'.$dir)) {
  126. fulldelete($CFG->dataroot.'/'.$dir);
  127. $dirparts = explode('/', $dir);
  128. // the directory is two levels deep, so delete the lower directory, too
  129. array_pop($dirparts);
  130. $dir = implode('/', $dirparts);
  131. fulldelete($CFG->dataroot.'/'.$dir);
  132. }
  133. }
  134. return true;
  135. }
  136. /**
  137. * Format question display
  138. */
  139. function print_question_formulation_and_controls(&$question, &$state, $cmoptions, $options) {
  140. global $CFG;
  141. require_once($CFG->libdir.'/formslib.php');
  142. $readonly = empty($options->readonly) ? '' : 'disabled="disabled"';
  143. static $htmleditorused = false;
  144. // Print formulation
  145. $questiontext = $this->format_text($question->questiontext, $question->questiontextformat, $cmoptions);
  146. $image = get_question_image($question);
  147. $maxbytes = $question->options->maxbytes;
  148. $showessay = $question->options->essay;
  149. $answers = &$question->options->answers;
  150. $readonly = empty($options->readonly) ? '' : 'disabled="disabled"';
  151. // Only use the rich text editor for the first essay question on a page.
  152. $usehtmleditor = can_use_html_editor() && !$htmleditorused;
  153. $formatoptions = new stdClass;
  154. $formatoptions->noclean = true;
  155. $formatoptions->para = false;
  156. $inputname = $question->name_prefix;
  157. /// set question text and media
  158. $questiontext = format_text($question->questiontext,
  159. $question->questiontextformat,
  160. $formatoptions, $cmoptions->course);
  161. // feedback handling
  162. $feedback = '';
  163. if ($options->feedback && !empty($answers)) {
  164. foreach ($answers as $answer) {
  165. $feedback = format_text($answer->feedback, '', $formatoptions, $cmoptions->course);
  166. }
  167. }
  168. // get essay response value
  169. if (isset($state->responses[''])) {
  170. $value = stripslashes_safe($state->responses['']);
  171. } else {
  172. $value = "";
  173. }
  174. // essay answer
  175. $answer = '';
  176. if ($showessay) {
  177. if (empty($options->readonly)) {
  178. // the student needs to type in their answer so print out a text editor
  179. $answer = print_textarea($usehtmleditor, 18, 80, 630, 400, $inputname, $value, $cmoptions->course, true);
  180. } else {
  181. // it is read only, so just format the students answer and output it
  182. $safeformatoptions = new stdClass;
  183. $safeformatoptions->para = false;
  184. $answer = format_text($value, FORMAT_MOODLE,
  185. $safeformatoptions, $cmoptions->course);
  186. }
  187. }
  188. // set the file input form
  189. //"form.action = form.action + '#q".$question->id."'; document.getElementById('responseform').submit();"
  190. $struploadform = upload_print_form_fragment(1, array($question->name_prefix . "file"), null, false, null, 0, $maxbytes, true);
  191. // set file upload feedback and display of uploaded file
  192. $uploadfeedback = '';
  193. if (isset($state->uploadfeedback)) {
  194. $uploadfeedback = $state->uploadfeedback;
  195. }
  196. $struploadedfile = '';
  197. $currentfile = get_student_answer($state->attempt, $question->id);
  198. if ($currentfile) {
  199. $struploadedfile = get_string('answer', 'quiz').': '.$currentfile;
  200. }
  201. // string prompts for form
  202. if ($currentfile) {
  203. $struploadfile = get_string('uploadnew', 'qtype_fileresponse');
  204. } else {
  205. $struploadfile = get_string('uploadafile');
  206. }
  207. $strmaxsize = get_string('maximumupload').' '. display_size($maxbytes);
  208. include("$CFG->dirroot/question/type/fileresponse/display.html");
  209. if ($usehtmleditor) {
  210. use_html_editor($inputname);
  211. $htmleditorused = true;
  212. }
  213. }
  214. /**
  215. * Upload the file and prepare for manual grading
  216. */
  217. function grade_responses(&$question, &$state, $cmoptions) {
  218. global $CFG;
  219. $state->raw_grade = 0;
  220. $state->penalty = 0;
  221. $state->uploadfeedback = upload_response($question->name_prefix.'file', $cmoptions->course, $state->attempt, $question->id, $question->options->maxbytes);
  222. if ($question->options->essay) {
  223. clean_param($state->responses[''], PARAM_CLEANHTML);
  224. }
  225. return true;
  226. }
  227. /**
  228. * Backup the data in the question
  229. *
  230. * This is used in question/backuplib.php
  231. */
  232. function backup($bf, $preferences, $question, $level=6) {
  233. $status = true;
  234. $fileresponses = get_records("question_fileresponse", "question", $question, "id ASC");
  235. // If there is a question
  236. if ($fileresponses) {
  237. // Iterate over each
  238. foreach ($fileresponses as $fileresponse) {
  239. $status = $status && fwrite($bf, start_tag("FILERESPONSE", $level, true));
  240. // Print contents
  241. $status = $status && fwrite($bf, full_tag("MAXBYTES", $level+1, false,$fileresponse->maxbytes));
  242. $status = $status && fwrite($bf, full_tag("ESSAY", $level+1, false, $fileresponse->essay));
  243. $status = $status && fwrite($bf, end_tag("FILERESPONSE", $level, true));
  244. }
  245. // Now print question_answers
  246. $status = $status && question_backup_answers($bf, $preferences, $question, $level);
  247. }
  248. return $status;
  249. }
  250. /**
  251. * Restores the data in the question
  252. *
  253. * This is used in question/restorelib.php
  254. */
  255. function restore($oldquestion, $newquestion, $info, $restore) {
  256. $status = true;
  257. // Get the fileresponses array
  258. $fileresponses = $info['#']['FILERESPONSE'];
  259. // Iterate over fileresponses
  260. for($i = 0; $i < sizeof($fileresponses); $i++) {
  261. $frinfo = $fileresponses[$i];
  262. // Now, build the question_fileresponse record structure
  263. $fileresponse = new stdClass;
  264. $fileresponse->question = $newquestion;
  265. $fileresponse->maxbytes = backup_todb($frinfo['#']['MAXBYTES']['0']['#']);
  266. $fileresponse->essay = backup_todb($frinfo['#']['ESSAY']['0']['#']);
  267. // The structure is equal to the db, so insert the question_fileresponse
  268. $newid = insert_record("question_fileresponse", $fileresponse);
  269. // Do some output
  270. if (($i+1) % 50 == 0) {
  271. if (!defined('RESTORE_SILENTLY')) {
  272. echo ".";
  273. if (($i+1) % 1000 == 0) {
  274. echo "<br />";
  275. }
  276. }
  277. backup_flush(300);
  278. }
  279. if (!$newid) {
  280. $status = false;
  281. }
  282. }
  283. return $status;
  284. }
  285. }
  286. // Register this question type with the system.
  287. question_register_questiontype(new fileresponse_qtype());
  288. ?>