MDL-34955 fix use of uninitialised disabledsubplugins setting
[moodle.git] / lib / editor / tinymce / lib.php
CommitLineData
5ca3c838 1<?php
8fd57583 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 * TinyMCE text editor integration.
19 *
7ad5a627
PS
20 * @package editor
21 * @subpackage tinymce
8fd57583 22 * @copyright 2009 Petr Skoda (http://skodak.org)
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
5ca3c838 25
7ad5a627
PS
26defined('MOODLE_INTERNAL') || die();
27
5ca3c838 28class tinymce_texteditor extends texteditor {
a3f1cd03
PS
29 /** @var string active version - this is the directory name where to find tinymce code */
30 public $version = '3.6.0';
34a30b5c 31
de6a6512
PS
32 /**
33 * Is the current browser supported by this editor?
34 * @return bool
35 */
5ca3c838 36 public function supported_by_browser() {
06671035 37 if (check_browser_version('MSIE', 6)) {
5ca3c838 38 return true;
06671035
PS
39 }
40 if (check_browser_version('Gecko', 20030516)) {
5ca3c838 41 return true;
06671035
PS
42 }
43 if (check_browser_version('Safari', 412)) {
5ca3c838 44 return true;
06671035
PS
45 }
46 if (check_browser_version('Chrome', 6)) {
47 return true;
48 }
49 if (check_browser_version('Opera', 9)) {
5ca3c838 50 return true;
51 }
626509d4
PS
52 if (check_browser_version('Safari iOS', 534)) {
53 return true;
54 }
69429650 55
c55ff183 56 return false;
5ca3c838 57 }
58
de6a6512
PS
59 /**
60 * Returns array of supported text formats.
61 * @return array
62 */
5ca3c838 63 public function get_supported_formats() {
de6a6512 64 // FORMAT_MOODLE is not supported here, sorry.
5ca3c838 65 return array(FORMAT_HTML => FORMAT_HTML);
66 }
67
de6a6512
PS
68 /**
69 * Returns text format preferred by this editor.
70 * @return int
71 */
5ca3c838 72 public function get_preferred_format() {
73 return FORMAT_HTML;
74 }
75
de6a6512
PS
76 /**
77 * Does this editor support picking from repositories?
78 * @return bool
79 */
5ca3c838 80 public function supports_repositories() {
81 return true;
82 }
83
de6a6512
PS
84 /**
85 * Sets up head code if necessary.
86 */
ff5fe311 87 public function head_setup() {
ff5fe311 88 }
34a30b5c 89
de6a6512
PS
90 /**
91 * Use this editor for give element.
92 *
93 * @param string $elementid
94 * @param array $options
95 * @param null $fpoptions
96 */
4c508047 97 public function use_editor($elementid, array $options=null, $fpoptions=null) {
ff5fe311 98 global $PAGE;
a8c86418
TH
99 if (debugging('', DEBUG_DEVELOPER)) {
100 $PAGE->requires->js('/lib/editor/tinymce/tiny_mce/'.$this->version.'/tiny_mce_src.js');
101 } else {
102 $PAGE->requires->js('/lib/editor/tinymce/tiny_mce/'.$this->version.'/tiny_mce.js');
103 }
4c508047
PS
104 $PAGE->requires->js_init_call('M.editor_tinymce.init_editor', array($elementid, $this->get_init_params($elementid, $options)), true);
105 if ($fpoptions) {
106 $PAGE->requires->js_init_call('M.editor_tinymce.init_filepicker', array($elementid, $fpoptions), true);
107 }
5ca3c838 108 }
109
69429650 110 protected function get_init_params($elementid, array $options=null) {
b9fadae7 111 global $CFG, $PAGE, $OUTPUT;
fae91170 112 require_once($CFG->dirroot . '/lib/editor/tinymce/classes/plugin.php');
13a220cf 113
34a30b5c 114 //TODO: we need to implement user preferences that affect the editor setup too
69429650 115
e372f4c7 116 $directionality = get_string('thisdirection', 'langconfig');
69429650 117 $strtime = get_string('strftimetime');
118 $strdate = get_string('strftimedaydate');
3a915b06 119 $lang = current_language();
b9bc2019 120 $contentcss = $PAGE->theme->editor_css_url()->out(false);
69429650 121
b0c6dc1c 122 $context = empty($options['context']) ? context_system::instance() : $options['context'];
ca91bc95 123
1fea5537 124 $config = get_config('editor_tinymce');
71c3b047
PS
125 if (!isset($config->disabledsubplugins)) {
126 $config->disabledsubplugins = '';
127 }
1fea5537 128
1fea5537
PS
129 $fontselectlist = empty($config->fontselectlist) ? '' : $config->fontselectlist;
130 $fontbutton = ($fontselectlist === '') ? '' : 'fontselect,';
131
69429650 132 $params = array(
9b63a155 133 'moodle_config' => $config,
1702fb6d 134 'mode' => "exact",
135 'elements' => $elementid,
136 'relative_urls' => false,
137 'document_base_url' => $CFG->httpswwwroot,
e4907cab 138 'moodle_plugin_base' => "$CFG->httpswwwroot/lib/editor/tinymce/plugins/",
1702fb6d 139 'content_css' => $contentcss,
140 'language' => $lang,
141 'directionality' => $directionality,
142 'plugin_insertdate_dateFormat ' => $strdate,
143 'plugin_insertdate_timeFormat ' => $strtime,
144 'theme' => "advanced",
145 'skin' => "o2k7",
146 'skin_variant' => "silver",
147 'apply_source_formatting' => true,
148 'remove_script_host' => false,
149 'entity_encoding' => "raw",
fb7bcc13 150 'plugins' => 'safari,table,style,layer,advhr,advlink,emotions,inlinepopups,' .
20490336 151 'searchreplace,paste,directionality,fullscreen,nonbreaking,contextmenu,' .
152 'insertdatetime,save,iespell,preview,print,noneditable,visualchars,' .
9b63a155 153 'xhtmlxtras,template,pagebreak',
1702fb6d 154 'theme_advanced_font_sizes' => "1,2,3,4,5,6,7",
155 'theme_advanced_layout_manager' => "SimpleLayout",
156 'theme_advanced_toolbar_align' => "left",
157 'theme_advanced_buttons1' => $fontbutton . 'fontsizeselect,formatselect,|,' .
158 'undo,redo,|,search,replace,|,fullscreen',
159 'theme_advanced_buttons2' => 'bold,italic,underline,strikethrough,sub,sup,|,' .
160 'justifyleft,justifycenter,justifyright,|,' .
161 'cleanup,removeformat,pastetext,pasteword,|,forecolor,backcolor,|,ltr,rtl',
162 'theme_advanced_buttons3' => 'bullist,numlist,outdent,indent,|,' .
9b63a155 163 'link,unlink,|,image,nonbreaking,charmap,table,|,code',
1702fb6d 164 'theme_advanced_fonts' => $fontselectlist,
165 'theme_advanced_resize_horizontal' => true,
166 'theme_advanced_resizing' => true,
167 'theme_advanced_resizing_min_height' => 30,
168 'min_height' => 30,
169 'theme_advanced_toolbar_location' => "top",
170 'theme_advanced_statusbar_location' => "bottom",
1702fb6d 171 );
b9fadae7 172
13725b37 173 if (!empty($options['legacy']) or !empty($options['noclean']) or !empty($options['trusted'])) {
38c8aed7
PS
174 // now deal somehow with non-standard tags, people scream when we do not make moodle code xtml strict,
175 // but they scream even more when we strip all tags that are not strict :-(
79abc6d1 176 $params['valid_elements'] = 'script[src|type],*[*]'; // for some reason the *[*] does not inlcude javascript src attribute MDL-25836
38c8aed7
PS
177 $params['invalid_elements'] = '';
178 }
64ed8ca2
PS
179 // Add unique moodle elements - unfortunately we have to decide if these are SPANs or DIVs.
180 $params['extended_valid_elements'] = 'nolink,tex,algebra,lang[lang]';
181 $params['custom_elements'] = 'nolink,~tex,~algebra,lang';
69429650 182
ab978b38
RT
183 //Add onblur event for client side text validation
184 if (!empty($options['required'])) {
185 $params['init_instance_callback'] = 'M.editor_tinymce.onblur_event';
186 }
fae91170 187
9b63a155 188 // Allow plugins to adjust parameters.
fae91170 189 editor_tinymce_plugin::all_update_init_params($params, $context, $options);
9b63a155 190
caaccae5 191 // Should we override the default toolbar layout unconditionally?
b3aefe3c 192 $customtoolbar = self::parse_toolbar_setting($config->customtoolbar);
caaccae5
PS
193 if ($customtoolbar) {
194 unset($params['theme_advanced_buttons1']);
195 unset($params['theme_advanced_buttons2']);
196 unset($params['theme_advanced_buttons3']);
197 unset($params['theme_advanced_buttons4']);
caaccae5 198 $i = 1;
b3aefe3c 199 foreach ($customtoolbar as $line) {
caaccae5
PS
200 $params['theme_advanced_buttons'.$i] = $line;
201 $i++;
202 }
203 }
204
9b63a155 205 // Remove temporary parameters.
206 unset($params['moodle_config']);
207
69429650 208 return $params;
5ca3c838 209 }
fae91170 210
b3aefe3c
PS
211 /**
212 * Parse the custom toolbar setting.
213 * @param string $customtoolbar
214 * @return array csv toolbar lines
215 */
216 public static function parse_toolbar_setting($customtoolbar) {
217 $result = array();
218 $customtoolbar = trim($customtoolbar);
219 if ($customtoolbar === '') {
220 return $result;
221 }
222 $customtoolbar = str_replace("\r", "\n", $customtoolbar);
223 $customtoolbar = strtolower($customtoolbar);
224 foreach (explode("\n", $customtoolbar) as $line) {
225 $line = preg_replace('/[^a-z0-9_,\|\-]/', ',', $line);
226 $line = str_replace('|', ',|,', $line);
227 $line = preg_replace('/,,+/', ',', $line);
228 $line = trim($line, ',|');
229 if ($line === '') {
230 continue;
231 }
232 $result[] = $line;
233 }
234 return $result;
235 }
236
fae91170 237 /**
238 * Gets a named plugin object. Will cause fatal error if plugin doesn't
239 * exist. This is intended for use by plugin files themselves.
240 *
241 * @param string $plugin Name of plugin e.g. 'moodleemoticon'
242 * @return editor_tinymce_plugin Plugin object
243 */
244 public function get_plugin($plugin) {
245 global $CFG;
246 require_once($CFG->dirroot . '/lib/editor/tinymce/classes/plugin.php');
247 return editor_tinymce_plugin::get($plugin);
248 }
e4907cab
PS
249
250 /**
251 * Equivalent to tinyMCE.baseURL value available from JavaScript,
252 * always use instead of /../ when referencing tinymce core code from moodle plugins!
253 *
254 * @return moodle_url url pointing to the root of TinyMCE javascript code.
255 */
256 public function get_tinymce_base_url() {
257 global $CFG;
258 return new moodle_url("$CFG->httpswwwroot/lib/editor/tinymce/tiny_mce/$this->version/");
259 }
69429650 260}