| 1 | efrain | 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 renderer 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 |   | 
        
           |  |  | 30 | /**
 | 
        
           |  |  | 31 |  * Generates the output for essay questions.
 | 
        
           |  |  | 32 |  *
 | 
        
           |  |  | 33 |  * @copyright  2009 The Open University
 | 
        
           |  |  | 34 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 35 |  */
 | 
        
           |  |  | 36 | class qtype_essay_renderer extends qtype_renderer {
 | 
        
           |  |  | 37 |     public function formulation_and_controls(question_attempt $qa,
 | 
        
           |  |  | 38 |             question_display_options $options) {
 | 
        
           |  |  | 39 |         global $CFG;
 | 
        
           |  |  | 40 |         $question = $qa->get_question();
 | 
        
           |  |  | 41 |   | 
        
           |  |  | 42 |         /** @var qtype_essay_format_renderer_base $responseoutput */
 | 
        
           |  |  | 43 |         $responseoutput = $question->get_format_renderer($this->page);
 | 
        
           |  |  | 44 |         $responseoutput->set_displayoptions($options);
 | 
        
           |  |  | 45 |   | 
        
           |  |  | 46 |         // Answer field.
 | 
        
           |  |  | 47 |         $step = $qa->get_last_step_with_qt_var('answer');
 | 
        
           |  |  | 48 |   | 
        
           |  |  | 49 |         if (!$step->has_qt_var('answer') && empty($options->readonly)) {
 | 
        
           |  |  | 50 |             // Question has never been answered, fill it with response template.
 | 
        
           |  |  | 51 |             $step = new question_attempt_step(array('answer' => $question->responsetemplate));
 | 
        
           |  |  | 52 |         }
 | 
        
           |  |  | 53 |   | 
        
           |  |  | 54 |         if (empty($options->readonly)) {
 | 
        
           |  |  | 55 |             $answer = $responseoutput->response_area_input('answer', $qa,
 | 
        
           |  |  | 56 |                     $step, $question->responsefieldlines, $options->context);
 | 
        
           |  |  | 57 |   | 
        
           |  |  | 58 |         } else {
 | 
        
           |  |  | 59 |             $answer = $responseoutput->response_area_read_only('answer', $qa,
 | 
        
           |  |  | 60 |                     $step, $question->responsefieldlines, $options->context);
 | 
        
           |  |  | 61 |             $answer .= html_writer::nonempty_tag('p', $question->get_word_count_message_for_review($step->get_qt_data()));
 | 
        
           |  |  | 62 |   | 
        
           |  |  | 63 |             if (!empty($CFG->enableplagiarism)) {
 | 
        
           |  |  | 64 |                 require_once($CFG->libdir . '/plagiarismlib.php');
 | 
        
           |  |  | 65 |   | 
        
           |  |  | 66 |                 $answer .= plagiarism_get_links([
 | 
        
           |  |  | 67 |                     'context' => $options->context->id,
 | 
        
           |  |  | 68 |                     'component' => $qa->get_question()->qtype->plugin_name(),
 | 
        
           |  |  | 69 |                     'area' => $qa->get_usage_id(),
 | 
        
           |  |  | 70 |                     'itemid' => $qa->get_slot(),
 | 
        
           |  |  | 71 |                     'userid' => $step->get_user_id(),
 | 
        
           |  |  | 72 |                     'content' => $qa->get_response_summary()]);
 | 
        
           |  |  | 73 |             }
 | 
        
           |  |  | 74 |         }
 | 
        
           |  |  | 75 |   | 
        
           |  |  | 76 |         $files = '';
 | 
        
           |  |  | 77 |         if ($question->attachments) {
 | 
        
           |  |  | 78 |             if (empty($options->readonly)) {
 | 
        
           |  |  | 79 |                 $files = $this->files_input($qa, $question->attachments, $options);
 | 
        
           |  |  | 80 |   | 
        
           |  |  | 81 |             } else {
 | 
        
           |  |  | 82 |                 $files = $this->files_read_only($qa, $options);
 | 
        
           |  |  | 83 |             }
 | 
        
           |  |  | 84 |         }
 | 
        
           |  |  | 85 |   | 
        
           |  |  | 86 |         $result = '';
 | 
        
           |  |  | 87 |         $result .= html_writer::tag('div', $question->format_questiontext($qa),
 | 
        
           |  |  | 88 |                 array('class' => 'qtext'));
 | 
        
           |  |  | 89 |   | 
        
           |  |  | 90 |         $result .= html_writer::start_tag('div', array('class' => 'ablock'));
 | 
        
           |  |  | 91 |         $result .= html_writer::tag('div', $answer, array('class' => 'answer'));
 | 
        
           |  |  | 92 |   | 
        
           |  |  | 93 |         // If there is a response and min/max word limit is set in the form then check the response word count.
 | 
        
           |  |  | 94 |         if ($qa->get_state() == question_state::$invalid) {
 | 
        
           |  |  | 95 |             $result .= html_writer::nonempty_tag('div',
 | 
        
           |  |  | 96 |                 $question->get_validation_error($step->get_qt_data()), ['class' => 'validationerror']);
 | 
        
           |  |  | 97 |         }
 | 
        
           |  |  | 98 |         $result .= html_writer::tag('div', $files, array('class' => 'attachments'));
 | 
        
           |  |  | 99 |         $result .= html_writer::end_tag('div');
 | 
        
           |  |  | 100 |   | 
        
           |  |  | 101 |         return $result;
 | 
        
           |  |  | 102 |     }
 | 
        
           |  |  | 103 |   | 
        
           |  |  | 104 |     /**
 | 
        
           |  |  | 105 |      * Displays any attached files when the question is in read-only mode.
 | 
        
           |  |  | 106 |      * @param question_attempt $qa the question attempt to display.
 | 
        
           |  |  | 107 |      * @param question_display_options $options controls what should and should
 | 
        
           |  |  | 108 |      *      not be displayed. Used to get the context.
 | 
        
           |  |  | 109 |      */
 | 
        
           |  |  | 110 |     public function files_read_only(question_attempt $qa, question_display_options $options) {
 | 
        
           |  |  | 111 |         global $CFG;
 | 
        
           |  |  | 112 |         $files = $qa->get_last_qt_files('attachments', $options->context->id);
 | 
        
           |  |  | 113 |         $filelist = [];
 | 
        
           |  |  | 114 |   | 
        
           |  |  | 115 |         $step = $qa->get_last_step_with_qt_var('attachments');
 | 
        
           |  |  | 116 |   | 
        
           |  |  | 117 |         foreach ($files as $file) {
 | 
        
           |  |  | 118 |             $out = html_writer::link($qa->get_response_file_url($file),
 | 
        
           |  |  | 119 |                 $this->output->pix_icon(file_file_icon($file), get_mimetype_description($file),
 | 
        
           |  |  | 120 |                     'moodle', array('class' => 'icon')) . ' ' . s($file->get_filename()));
 | 
        
           |  |  | 121 |             if (!empty($CFG->enableplagiarism)) {
 | 
        
           |  |  | 122 |                 require_once($CFG->libdir . '/plagiarismlib.php');
 | 
        
           |  |  | 123 |   | 
        
           |  |  | 124 |                 $out .= plagiarism_get_links([
 | 
        
           |  |  | 125 |                     'context' => $options->context->id,
 | 
        
           |  |  | 126 |                     'component' => $qa->get_question()->qtype->plugin_name(),
 | 
        
           |  |  | 127 |                     'area' => $qa->get_usage_id(),
 | 
        
           |  |  | 128 |                     'itemid' => $qa->get_slot(),
 | 
        
           |  |  | 129 |                     'userid' => $step->get_user_id(),
 | 
        
           |  |  | 130 |                     'file' => $file]);
 | 
        
           |  |  | 131 |             }
 | 
        
           |  |  | 132 |             $filelist[] = html_writer::tag('li', $out, ['class' => 'mb-2']);
 | 
        
           |  |  | 133 |         }
 | 
        
           |  |  | 134 |   | 
        
           |  |  | 135 |         $labelbyid = $qa->get_qt_field_name('attachments') . '_label';
 | 
        
           |  |  | 136 |   | 
        
           |  |  | 137 |         $fileslabel = $options->add_question_identifier_to_label(get_string('answerfiles', 'qtype_essay'));
 | 
        
           | 1441 | ariadna | 138 |         $output = html_writer::tag('h4', $fileslabel, ['id' => $labelbyid, 'class' => 'visually-hidden']);
 | 
        
           | 1 | efrain | 139 |         $output .= html_writer::tag('ul', implode($filelist), [
 | 
        
           |  |  | 140 |             'aria-labelledby' => $labelbyid,
 | 
        
           |  |  | 141 |             'class' => 'list-unstyled m-0',
 | 
        
           |  |  | 142 |         ]);
 | 
        
           |  |  | 143 |         return $output;
 | 
        
           |  |  | 144 |     }
 | 
        
           |  |  | 145 |   | 
        
           |  |  | 146 |     /**
 | 
        
           |  |  | 147 |      * Displays the input control for when the student should upload a single file.
 | 
        
           |  |  | 148 |      * @param question_attempt $qa the question attempt to display.
 | 
        
           |  |  | 149 |      * @param int $numallowed the maximum number of attachments allowed. -1 = unlimited.
 | 
        
           |  |  | 150 |      * @param question_display_options $options controls what should and should
 | 
        
           |  |  | 151 |      *      not be displayed. Used to get the context.
 | 
        
           |  |  | 152 |      */
 | 
        
           |  |  | 153 |     public function files_input(question_attempt $qa, $numallowed,
 | 
        
           |  |  | 154 |             question_display_options $options) {
 | 
        
           |  |  | 155 |         global $CFG, $COURSE;
 | 
        
           |  |  | 156 |         require_once($CFG->dirroot . '/lib/form/filemanager.php');
 | 
        
           |  |  | 157 |   | 
        
           |  |  | 158 |         $pickeroptions = new stdClass();
 | 
        
           |  |  | 159 |         $pickeroptions->mainfile = null;
 | 
        
           |  |  | 160 |         $pickeroptions->maxfiles = $numallowed;
 | 
        
           |  |  | 161 |         $pickeroptions->itemid = $qa->prepare_response_files_draft_itemid(
 | 
        
           |  |  | 162 |                 'attachments', $options->context->id);
 | 
        
           |  |  | 163 |         $pickeroptions->context = $options->context;
 | 
        
           |  |  | 164 |         $pickeroptions->return_types = FILE_INTERNAL | FILE_CONTROLLED_LINK;
 | 
        
           |  |  | 165 |         $pickeroptions->accepted_types = $qa->get_question()->filetypeslist;
 | 
        
           |  |  | 166 |   | 
        
           |  |  | 167 |         $fm = new form_filemanager($pickeroptions);
 | 
        
           |  |  | 168 |         $fm->options->maxbytes = get_user_max_upload_file_size(
 | 
        
           |  |  | 169 |             $this->page->context,
 | 
        
           |  |  | 170 |             $CFG->maxbytes,
 | 
        
           |  |  | 171 |             $COURSE->maxbytes,
 | 
        
           |  |  | 172 |             $qa->get_question()->maxbytes
 | 
        
           |  |  | 173 |         );
 | 
        
           |  |  | 174 |         $filesrenderer = $this->page->get_renderer('core', 'files');
 | 
        
           |  |  | 175 |   | 
        
           |  |  | 176 |         $text = '';
 | 
        
           |  |  | 177 |         if (!empty($qa->get_question()->filetypeslist)) {
 | 
        
           |  |  | 178 |             $text = html_writer::tag('p', get_string('acceptedfiletypes', 'qtype_essay'));
 | 
        
           |  |  | 179 |             $filetypesutil = new \core_form\filetypes_util();
 | 
        
           |  |  | 180 |             $filetypes = $qa->get_question()->filetypeslist;
 | 
        
           |  |  | 181 |             $filetypedescriptions = $filetypesutil->describe_file_types($filetypes);
 | 
        
           |  |  | 182 |             $text .= $this->render_from_template('core_form/filetypes-descriptions', $filetypedescriptions);
 | 
        
           |  |  | 183 |         }
 | 
        
           |  |  | 184 |   | 
        
           |  |  | 185 |         $output = html_writer::start_tag('fieldset');
 | 
        
           |  |  | 186 |         $fileslabel = $options->add_question_identifier_to_label(get_string('answerfiles', 'qtype_essay'));
 | 
        
           | 1441 | ariadna | 187 |         $output .= html_writer::tag('legend', $fileslabel, ['class' => 'visually-hidden']);
 | 
        
           | 1 | efrain | 188 |         $output .= $filesrenderer->render($fm);
 | 
        
           |  |  | 189 |         $output .= html_writer::empty_tag('input', [
 | 
        
           |  |  | 190 |             'type' => 'hidden',
 | 
        
           |  |  | 191 |             'name' => $qa->get_qt_field_name('attachments'),
 | 
        
           |  |  | 192 |             'value' => $pickeroptions->itemid,
 | 
        
           |  |  | 193 |         ]);
 | 
        
           |  |  | 194 |         $output .= $text;
 | 
        
           |  |  | 195 |         $output .= html_writer::end_tag('fieldset');
 | 
        
           |  |  | 196 |   | 
        
           |  |  | 197 |         return $output;
 | 
        
           |  |  | 198 |     }
 | 
        
           |  |  | 199 |   | 
        
           |  |  | 200 |     public function manual_comment(question_attempt $qa, question_display_options $options) {
 | 
        
           |  |  | 201 |         if ($options->manualcomment != question_display_options::EDITABLE) {
 | 
        
           |  |  | 202 |             return '';
 | 
        
           |  |  | 203 |         }
 | 
        
           |  |  | 204 |   | 
        
           |  |  | 205 |         $question = $qa->get_question();
 | 
        
           |  |  | 206 |         return html_writer::nonempty_tag('div', $question->format_text(
 | 
        
           |  |  | 207 |                 $question->graderinfo, $question->graderinfoformat, $qa, 'qtype_essay',
 | 
        
           |  |  | 208 |                 'graderinfo', $question->id), array('class' => 'graderinfo'));
 | 
        
           |  |  | 209 |     }
 | 
        
           |  |  | 210 | }
 | 
        
           |  |  | 211 |   | 
        
           |  |  | 212 |   | 
        
           |  |  | 213 | /**
 | 
        
           |  |  | 214 |  * A base class to abstract out the differences between different type of
 | 
        
           |  |  | 215 |  * response format.
 | 
        
           |  |  | 216 |  *
 | 
        
           |  |  | 217 |  * @copyright  2011 The Open University
 | 
        
           |  |  | 218 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 219 |  */
 | 
        
           |  |  | 220 | abstract class qtype_essay_format_renderer_base extends plugin_renderer_base {
 | 
        
           |  |  | 221 |   | 
        
           |  |  | 222 |     /** @var question_display_options Question display options instance for any necessary information for rendering the question. */
 | 
        
           |  |  | 223 |     protected $displayoptions;
 | 
        
           |  |  | 224 |   | 
        
           |  |  | 225 |     /**
 | 
        
           |  |  | 226 |      * Question number setter.
 | 
        
           |  |  | 227 |      *
 | 
        
           |  |  | 228 |      * @param question_display_options $displayoptions
 | 
        
           |  |  | 229 |      */
 | 
        
           |  |  | 230 |     public function set_displayoptions(question_display_options $displayoptions): void {
 | 
        
           |  |  | 231 |         $this->displayoptions = $displayoptions;
 | 
        
           |  |  | 232 |     }
 | 
        
           |  |  | 233 |   | 
        
           |  |  | 234 |     /**
 | 
        
           |  |  | 235 |      * Render the students respone when the question is in read-only mode.
 | 
        
           |  |  | 236 |      * @param string $name the variable name this input edits.
 | 
        
           |  |  | 237 |      * @param question_attempt $qa the question attempt being display.
 | 
        
           |  |  | 238 |      * @param question_attempt_step $step the current step.
 | 
        
           |  |  | 239 |      * @param int $lines approximate size of input box to display.
 | 
        
           |  |  | 240 |      * @param object $context the context teh output belongs to.
 | 
        
           |  |  | 241 |      * @return string html to display the response.
 | 
        
           |  |  | 242 |      */
 | 
        
           |  |  | 243 |     abstract public function response_area_read_only($name, question_attempt $qa,
 | 
        
           |  |  | 244 |             question_attempt_step $step, $lines, $context);
 | 
        
           |  |  | 245 |   | 
        
           |  |  | 246 |     /**
 | 
        
           |  |  | 247 |      * Render the students respone when the question is in read-only mode.
 | 
        
           |  |  | 248 |      * @param string $name the variable name this input edits.
 | 
        
           |  |  | 249 |      * @param question_attempt $qa the question attempt being display.
 | 
        
           |  |  | 250 |      * @param question_attempt_step $step the current step.
 | 
        
           |  |  | 251 |      * @param int $lines approximate size of input box to display.
 | 
        
           |  |  | 252 |      * @param object $context the context teh output belongs to.
 | 
        
           |  |  | 253 |      * @return string html to display the response for editing.
 | 
        
           |  |  | 254 |      */
 | 
        
           |  |  | 255 |     abstract public function response_area_input($name, question_attempt $qa,
 | 
        
           |  |  | 256 |             question_attempt_step $step, $lines, $context);
 | 
        
           |  |  | 257 |   | 
        
           |  |  | 258 |     /**
 | 
        
           |  |  | 259 |      * @return string specific class name to add to the input element.
 | 
        
           |  |  | 260 |      */
 | 
        
           |  |  | 261 |     abstract protected function class_name();
 | 
        
           |  |  | 262 | }
 | 
        
           |  |  | 263 |   | 
        
           |  |  | 264 | /**
 | 
        
           |  |  | 265 |  * An essay format renderer for essays where the student should not enter
 | 
        
           |  |  | 266 |  * any inline response.
 | 
        
           |  |  | 267 |  *
 | 
        
           |  |  | 268 |  * @copyright  2013 Binghamton University
 | 
        
           |  |  | 269 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 270 |  */
 | 
        
           |  |  | 271 | class qtype_essay_format_noinline_renderer extends qtype_essay_format_renderer_base {
 | 
        
           |  |  | 272 |   | 
        
           |  |  | 273 |     protected function class_name() {
 | 
        
           |  |  | 274 |         return 'qtype_essay_noinline';
 | 
        
           |  |  | 275 |     }
 | 
        
           |  |  | 276 |   | 
        
           |  |  | 277 |     public function response_area_read_only($name, $qa, $step, $lines, $context) {
 | 
        
           |  |  | 278 |         return '';
 | 
        
           |  |  | 279 |     }
 | 
        
           |  |  | 280 |   | 
        
           |  |  | 281 |     public function response_area_input($name, $qa, $step, $lines, $context) {
 | 
        
           |  |  | 282 |         return '';
 | 
        
           |  |  | 283 |     }
 | 
        
           |  |  | 284 |   | 
        
           |  |  | 285 | }
 | 
        
           |  |  | 286 |   | 
        
           |  |  | 287 | /**
 | 
        
           |  |  | 288 |  * An essay format renderer for essays where the student should use the HTML
 | 
        
           |  |  | 289 |  * editor without the file picker.
 | 
        
           |  |  | 290 |  *
 | 
        
           |  |  | 291 |  * @copyright  2011 The Open University
 | 
        
           |  |  | 292 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 293 |  */
 | 
        
           |  |  | 294 | class qtype_essay_format_editor_renderer extends qtype_essay_format_renderer_base {
 | 
        
           |  |  | 295 |     protected function class_name() {
 | 
        
           |  |  | 296 |         return 'qtype_essay_editor';
 | 
        
           |  |  | 297 |     }
 | 
        
           |  |  | 298 |   | 
        
           |  |  | 299 |     public function response_area_read_only($name, $qa, $step, $lines, $context) {
 | 
        
           |  |  | 300 |         $labelbyid = $qa->get_qt_field_name($name) . '_label';
 | 
        
           |  |  | 301 |   | 
        
           |  |  | 302 |         $responselabel = $this->displayoptions->add_question_identifier_to_label(get_string('answertext', 'qtype_essay'));
 | 
        
           | 1441 | ariadna | 303 |         $output = html_writer::tag('h4', $responselabel, ['id' => $labelbyid, 'class' => 'visually-hidden']);
 | 
        
           | 1 | efrain | 304 |         $output .= html_writer::tag('div', $this->prepare_response($name, $qa, $step, $context), [
 | 
        
           |  |  | 305 |             'role' => 'textbox',
 | 
        
           |  |  | 306 |             'aria-readonly' => 'true',
 | 
        
           |  |  | 307 |             'aria-labelledby' => $labelbyid,
 | 
        
           |  |  | 308 |             'class' => $this->class_name() . ' qtype_essay_response readonly',
 | 
        
           |  |  | 309 |             'style' => 'min-height: ' . ($lines * 1.5) . 'em;',
 | 
        
           |  |  | 310 |         ]);
 | 
        
           |  |  | 311 |         // Height $lines * 1.5 because that is a typical line-height on web pages.
 | 
        
           |  |  | 312 |         // That seems to give results that look OK.
 | 
        
           |  |  | 313 |   | 
        
           |  |  | 314 |         return $output;
 | 
        
           |  |  | 315 |     }
 | 
        
           |  |  | 316 |   | 
        
           |  |  | 317 |     public function response_area_input($name, $qa, $step, $lines, $context) {
 | 
        
           |  |  | 318 |         global $CFG;
 | 
        
           |  |  | 319 |         require_once($CFG->dirroot . '/repository/lib.php');
 | 
        
           |  |  | 320 |   | 
        
           |  |  | 321 |         $inputname = $qa->get_qt_field_name($name);
 | 
        
           |  |  | 322 |         $responseformat = $step->get_qt_var($name . 'format');
 | 
        
           |  |  | 323 |         $id = $inputname . '_id';
 | 
        
           |  |  | 324 |   | 
        
           |  |  | 325 |         $editor = editors_get_preferred_editor($responseformat);
 | 
        
           |  |  | 326 |         $strformats = format_text_menu();
 | 
        
           |  |  | 327 |         $formats = $editor->get_supported_formats();
 | 
        
           |  |  | 328 |         foreach ($formats as $fid) {
 | 
        
           |  |  | 329 |             $formats[$fid] = $strformats[$fid];
 | 
        
           |  |  | 330 |         }
 | 
        
           |  |  | 331 |   | 
        
           |  |  | 332 |         list($draftitemid, $response) = $this->prepare_response_for_editing(
 | 
        
           |  |  | 333 |                 $name, $step, $context);
 | 
        
           |  |  | 334 |   | 
        
           |  |  | 335 |         $editor->set_text($response);
 | 
        
           |  |  | 336 |         $editor->use_editor($id, $this->get_editor_options($context),
 | 
        
           |  |  | 337 |                 $this->get_filepicker_options($context, $draftitemid));
 | 
        
           |  |  | 338 |   | 
        
           |  |  | 339 |         $responselabel = $this->displayoptions->add_question_identifier_to_label(get_string('answertext', 'qtype_essay'));
 | 
        
           |  |  | 340 |         $output = html_writer::tag('label', $responselabel, [
 | 
        
           | 1441 | ariadna | 341 |             'class' => 'visually-hidden',
 | 
        
           | 1 | efrain | 342 |             'for' => $id,
 | 
        
           |  |  | 343 |         ]);
 | 
        
           |  |  | 344 |         $output .= html_writer::start_tag('div', array('class' =>
 | 
        
           |  |  | 345 |                 $this->class_name() . ' qtype_essay_response'));
 | 
        
           |  |  | 346 |   | 
        
           |  |  | 347 |         $output .= html_writer::tag('div', html_writer::tag('textarea', s($response),
 | 
        
           |  |  | 348 |                 array('id' => $id, 'name' => $inputname, 'rows' => $lines, 'cols' => 60, 'class' => 'form-control')));
 | 
        
           |  |  | 349 |   | 
        
           |  |  | 350 |         $output .= html_writer::start_tag('div');
 | 
        
           |  |  | 351 |         if (count($formats) == 1) {
 | 
        
           |  |  | 352 |             reset($formats);
 | 
        
           |  |  | 353 |             $output .= html_writer::empty_tag('input', array('type' => 'hidden',
 | 
        
           |  |  | 354 |                     'name' => $inputname . 'format', 'value' => key($formats)));
 | 
        
           |  |  | 355 |   | 
        
           |  |  | 356 |         } else {
 | 
        
           |  |  | 357 |             $output .= html_writer::label(get_string('format'), 'menu' . $inputname . 'format', false);
 | 
        
           |  |  | 358 |             $output .= ' ';
 | 
        
           |  |  | 359 |             $output .= html_writer::select($formats, $inputname . 'format', $responseformat, '');
 | 
        
           |  |  | 360 |         }
 | 
        
           |  |  | 361 |         $output .= html_writer::end_tag('div');
 | 
        
           |  |  | 362 |   | 
        
           |  |  | 363 |         $output .= $this->filepicker_html($inputname, $draftitemid);
 | 
        
           |  |  | 364 |   | 
        
           |  |  | 365 |         $output .= html_writer::end_tag('div');
 | 
        
           |  |  | 366 |         return $output;
 | 
        
           |  |  | 367 |     }
 | 
        
           |  |  | 368 |   | 
        
           |  |  | 369 |     /**
 | 
        
           |  |  | 370 |      * Prepare the response for read-only display.
 | 
        
           |  |  | 371 |      * @param string $name the variable name this input edits.
 | 
        
           |  |  | 372 |      * @param question_attempt $qa the question attempt being display.
 | 
        
           |  |  | 373 |      * @param question_attempt_step $step the current step.
 | 
        
           |  |  | 374 |      * @param object $context the context the attempt belongs to.
 | 
        
           |  |  | 375 |      * @return string the response prepared for display.
 | 
        
           |  |  | 376 |      */
 | 
        
           |  |  | 377 |     protected function prepare_response($name, question_attempt $qa,
 | 
        
           |  |  | 378 |             question_attempt_step $step, $context) {
 | 
        
           |  |  | 379 |         if (!$step->has_qt_var($name)) {
 | 
        
           |  |  | 380 |             return '';
 | 
        
           |  |  | 381 |         }
 | 
        
           |  |  | 382 |   | 
        
           |  |  | 383 |         $formatoptions = new stdClass();
 | 
        
           |  |  | 384 |         $formatoptions->para = false;
 | 
        
           |  |  | 385 |         return format_text($step->get_qt_var($name), $step->get_qt_var($name . 'format'),
 | 
        
           |  |  | 386 |                 $formatoptions);
 | 
        
           |  |  | 387 |     }
 | 
        
           |  |  | 388 |   | 
        
           |  |  | 389 |     /**
 | 
        
           |  |  | 390 |      * Prepare the response for editing.
 | 
        
           |  |  | 391 |      * @param string $name the variable name this input edits.
 | 
        
           |  |  | 392 |      * @param question_attempt_step $step the current step.
 | 
        
           |  |  | 393 |      * @param object $context the context the attempt belongs to.
 | 
        
           |  |  | 394 |      * @return string the response prepared for display.
 | 
        
           |  |  | 395 |      */
 | 
        
           |  |  | 396 |     protected function prepare_response_for_editing($name,
 | 
        
           |  |  | 397 |             question_attempt_step $step, $context) {
 | 
        
           |  |  | 398 |         return array(0, $step->get_qt_var($name));
 | 
        
           |  |  | 399 |     }
 | 
        
           |  |  | 400 |   | 
        
           |  |  | 401 |     /**
 | 
        
           |  |  | 402 |      * @param object $context the context the attempt belongs to.
 | 
        
           |  |  | 403 |      * @return array options for the editor.
 | 
        
           |  |  | 404 |      */
 | 
        
           |  |  | 405 |     protected function get_editor_options($context) {
 | 
        
           |  |  | 406 |         // Disable the text-editor autosave because quiz has it's own auto save function.
 | 
        
           |  |  | 407 |         return array('context' => $context, 'autosave' => false);
 | 
        
           |  |  | 408 |     }
 | 
        
           |  |  | 409 |   | 
        
           |  |  | 410 |     /**
 | 
        
           |  |  | 411 |      * @param object $context the context the attempt belongs to.
 | 
        
           |  |  | 412 |      * @param int $draftitemid draft item id.
 | 
        
           |  |  | 413 |      * @return array filepicker options for the editor.
 | 
        
           |  |  | 414 |      */
 | 
        
           |  |  | 415 |     protected function get_filepicker_options($context, $draftitemid) {
 | 
        
           |  |  | 416 |         return array('return_types'  => FILE_INTERNAL | FILE_EXTERNAL);
 | 
        
           |  |  | 417 |     }
 | 
        
           |  |  | 418 |   | 
        
           |  |  | 419 |     /**
 | 
        
           |  |  | 420 |      * @param string $inputname input field name.
 | 
        
           |  |  | 421 |      * @param int $draftitemid draft file area itemid.
 | 
        
           |  |  | 422 |      * @return string HTML for the filepicker, if used.
 | 
        
           |  |  | 423 |      */
 | 
        
           |  |  | 424 |     protected function filepicker_html($inputname, $draftitemid) {
 | 
        
           |  |  | 425 |         return '';
 | 
        
           |  |  | 426 |     }
 | 
        
           |  |  | 427 | }
 | 
        
           |  |  | 428 |   | 
        
           |  |  | 429 |   | 
        
           |  |  | 430 | /**
 | 
        
           |  |  | 431 |  * An essay format renderer for essays where the student should use the HTML
 | 
        
           |  |  | 432 |  * editor with the file picker.
 | 
        
           |  |  | 433 |  *
 | 
        
           |  |  | 434 |  * @copyright  2011 The Open University
 | 
        
           |  |  | 435 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 436 |  */
 | 
        
           |  |  | 437 | class qtype_essay_format_editorfilepicker_renderer extends qtype_essay_format_editor_renderer {
 | 
        
           |  |  | 438 |     protected function class_name() {
 | 
        
           |  |  | 439 |         return 'qtype_essay_editorfilepicker';
 | 
        
           |  |  | 440 |     }
 | 
        
           |  |  | 441 |   | 
        
           |  |  | 442 |     protected function prepare_response($name, question_attempt $qa,
 | 
        
           |  |  | 443 |             question_attempt_step $step, $context) {
 | 
        
           |  |  | 444 |         if (!$step->has_qt_var($name)) {
 | 
        
           |  |  | 445 |             return '';
 | 
        
           |  |  | 446 |         }
 | 
        
           |  |  | 447 |   | 
        
           |  |  | 448 |         $formatoptions = new stdClass();
 | 
        
           |  |  | 449 |         $formatoptions->para = false;
 | 
        
           |  |  | 450 |         $text = $qa->rewrite_response_pluginfile_urls($step->get_qt_var($name),
 | 
        
           |  |  | 451 |                 $context->id, 'answer', $step);
 | 
        
           |  |  | 452 |         return format_text($text, $step->get_qt_var($name . 'format'), $formatoptions);
 | 
        
           |  |  | 453 |     }
 | 
        
           |  |  | 454 |   | 
        
           |  |  | 455 |     protected function prepare_response_for_editing($name,
 | 
        
           |  |  | 456 |             question_attempt_step $step, $context) {
 | 
        
           |  |  | 457 |         return $step->prepare_response_files_draft_itemid_with_text(
 | 
        
           |  |  | 458 |                 $name, $context->id, $step->get_qt_var($name));
 | 
        
           |  |  | 459 |     }
 | 
        
           |  |  | 460 |   | 
        
           |  |  | 461 |     /**
 | 
        
           |  |  | 462 |      * Get editor options for question response text area.
 | 
        
           |  |  | 463 |      * @param object $context the context the attempt belongs to.
 | 
        
           |  |  | 464 |      * @return array options for the editor.
 | 
        
           |  |  | 465 |      */
 | 
        
           |  |  | 466 |     protected function get_editor_options($context) {
 | 
        
           |  |  | 467 |         return question_utils::get_editor_options($context);
 | 
        
           |  |  | 468 |     }
 | 
        
           |  |  | 469 |   | 
        
           |  |  | 470 |     /**
 | 
        
           |  |  | 471 |      * Get the options required to configure the filepicker for one of the editor
 | 
        
           |  |  | 472 |      * toolbar buttons.
 | 
        
           |  |  | 473 |      * @deprecated since 3.5
 | 
        
           |  |  | 474 |      * @param mixed $acceptedtypes array of types of '*'.
 | 
        
           |  |  | 475 |      * @param int $draftitemid the draft area item id.
 | 
        
           |  |  | 476 |      * @param object $context the context.
 | 
        
           |  |  | 477 |      * @return object the required options.
 | 
        
           |  |  | 478 |      */
 | 
        
           |  |  | 479 |     protected function specific_filepicker_options($acceptedtypes, $draftitemid, $context) {
 | 
        
           |  |  | 480 |         debugging('qtype_essay_format_editorfilepicker_renderer::specific_filepicker_options() is deprecated, ' .
 | 
        
           |  |  | 481 |             'use question_utils::specific_filepicker_options() instead.', DEBUG_DEVELOPER);
 | 
        
           |  |  | 482 |   | 
        
           |  |  | 483 |         $filepickeroptions = new stdClass();
 | 
        
           |  |  | 484 |         $filepickeroptions->accepted_types = $acceptedtypes;
 | 
        
           |  |  | 485 |         $filepickeroptions->return_types = FILE_INTERNAL | FILE_EXTERNAL;
 | 
        
           |  |  | 486 |         $filepickeroptions->context = $context;
 | 
        
           |  |  | 487 |         $filepickeroptions->env = 'filepicker';
 | 
        
           |  |  | 488 |   | 
        
           |  |  | 489 |         $options = initialise_filepicker($filepickeroptions);
 | 
        
           |  |  | 490 |         $options->context = $context;
 | 
        
           |  |  | 491 |         $options->client_id = uniqid();
 | 
        
           |  |  | 492 |         $options->env = 'editor';
 | 
        
           |  |  | 493 |         $options->itemid = $draftitemid;
 | 
        
           |  |  | 494 |   | 
        
           |  |  | 495 |         return $options;
 | 
        
           |  |  | 496 |     }
 | 
        
           |  |  | 497 |   | 
        
           |  |  | 498 |     /**
 | 
        
           |  |  | 499 |      * @param object $context the context the attempt belongs to.
 | 
        
           |  |  | 500 |      * @param int $draftitemid draft item id.
 | 
        
           |  |  | 501 |      * @return array filepicker options for the editor.
 | 
        
           |  |  | 502 |      */
 | 
        
           |  |  | 503 |     protected function get_filepicker_options($context, $draftitemid) {
 | 
        
           |  |  | 504 |         return question_utils::get_filepicker_options($context, $draftitemid);
 | 
        
           |  |  | 505 |     }
 | 
        
           |  |  | 506 |   | 
        
           |  |  | 507 |     protected function filepicker_html($inputname, $draftitemid) {
 | 
        
           |  |  | 508 |         $nonjspickerurl = new moodle_url('/repository/draftfiles_manager.php', array(
 | 
        
           |  |  | 509 |             'action' => 'browse',
 | 
        
           |  |  | 510 |             'env' => 'editor',
 | 
        
           |  |  | 511 |             'itemid' => $draftitemid,
 | 
        
           |  |  | 512 |             'subdirs' => false,
 | 
        
           |  |  | 513 |             'maxfiles' => -1,
 | 
        
           |  |  | 514 |             'sesskey' => sesskey(),
 | 
        
           |  |  | 515 |         ));
 | 
        
           |  |  | 516 |   | 
        
           |  |  | 517 |         return html_writer::empty_tag('input', array('type' => 'hidden',
 | 
        
           |  |  | 518 |                 'name' => $inputname . ':itemid', 'value' => $draftitemid)) .
 | 
        
           |  |  | 519 |                 html_writer::tag('noscript', html_writer::tag('div',
 | 
        
           |  |  | 520 |                     html_writer::tag('object', '', array('type' => 'text/html',
 | 
        
           |  |  | 521 |                         'data' => $nonjspickerurl, 'height' => 160, 'width' => 600,
 | 
        
           |  |  | 522 |                         'style' => 'border: 1px solid #000;'))));
 | 
        
           |  |  | 523 |     }
 | 
        
           |  |  | 524 | }
 | 
        
           |  |  | 525 |   | 
        
           |  |  | 526 |   | 
        
           |  |  | 527 | /**
 | 
        
           |  |  | 528 |  * An essay format renderer for essays where the student should use a plain
 | 
        
           |  |  | 529 |  * input box, but with a normal, proportional font.
 | 
        
           |  |  | 530 |  *
 | 
        
           |  |  | 531 |  * @copyright  2011 The Open University
 | 
        
           |  |  | 532 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 533 |  */
 | 
        
           |  |  | 534 | class qtype_essay_format_plain_renderer extends qtype_essay_format_renderer_base {
 | 
        
           |  |  | 535 |     /**
 | 
        
           |  |  | 536 |      * @return string the HTML for the textarea.
 | 
        
           |  |  | 537 |      */
 | 
        
           |  |  | 538 |     protected function textarea($response, $lines, $attributes) {
 | 
        
           |  |  | 539 |         $attributes['class'] = $this->class_name() . ' qtype_essay_response form-control';
 | 
        
           |  |  | 540 |         $attributes['rows'] = $lines;
 | 
        
           |  |  | 541 |         $attributes['cols'] = 60;
 | 
        
           |  |  | 542 |         return html_writer::tag('textarea', s($response), $attributes);
 | 
        
           |  |  | 543 |     }
 | 
        
           |  |  | 544 |   | 
        
           |  |  | 545 |     protected function class_name() {
 | 
        
           |  |  | 546 |         return 'qtype_essay_plain';
 | 
        
           |  |  | 547 |     }
 | 
        
           |  |  | 548 |   | 
        
           |  |  | 549 |     public function response_area_read_only($name, $qa, $step, $lines, $context) {
 | 
        
           |  |  | 550 |         $id = $qa->get_qt_field_name($name) . '_id';
 | 
        
           |  |  | 551 |   | 
        
           |  |  | 552 |         $responselabel = $this->displayoptions->add_question_identifier_to_label(get_string('answertext', 'qtype_essay'));
 | 
        
           | 1441 | ariadna | 553 |         $output = html_writer::tag('label', $responselabel, ['class' => 'visually-hidden', 'for' => $id]);
 | 
        
           | 1 | efrain | 554 |         $output .= $this->textarea($step->get_qt_var($name), $lines, ['id' => $id, 'readonly' => 'readonly']);
 | 
        
           |  |  | 555 |         return $output;
 | 
        
           |  |  | 556 |     }
 | 
        
           |  |  | 557 |   | 
        
           |  |  | 558 |     public function response_area_input($name, $qa, $step, $lines, $context) {
 | 
        
           |  |  | 559 |         $inputname = $qa->get_qt_field_name($name);
 | 
        
           |  |  | 560 |         $id = $inputname . '_id';
 | 
        
           |  |  | 561 |   | 
        
           |  |  | 562 |         $responselabel = $this->displayoptions->add_question_identifier_to_label(get_string('answertext', 'qtype_essay'));
 | 
        
           | 1441 | ariadna | 563 |         $output = html_writer::tag('label', $responselabel, ['class' => 'visually-hidden', 'for' => $id]);
 | 
        
           | 1 | efrain | 564 |         $output .= $this->textarea($step->get_qt_var($name), $lines, ['name' => $inputname, 'id' => $id]);
 | 
        
           |  |  | 565 |         $output .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => $inputname . 'format', 'value' => FORMAT_PLAIN]);
 | 
        
           |  |  | 566 |   | 
        
           |  |  | 567 |         return $output;
 | 
        
           |  |  | 568 |     }
 | 
        
           |  |  | 569 | }
 | 
        
           |  |  | 570 |   | 
        
           |  |  | 571 |   | 
        
           |  |  | 572 | /**
 | 
        
           |  |  | 573 |  * An essay format renderer for essays where the student should use a plain
 | 
        
           |  |  | 574 |  * input box with a monospaced font. You might use this, for example, for a
 | 
        
           |  |  | 575 |  * question where the students should type computer code.
 | 
        
           |  |  | 576 |  *
 | 
        
           |  |  | 577 |  * @copyright  2011 The Open University
 | 
        
           |  |  | 578 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 579 |  */
 | 
        
           |  |  | 580 | class qtype_essay_format_monospaced_renderer extends qtype_essay_format_plain_renderer {
 | 
        
           |  |  | 581 |     protected function class_name() {
 | 
        
           |  |  | 582 |         return 'qtype_essay_monospaced';
 | 
        
           |  |  | 583 |     }
 | 
        
           |  |  | 584 | }
 |