See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]
1 <?php 2 /////////////////////////////////////////////////////////////////////////// 3 // // 4 // NOTICE OF COPYRIGHT // 5 // // 6 // Moodle - Modular Object-Oriented Dynamic Learning Environment // 7 // http://moodle.org // 8 // // 9 // Copyright (C) 1999-onwards Moodle Pty Ltd http://moodle.com // 10 // // 11 // This program is free software; you can redistribute it and/or modify // 12 // it under the terms of the GNU General Public License as published by // 13 // the Free Software Foundation; either version 2 of the License, or // 14 // (at your option) any later version. // // // 15 // This program is distributed in the hope that it will be useful, // 16 // but WITHOUT ANY WARRANTY; without even the implied warranty of // 17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // 18 // GNU General Public License for more details: // 19 // // 20 // http://www.gnu.org/copyleft/gpl.html // 21 // // 22 /////////////////////////////////////////////////////////////////////////// 23 24 defined('MOODLE_INTERNAL') || die(); 25 26 global $CFG; 27 28 require_once($CFG->dirroot.'/lib/filelib.php'); 29 require_once($CFG->dirroot.'/repository/lib.php'); 30 31 class data_field_textarea extends data_field_base { 32 33 var $type = 'textarea'; 34 /** 35 * priority for globalsearch indexing 36 * 37 * @var int 38 */ 39 protected static $priority = self::LOW_PRIORITY; 40 41 public function supports_preview(): bool { 42 return true; 43 } 44 45 public function get_data_content_preview(int $recordid): stdClass { 46 return (object)[ 47 'id' => 0, 48 'fieldid' => $this->field->id, 49 'recordid' => $recordid, 50 'content' => get_string('sample', 'datafield_textarea'), 51 'content1' => 1, 52 'content2' => null, 53 'content3' => null, 54 'content4' => null, 55 ]; 56 } 57 58 /** 59 * Returns options for embedded files 60 * 61 * @return array 62 */ 63 private function get_options() { 64 if (!isset($this->field->param5)) { 65 $this->field->param5 = 0; 66 } 67 $options = array(); 68 $options['trusttext'] = false; 69 $options['forcehttps'] = false; 70 $options['subdirs'] = false; 71 $options['maxfiles'] = -1; 72 $options['context'] = $this->context; 73 $options['maxbytes'] = $this->field->param5; 74 $options['changeformat'] = 0; 75 $options['noclean'] = false; 76 return $options; 77 } 78 79 function display_add_field($recordid = 0, $formdata = null) { 80 global $CFG, $DB, $OUTPUT, $PAGE; 81 82 $text = ''; 83 $format = 0; 84 $str = '<div title="' . s($this->field->description) . '" class="d-inline-flex">'; 85 $str .= '<label for="field_' . $this->field->id . '">'; 86 $str .= html_writer::span($this->field->name, 'accesshide'); 87 if ($this->field->required) { 88 $image = $OUTPUT->pix_icon('req', get_string('requiredelement', 'form')); 89 $str .= html_writer::div($image, 'inline-req'); 90 } 91 $str .= '</label>'; 92 93 editors_head_setup(); 94 $options = $this->get_options(); 95 96 $itemid = $this->field->id; 97 $field = 'field_'.$itemid; 98 99 if ($formdata) { 100 $fieldname = 'field_' . $this->field->id . '_content1'; 101 if (isset($formdata->$fieldname)) { 102 $format = $formdata->$fieldname; 103 } else { 104 $format = file_get_unused_draft_itemid(); 105 } 106 $fieldname = 'field_' . $this->field->id . '_itemid'; 107 if (isset($formdata->$fieldname)) { 108 $draftitemid = clean_param($formdata->$fieldname, PARAM_INT); 109 } else { 110 $draftitemid = file_get_unused_draft_itemid(); 111 } 112 $fieldname = 'field_' . $this->field->id; 113 if (isset($formdata->$fieldname)) { 114 $text = $formdata->$fieldname; 115 } 116 } else if ($recordid && 117 $content = $DB->get_record('data_content', array('fieldid' => $this->field->id, 'recordid' => $recordid))) { 118 $format = $content->content1; 119 $text = clean_text($content->content, $format); 120 $text = file_prepare_draft_area($draftitemid, $this->context->id, 'mod_data', 'content', $content->id, $options, $text); 121 } else { 122 $draftitemid = file_get_unused_draft_itemid(); 123 $format = editors_get_preferred_format(); 124 } 125 126 // get filepicker info 127 // 128 $fpoptions = array(); 129 if ($options['maxfiles'] != 0 ) { 130 $args = new stdClass(); 131 // need these three to filter repositories list 132 $args->accepted_types = array('web_image'); 133 $args->return_types = (FILE_INTERNAL | FILE_EXTERNAL); 134 $args->context = $this->context; 135 $args->env = 'filepicker'; 136 // advimage plugin 137 $image_options = initialise_filepicker($args); 138 $image_options->context = $this->context; 139 $image_options->client_id = uniqid(); 140 $image_options->maxbytes = $options['maxbytes']; 141 $image_options->env = 'editor'; 142 $image_options->itemid = $draftitemid; 143 144 // moodlemedia plugin 145 $args->accepted_types = array('video', 'audio'); 146 $media_options = initialise_filepicker($args); 147 $media_options->context = $this->context; 148 $media_options->client_id = uniqid(); 149 $media_options->maxbytes = $options['maxbytes']; 150 $media_options->env = 'editor'; 151 $media_options->itemid = $draftitemid; 152 153 // advlink plugin 154 $args->accepted_types = '*'; 155 $link_options = initialise_filepicker($args); 156 $link_options->context = $this->context; 157 $link_options->client_id = uniqid(); 158 $link_options->maxbytes = $options['maxbytes']; 159 $link_options->env = 'editor'; 160 $link_options->itemid = $draftitemid; 161 162 // H5P plugin. 163 $args->accepted_types = ['h5p']; 164 $h5poptions = initialise_filepicker($args); 165 $h5poptions->context = $this->context; 166 $h5poptions->client_id = uniqid(); 167 $h5poptions->maxbytes = $options['maxbytes']; 168 $h5poptions->env = 'editor'; 169 $h5poptions->itemid = $draftitemid; 170 171 $fpoptions['image'] = $image_options; 172 $fpoptions['media'] = $media_options; 173 $fpoptions['link'] = $link_options; 174 $fpoptions['h5p'] = $h5poptions; 175 } 176 177 $editor = editors_get_preferred_editor($format); 178 $strformats = format_text_menu(); 179 $formats = $editor->get_supported_formats(); 180 foreach ($formats as $fid) { 181 $formats[$fid] = $strformats[$fid]; 182 } 183 $editor->set_text($text); 184 $editor->use_editor($field, $options, $fpoptions); 185 $str .= '<input type="hidden" name="'.$field.'_itemid" value="'.s($draftitemid).'" />'; 186 $str .= '<div class="mod-data-input">'; 187 $str .= '<div><textarea id="'.$field.'" name="'.$field.'" rows="'.$this->field->param3.'" class="form-control" ' . 188 'cols="'.$this->field->param2.'" spellcheck="true">'.s($text).'</textarea></div>'; 189 $str .= '<div><label class="accesshide" for="' . $field . '_content1">' . get_string('format') . '</label>'; 190 $str .= '<select id="' . $field . '_content1" name="'.$field.'_content1">'; 191 foreach ($formats as $key=>$desc) { 192 $selected = ($format == $key) ? 'selected="selected"' : ''; 193 $str .= '<option value="'.s($key).'" '.$selected.'>'.$desc.'</option>'; 194 } 195 $str .= '</select>'; 196 197 $str .= '</div>'; 198 $str .= '</div>'; 199 $str .= '</div>'; 200 return $str; 201 } 202 203 204 function display_search_field($value = '') { 205 return '<label class="accesshide" for="f_' . $this->field->id . '">' . $this->field->name . '</label>' . 206 '<input type="text" size="16" id="f_' . $this->field->id . '" name="f_' . $this->field->id . '" ' . 207 'value="' . s($value) . '" class="form-control"/>'; 208 } 209 210 public function parse_search_field($defaults = null) { 211 $param = 'f_'.$this->field->id; 212 if (empty($defaults[$param])) { 213 $defaults = array($param => ''); 214 } 215 return optional_param($param, $defaults[$param], PARAM_NOTAGS); 216 } 217 218 function generate_sql($tablealias, $value) { 219 global $DB; 220 221 static $i=0; 222 $i++; 223 $name = "df_textarea_$i"; 224 return array(" ({$tablealias}.fieldid = {$this->field->id} AND ".$DB->sql_like("{$tablealias}.content", ":$name", false).") ", array($name=>"%$value%")); 225 } 226 227 function print_after_form() { 228 } 229 230 231 function update_content($recordid, $value, $name='') { 232 global $DB; 233 234 $content = new stdClass(); 235 $content->fieldid = $this->field->id; 236 $content->recordid = $recordid; 237 238 $names = explode('_', $name); 239 if (!empty($names[2])) { 240 if ($names[2] == 'itemid') { 241 // the value will be retrieved by file_get_submitted_draft_itemid, do not need to save in DB 242 return true; 243 } else { 244 $content->{$names[2]} = clean_param($value, PARAM_NOTAGS); // content[1-4] 245 } 246 } else { 247 $content->content = clean_param($value, PARAM_CLEAN); 248 } 249 250 if ($oldcontent = $DB->get_record('data_content', array('fieldid'=>$this->field->id, 'recordid'=>$recordid))) { 251 $content->id = $oldcontent->id; 252 } else { 253 $content->id = $DB->insert_record('data_content', $content); 254 if (!$content->id) { 255 return false; 256 } 257 } 258 if (!empty($content->content)) { 259 $draftitemid = file_get_submitted_draft_itemid('field_'. $this->field->id. '_itemid'); 260 $options = $this->get_options(); 261 $content->content = file_save_draft_area_files($draftitemid, $this->context->id, 'mod_data', 'content', $content->id, $options, $content->content); 262 } 263 $rv = $DB->update_record('data_content', $content); 264 return $rv; 265 } 266 267 /** 268 * Display the content of the field in browse mode 269 * 270 * @param int $recordid 271 * @param object $template 272 * @return bool|string 273 */ 274 function display_browse_field($recordid, $template) { 275 $content = $this->get_data_content($recordid); 276 if (!$content || !isset($content->content)) { 277 return ''; 278 } 279 $options = new stdClass(); 280 if ($this->field->param1 == '1') { // We are autolinking this field, so disable linking within us. 281 $options->filter = false; 282 } 283 $options->para = false; 284 $str = file_rewrite_pluginfile_urls( 285 $content->content, 286 'pluginfile.php', 287 $this->context->id, 288 'mod_data', 289 'content', 290 $content->id, 291 $this->get_options() 292 ); 293 $str = format_text($str, $content->content1, $options); 294 return '<div class="data-field-html">' . $str . '</div>'; 295 } 296 297 /** 298 * Whether this module support files 299 * 300 * @param string $relativepath 301 * @return bool 302 */ 303 function file_ok($relativepath) { 304 return true; 305 } 306 307 /** 308 * Only look at the first item (second is format) 309 * 310 * @param string $value 311 * @param string $name 312 * @return bool 313 */ 314 function notemptyfield($value, $name) { 315 $names = explode('_', $name); 316 // Clean first. 317 if (count($names) == 2) { 318 // Don't assume that this is coming from a text editor with tags. 319 return strval($value) !== ''; 320 } 321 return false; 322 } 323 324 /** 325 * Returns the presentable string value for a field content. 326 * 327 * The returned string should be plain text. 328 * 329 * @param stdClass $content 330 * @return string 331 */ 332 public static function get_content_value($content) { 333 return content_to_text($content->content, $content->content1); 334 } 335 336 /** 337 * Return the plugin configs for external functions. 338 * 339 * @return array the list of config parameters 340 * @since Moodle 3.3 341 */ 342 public function get_config_for_external() { 343 // Return all the config parameters. 344 $configs = []; 345 for ($i = 1; $i <= 10; $i++) { 346 $configs["param$i"] = $this->field->{"param$i"}; 347 } 348 return $configs; 349 } 350 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body