See Release Notes
Long Term Support Release
Differences Between: [Versions 39 and 310] [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]
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 * Essay question definition class. 19 * 20 * @package qtype 21 * @subpackage essay 22 * @copyright 2009 The Open University 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 require_once($CFG->dirroot . '/question/type/questionbase.php'); 30 31 /** 32 * Represents an essay question. 33 * 34 * @copyright 2009 The Open University 35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 */ 37 class qtype_essay_question extends question_with_responses { 38 39 public $responseformat; 40 41 /** @var int Indicates whether an inline response is required ('0') or optional ('1') */ 42 public $responserequired; 43 44 public $responsefieldlines; 45 public $attachments; 46 47 /** @var int The number of attachments required for a response to be complete. */ 48 public $attachmentsrequired; 49 50 public $graderinfo; 51 public $graderinfoformat; 52 public $responsetemplate; 53 public $responsetemplateformat; 54 55 /** @var array The string array of file types accepted upon file submission. */ 56 public $filetypeslist; 57 58 public function make_behaviour(question_attempt $qa, $preferredbehaviour) { 59 return question_engine::make_behaviour('manualgraded', $qa, $preferredbehaviour); 60 } 61 62 /** 63 * @param moodle_page the page we are outputting to. 64 * @return qtype_essay_format_renderer_base the response-format-specific renderer. 65 */ 66 public function get_format_renderer(moodle_page $page) { 67 return $page->get_renderer('qtype_essay', 'format_' . $this->responseformat); 68 } 69 70 public function get_expected_data() { 71 if ($this->responseformat == 'editorfilepicker') { 72 $expecteddata = array('answer' => question_attempt::PARAM_RAW_FILES); 73 } else { 74 $expecteddata = array('answer' => PARAM_RAW); 75 } 76 $expecteddata['answerformat'] = PARAM_ALPHANUMEXT; 77 if ($this->attachments != 0) { 78 $expecteddata['attachments'] = question_attempt::PARAM_FILES; 79 } 80 return $expecteddata; 81 } 82 83 public function summarise_response(array $response) { 84 $output = null; 85 86 if (isset($response['answer'])) { 87 $output .= question_utils::to_plain_text($response['answer'], 88 $response['answerformat'], array('para' => false)); 89 } 90 91 if (isset($response['attachments']) && $response['attachments']) { 92 $attachedfiles = []; 93 foreach ($response['attachments']->get_files() as $file) { 94 $attachedfiles[] = $file->get_filename() . ' (' . display_size($file->get_filesize()) . ')'; 95 } 96 if ($attachedfiles) { 97 $output .= get_string('attachedfiles', 'qtype_essay', implode(', ', $attachedfiles)); 98 } 99 } 100 return $output; 101 } 102 103 public function un_summarise_response(string $summary) { 104 if (empty($summary)) { 105 return []; 106 } 107 108 if (str_contains($this->responseformat, 'editor')) { 109 return ['answer' => text_to_html($summary), 'answerformat' => FORMAT_HTML]; 110 } else { 111 return ['answer' => $summary, 'answerformat' => FORMAT_PLAIN]; 112 } 113 } 114 115 public function get_correct_response() { 116 return null; 117 } 118 119 public function is_complete_response(array $response) { 120 // Determine if the given response has online text and attachments. 121 $hasinlinetext = array_key_exists('answer', $response) && ($response['answer'] !== ''); 122 $hasattachments = array_key_exists('attachments', $response) 123 && $response['attachments'] instanceof question_response_files; 124 125 // Determine the number of attachments present. 126 if ($hasattachments) { 127 // Check the filetypes. 128 $filetypesutil = new \core_form\filetypes_util(); 129 $whitelist = $filetypesutil->normalize_file_types($this->filetypeslist); 130 $wrongfiles = array(); 131 foreach ($response['attachments']->get_files() as $file) { 132 if (!$filetypesutil->is_allowed_file_type($file->get_filename(), $whitelist)) { 133 $wrongfiles[] = $file->get_filename(); 134 } 135 } 136 if ($wrongfiles) { // At least one filetype is wrong. 137 return false; 138 } 139 $attachcount = count($response['attachments']->get_files()); 140 } else { 141 $attachcount = 0; 142 } 143 144 // Determine if we have /some/ content to be graded. 145 $hascontent = $hasinlinetext || ($attachcount > 0); 146 147 // Determine if we meet the optional requirements. 148 $meetsinlinereq = $hasinlinetext || (!$this->responserequired) || ($this->responseformat == 'noinline'); 149 $meetsattachmentreq = ($attachcount >= $this->attachmentsrequired); 150 151 // The response is complete iff all of our requirements are met. 152 return $hascontent && $meetsinlinereq && $meetsattachmentreq; 153 } 154 155 public function is_gradable_response(array $response) { 156 // Determine if the given response has online text and attachments. 157 if (array_key_exists('answer', $response) && ($response['answer'] !== '')) { 158 return true; 159 } else if (array_key_exists('attachments', $response) 160 && $response['attachments'] instanceof question_response_files) { 161 return true; 162 } else { 163 return false; 164 } 165 } 166 167 public function is_same_response(array $prevresponse, array $newresponse) { 168 if (array_key_exists('answer', $prevresponse) && $prevresponse['answer'] !== $this->responsetemplate) { 169 $value1 = (string) $prevresponse['answer']; 170 } else { 171 $value1 = ''; 172 } 173 if (array_key_exists('answer', $newresponse) && $newresponse['answer'] !== $this->responsetemplate) { 174 $value2 = (string) $newresponse['answer']; 175 } else { 176 $value2 = ''; 177 } 178 return $value1 === $value2 && ($this->attachments == 0 || 179 question_utils::arrays_same_at_key_missing_is_blank( 180 $prevresponse, $newresponse, 'attachments')); 181 } 182 183 public function check_file_access($qa, $options, $component, $filearea, $args, $forcedownload) { 184 if ($component == 'question' && $filearea == 'response_attachments') { 185 // Response attachments visible if the question has them. 186 return $this->attachments != 0; 187 188 } else if ($component == 'question' && $filearea == 'response_answer') { 189 // Response attachments visible if the question has them. 190 return $this->responseformat === 'editorfilepicker'; 191 192 } else if ($component == 'qtype_essay' && $filearea == 'graderinfo') { 193 return $options->manualcomment && $args[0] == $this->id; 194 195 } else { 196 return parent::check_file_access($qa, $options, $component, 197 $filearea, $args, $forcedownload); 198 } 199 } 200 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body