MDL-30843 editor: Fixed up out of place if
[moodle.git] / lib / form / editor.php
CommitLineData
ae4a98a1 1<?php
6c1fd304
RT
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/**
19 * Editor input element
20 *
21 * Contains class to create preffered editor form element
22 *
23 * @package core_form
24 * @copyright 2009 Petr Skoda {@link http://skodak.org}
25 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 */
ae4a98a1 27
28global $CFG;
cefe1408 29
30require_once('HTML/QuickForm/element.php');
ae4a98a1 31require_once($CFG->dirroot.'/lib/filelib.php');
ad362539 32require_once($CFG->dirroot.'/repository/lib.php');
cefe1408 33
6c1fd304
RT
34/**
35 * Editor element
36 *
58b7d48f 37 * It creates preffered editor (textbox/TinyMce) form element for the format (Text/HTML) selected.
6c1fd304
RT
38 *
39 * @package core_form
40 * @category form
41 * @copyright 2009 Petr Skoda {@link http://skodak.org}
42 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
43 * @todo MDL-29421 element Freezing
44 * @todo MDL-29426 ajax format conversion
45 */
cefe1408 46class MoodleQuickForm_editor extends HTML_QuickForm_element {
6c1fd304 47 /** @var string html for help button, if empty then no help will icon will be dispalyed. */
12f11f23 48 public $_helpbutton = '';
775af58f 49
6c1fd304 50 /** @var string defines the type of editor */
775af58f 51 public $_type = 'editor';
6c1fd304
RT
52
53 /** @var array options provided to initalize filepicker */
69429650 54 protected $_options = array('subdirs'=>0, 'maxbytes'=>0, 'maxfiles'=>0, 'changeformat'=>0,
7de5a29a 55 'context'=>null, 'noclean'=>0, 'trusttext'=>0);
6c1fd304
RT
56
57 /** @var array values for editor */
cefe1408 58 protected $_values = array('text'=>null, 'format'=>null, 'itemid'=>null);
59
6c1fd304
RT
60 /**
61 * Constructor
62 *
63 * @param string $elementName (optional) name of the editor
64 * @param string $elementLabel (optional) editor label
65 * @param array $attributes (optional) Either a typical HTML attribute string
66 * or an associative array
67 * @param array $options set of options to initalize filepicker
68 */
34d39b79 69 function MoodleQuickForm_editor($elementName=null, $elementLabel=null, $attributes=null, $options=null) {
99eaca9d 70 global $CFG, $PAGE;
cefe1408 71
72 $options = (array)$options;
73 foreach ($options as $name=>$value) {
74 if (array_key_exists($name, $this->_options)) {
75 $this->_options[$name] = $value;
0b94f320 76 }
77 }
cefe1408 78 if (!empty($options['maxbytes'])) {
79 $this->_options['maxbytes'] = get_max_upload_file_size($CFG->maxbytes, $options['maxbytes']);
0b94f320 80 }
69429650 81 if (!$this->_options['context']) {
82 $this->_options['context'] = get_context_instance(CONTEXT_SYSTEM);
83 }
7de5a29a 84 $this->_options['trusted'] = trusttext_trusted($this->_options['context']);
cefe1408 85 parent::HTML_QuickForm_element($elementName, $elementLabel, $attributes);
ff5fe311 86
ff5fe311 87 editors_head_setup();
0b94f320 88 }
cefe1408 89
6c1fd304
RT
90 /**
91 * Sets name of editor
92 *
93 * @param string $name name of the editor
94 */
cefe1408 95 function setName($name) {
96 $this->updateAttributes(array('name'=>$name));
97 }
98
6c1fd304
RT
99 /**
100 * Returns name of element
101 *
102 * @return string
103 */
cefe1408 104 function getName() {
105 return $this->getAttribute('name');
106 }
107
6c1fd304
RT
108 /**
109 * Updates editor values, if part of $_values
58b7d48f 110 *
6c1fd304
RT
111 * @param array $values associative array of values to set
112 */
cefe1408 113 function setValue($values) {
114 $values = (array)$values;
115 foreach ($values as $name=>$value) {
116 if (array_key_exists($name, $this->_values)) {
117 $this->_values[$name] = $value;
0b94f320 118 }
119 }
0b94f320 120 }
121
6c1fd304
RT
122 /**
123 * Returns editor values
124 *
58b7d48f 125 * @return array
6c1fd304 126 */
cefe1408 127 function getValue() {
8367651e 128 return $this->_values;
cefe1408 129 }
130
6c1fd304
RT
131 /**
132 * Returns maximum file size which can be uploaded
133 *
134 * @return int
135 */
cefe1408 136 function getMaxbytes() {
137 return $this->_options['maxbytes'];
138 }
139
6c1fd304
RT
140 /**
141 * Sets maximum file size which can be uploaded
142 *
143 * @param int $maxbytes file size
144 */
cefe1408 145 function setMaxbytes($maxbytes) {
146 global $CFG;
147 $this->_options['maxbytes'] = get_max_upload_file_size($CFG->maxbytes, $maxbytes);
148 }
149
6c1fd304
RT
150 /**
151 * Returns maximum number of files which can be uploaded
152 *
153 * @return int
154 */
ac025043 155 function getMaxfiles() {
156 return $this->_options['maxfiles'];
157 }
158
6c1fd304
RT
159 /**
160 * Sets maximum number of files which can be uploaded.
161 *
162 * @param int $num number of files
163 */
ac025043 164 function setMaxfiles($num) {
165 $this->_options['maxfiles'] = $num;
166 }
167
6c1fd304
RT
168 /**
169 * Returns true if subdirectoy can be created, else false
170 *
171 * @return bool
172 */
cefe1408 173 function getSubdirs() {
174 return $this->_options['subdirs'];
175 }
176
6c1fd304
RT
177 /**
178 * Set option to create sub directory, while uploading file
179 *
180 * @param bool $allow true if sub directory can be created.
181 */
cefe1408 182 function setSubdirs($allow) {
183 $this->_options['subdirs'] = $allow;
184 }
185
ab978b38
RT
186 /**
187 * Returns editor format
188 *
189 * @return int.
190 */
191 function getFormat() {
192 return $this->_values['format'];
193 }
194
cbe20ec3 195 /**
6c1fd304 196 * Checks if editor used is a required field
cbe20ec3 197 *
6c1fd304 198 * @return bool true if required field.
cbe20ec3 199 */
ab978b38
RT
200 function isRequired() {
201 return (isset($this->_options['required']) && $this->_options['required']);
cbe20ec3
RT
202 }
203
6c1fd304
RT
204 /**
205 * Sets help button for editor
58b7d48f 206 *
6c1fd304
RT
207 * @param mixed $_helpbuttonargs arguments to create help button
208 * @param string $function name of the callback function
209 * @deprecated since Moodle 2.0. Please do not call this function any more.
210 * @todo MDL-31047 this api will be removed.
211 * @see MoodleQuickForm::setHelpButton()
212 */
cefe1408 213 function setHelpButton($_helpbuttonargs, $function='_helpbutton') {
214 if (!is_array($_helpbuttonargs)) {
215 $_helpbuttonargs = array($_helpbuttonargs);
216 } else {
217 $_helpbuttonargs = $_helpbuttonargs;
218 }
219 //we do this to to return html instead of printing it
220 //without having to specify it in every call to make a button.
221 if ('_helpbutton' == $function){
222 $defaultargs = array('', '', 'moodle', true, false, '', true);
223 $_helpbuttonargs = $_helpbuttonargs + $defaultargs ;
224 }
225 $this->_helpbutton=call_user_func_array($function, $_helpbuttonargs);
226 }
227
6c1fd304
RT
228 /**
229 * Returns html for help button.
230 *
231 * @return string html for help button
232 */
cefe1408 233 function getHelpButton() {
234 return $this->_helpbutton;
235 }
236
6c1fd304
RT
237 /**
238 * Returns type of editor element
239 *
240 * @return string
241 */
cefe1408 242 function getElementTemplateType() {
243 if ($this->_flagFrozen){
244 return 'nodisplay';
245 } else {
246 return 'default';
247 }
248 }
249
6c1fd304
RT
250 /**
251 * Returns HTML for editor form element.
252 *
253 * @return string
254 */
cefe1408 255 function toHtml() {
057815f3 256 global $CFG, $PAGE;
99eaca9d 257 require_once($CFG->dirroot.'/repository/lib.php');
cefe1408 258
0b94f320 259 if ($this->_flagFrozen) {
260 return $this->getFrozenHtml();
cefe1408 261 }
262
4c508047
PS
263 $ctx = $this->_options['context'];
264
cefe1408 265 $id = $this->_attributes['id'];
266 $elname = $this->_attributes['name'];
267
268 $subdirs = $this->_options['subdirs'];
269 $maxbytes = $this->_options['maxbytes'];
ac025043 270 $maxfiles = $this->_options['maxfiles'];
cefe1408 271 $changeformat = $this->_options['changeformat']; // TO DO: implement as ajax calls
272
273 $text = $this->_values['text'];
274 $format = $this->_values['format'];
7cdee748 275 $draftitemid = $this->_values['itemid'];
cefe1408 276
277 // security - never ever allow guest/not logged in user to upload anything
278 if (isguestuser() or !isloggedin()) {
ac025043 279 $maxfiles = 0;
cefe1408 280 }
281
282 $str = $this->_getTabs();
283 $str .= '<div>';
284
20e5da7d 285 $editor = editors_get_preferred_editor($format);
5ca3c838 286 $strformats = format_text_menu();
287 $formats = $editor->get_supported_formats();
288 foreach ($formats as $fid) {
289 $formats[$fid] = $strformats[$fid];
cefe1408 290 }
291
4c508047 292 // get filepicker info
875f4e7b
DC
293 //
294 $fpoptions = array();
4c508047
PS
295 if ($maxfiles != 0 ) {
296 if (empty($draftitemid)) {
297 // no existing area info provided - let's use fresh new draft area
298 require_once("$CFG->libdir/filelib.php");
299 $this->setValue(array('itemid'=>file_get_unused_draft_itemid()));
300 $draftitemid = $this->_values['itemid'];
301 }
302
6bdfef5d 303 $args = new stdClass();
4c508047 304 // need these three to filter repositories list
875f4e7b 305 $args->accepted_types = array('image');
4c508047
PS
306 $args->return_types = (FILE_INTERNAL | FILE_EXTERNAL);
307 $args->context = $ctx;
308 $args->env = 'filepicker';
a4d91438 309 // advimage plugin
875f4e7b 310 $image_options = initialise_filepicker($args);
766514a0
DC
311 $image_options->context = $ctx;
312 $image_options->client_id = uniqid();
313 $image_options->maxbytes = $this->_options['maxbytes'];
314 $image_options->env = 'editor';
315 $image_options->itemid = $draftitemid;
875f4e7b 316
a4d91438 317 // moodlemedia plugin
033aad78 318 $args->accepted_types = array('video', 'audio');
775af58f 319 $media_options = initialise_filepicker($args);
be85f7ab 320 $media_options->context = $ctx;
875f4e7b 321 $media_options->client_id = uniqid();
875f4e7b 322 $media_options->maxbytes = $this->_options['maxbytes'];
875f4e7b 323 $media_options->env = 'editor';
875f4e7b 324 $media_options->itemid = $draftitemid;
766514a0 325
a4d91438 326 // advlink plugin
766514a0
DC
327 $args->accepted_types = '*';
328 $link_options = initialise_filepicker($args);
329 $link_options->context = $ctx;
330 $link_options->client_id = uniqid();
331 $link_options->maxbytes = $this->_options['maxbytes'];
332 $link_options->env = 'editor';
333 $link_options->itemid = $draftitemid;
334
875f4e7b
DC
335 $fpoptions['image'] = $image_options;
336 $fpoptions['media'] = $media_options;
766514a0 337 $fpoptions['link'] = $link_options;
4c508047
PS
338 }
339
cbe20ec3
RT
340 //If editor is required and tinymce, then set required_tinymce option to initalize tinymce validation.
341 if (($editor instanceof tinymce_texteditor) && !is_null($this->getAttribute('onchange'))) {
ab978b38 342 $this->_options['required'] = true;
cbe20ec3
RT
343 }
344
58b7d48f 345 // print text area - TODO: add on-the-fly switching, size configuration, etc.
4c508047 346 $editor->use_editor($id, $this->_options, $fpoptions);
7cdee748 347
cb2c1963
PS
348 $rows = empty($this->_attributes['rows']) ? 15 : $this->_attributes['rows'];
349 $cols = empty($this->_attributes['cols']) ? 80 : $this->_attributes['cols'];
350
cbe20ec3 351 //Apply editor validation if required field
56728202
AO
352 $editorrules = '';
353 if (!is_null($this->getAttribute('onblur')) && !is_null($this->getAttribute('onchange'))) {
856484f9 354 $editorrules = ' onblur="'.htmlspecialchars($this->getAttribute('onblur')).'" onchange="'.htmlspecialchars($this->getAttribute('onchange')).'"';
56728202
AO
355 }
356 $str .= '<div><textarea id="'.$id.'" name="'.$elname.'[text]" rows="'.$rows.'" cols="'.$cols.'"'.$editorrules.'>';
e19dc11e 357 $str .= s($text);
7cdee748 358 $str .= '</textarea></div>';
359
cefe1408 360 $str .= '<div>';
5a1a7112 361 if (count($formats)>1) {
f9f281b8
RW
362 $str .= html_writer::label(get_string('format'), 'menu'. $elname. '[format]', false, array('class' => 'accesshide'));
363 $str .= html_writer::select($formats, $elname.'[format]', $format, false);
5a1a7112 364 } else {
fabbf439 365 $keys = array_keys($formats);
f9f281b8 366 $str .= html_writer::empty_tag('input',
fabbf439 367 array('name'=>$elname.'[format]', 'type'=> 'hidden', 'value' => array_pop($keys)));
cefe1408 368 }
369 $str .= '</div>';
370
137bbbc6
DC
371 // during moodle installation, user area doesn't exist
372 // so we need to disable filepicker here.
373 if (!during_initial_install() && empty($CFG->adminsetuppending)) {
374 // 0 means no files, -1 unlimited
375 if ($maxfiles != 0 ) {
563d0417
DC
376 $str .= '<input type="hidden" name="'.$elname.'[itemid]" value="'.$draftitemid.'" />';
377
378 // used by non js editor only
379 $editorurl = new moodle_url("$CFG->wwwroot/repository/draftfiles_manager.php", array(
7f39d66a
DC
380 'action'=>'browse',
381 'env'=>'editor',
382 'itemid'=>$draftitemid,
383 'subdirs'=>$subdirs,
384 'maxbytes'=>$maxbytes,
563d0417 385 'maxfiles'=>$maxfiles,
7f39d66a 386 'ctx_id'=>$ctx->id,
71267723
DC
387 'course'=>$PAGE->course->id,
388 'sesskey'=>sesskey(),
7f39d66a 389 ));
563d0417 390 $str .= '<noscript>';
6ef1402e 391 $str .= "<div><object type='text/html' data='$editorurl' height='160' width='600' style='border:1px solid #000'></object></div>";
563d0417 392 $str .= '</noscript>';
137bbbc6 393 }
0b94f320 394 }
cefe1408 395
137bbbc6 396
cefe1408 397 $str .= '</div>';
398
399 return $str;
400 }
401
8367651e
RW
402 /**
403 * What to display when element is frozen.
404 *
405 * @return empty string
406 */
407 function getFrozenHtml() {
408
409 return '';
410 }
e19dc11e 411}