2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
18 * TinyMCE text editor integration.
22 * @copyright 2009 Petr Skoda (http://skodak.org)
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 defined('MOODLE_INTERNAL') ||
die();
28 class tinymce_texteditor
extends texteditor
{
29 /** @var string active version - this is the directory name where to find tinymce code */
30 public $version = '3.5.11';
33 * Is the current browser supported by this editor?
36 public function supported_by_browser() {
37 // We don't support any browsers which it doesn't support.
42 * Returns array of supported text formats.
45 public function get_supported_formats() {
46 // FORMAT_MOODLE is not supported here, sorry.
47 return array(FORMAT_HTML
=> FORMAT_HTML
);
51 * Returns text format preferred by this editor.
54 public function get_preferred_format() {
59 * Does this editor support picking from repositories?
62 public function supports_repositories() {
67 * Sets up head code if necessary.
69 public function head_setup() {
73 * Use this editor for give element.
75 * @param string $elementid
76 * @param array $options
77 * @param null $fpoptions
79 public function use_editor($elementid, array $options=null, $fpoptions=null) {
81 // Note: use full moodle_url instance to prevent standard JS loader, make sure we are using https on profile page if required.
82 if ($CFG->debugdeveloper
) {
83 $PAGE->requires
->js(new moodle_url('/lib/editor/tinymce/tiny_mce/'.$this->version
.'/tiny_mce_src.js'));
85 $PAGE->requires
->js(new moodle_url('/lib/editor/tinymce/tiny_mce/'.$this->version
.'/tiny_mce.js'));
87 $PAGE->requires
->js_init_call('M.editor_tinymce.init_editor', array($elementid, $this->get_init_params($elementid, $options)), true);
89 $PAGE->requires
->js_init_call('M.editor_tinymce.init_filepicker', array($elementid, $fpoptions), true);
93 protected function get_init_params($elementid, array $options=null) {
94 global $CFG, $PAGE, $OUTPUT;
96 //TODO: we need to implement user preferences that affect the editor setup too
98 $directionality = get_string('thisdirection', 'langconfig');
99 $strtime = get_string('strftimetime');
100 $strdate = get_string('strftimedaydate');
101 $lang = current_language();
102 $contentcss = $PAGE->theme
->editor_css_url()->out(false);
104 $context = empty($options['context']) ? context_system
::instance() : $options['context'];
106 $config = get_config('editor_tinymce');
107 if (!isset($config->disabledsubplugins
)) {
108 $config->disabledsubplugins
= '';
111 // Remove the manage files button if requested.
112 if (isset($options['enable_filemanagement']) && !$options['enable_filemanagement']) {
113 if (!strpos($config->disabledsubplugins
, 'managefiles')) {
114 $config->disabledsubplugins
.= ',managefiles';
118 $fontselectlist = empty($config->fontselectlist
) ?
'' : $config->fontselectlist
;
121 if (!empty($CFG->cachejs
)) {
122 $langrev = get_string_manager()->get_revision();
126 'moodle_config' => $config,
128 'elements' => $elementid,
129 'relative_urls' => false,
130 'document_base_url' => $CFG->wwwroot
,
131 'moodle_plugin_base' => "$CFG->wwwroot/lib/editor/tinymce/plugins/",
132 'content_css' => $contentcss,
134 'directionality' => $directionality,
135 'plugin_insertdate_dateFormat ' => $strdate,
136 'plugin_insertdate_timeFormat ' => $strtime,
137 'theme' => "advanced",
139 'apply_source_formatting' => true,
140 'remove_script_host' => false,
141 'entity_encoding' => "raw",
142 'plugins' => 'lists,table,style,layer,advhr,advlink,emotions,inlinepopups,' .
143 'searchreplace,paste,directionality,fullscreen,nonbreaking,contextmenu,' .
144 'insertdatetime,save,iespell,preview,print,noneditable,visualchars,' .
145 'xhtmlxtras,template,pagebreak',
146 'gecko_spellcheck' => true,
147 'theme_advanced_font_sizes' => "1,2,3,4,5,6,7",
148 'theme_advanced_layout_manager' => "SimpleLayout",
149 'theme_advanced_toolbar_align' => "left",
150 'theme_advanced_fonts' => $fontselectlist,
151 'theme_advanced_resize_horizontal' => true,
152 'theme_advanced_resizing' => true,
153 'theme_advanced_resizing_min_height' => 30,
155 'theme_advanced_toolbar_location' => "top",
156 'theme_advanced_statusbar_location' => "bottom",
157 'language_load' => false, // We load all lang strings directly from Moodle.
158 'langrev' => $langrev,
161 // Should we override the default toolbar layout unconditionally?
162 if (!empty($config->customtoolbar
) and $customtoolbar = self
::parse_toolbar_setting($config->customtoolbar
)) {
164 foreach ($customtoolbar as $line) {
165 $params['theme_advanced_buttons'.$i] = $line;
169 // At least one line is required.
170 $params['theme_advanced_buttons1'] = '';
173 if (!empty($config->customconfig
)) {
174 $config->customconfig
= trim($config->customconfig
);
175 $decoded = json_decode($config->customconfig
, true);
176 if (is_array($decoded)) {
177 foreach ($decoded as $k=>$v) {
183 if (!empty($options['legacy']) or !empty($options['noclean']) or !empty($options['trusted'])) {
184 // now deal somehow with non-standard tags, people scream when we do not make moodle code xtml strict,
185 // but they scream even more when we strip all tags that are not strict :-(
186 $params['valid_elements'] = 'script[src|type],*[*]'; // for some reason the *[*] does not inlcude javascript src attribute MDL-25836
187 $params['invalid_elements'] = '';
189 // Add unique moodle elements - unfortunately we have to decide if these are SPANs or DIVs.
190 $params['extended_valid_elements'] = 'nolink,tex,algebra,lang[lang]';
191 $params['custom_elements'] = 'nolink,~tex,~algebra,lang';
193 //Add onblur event for client side text validation
194 if (!empty($options['required'])) {
195 $params['init_instance_callback'] = 'M.editor_tinymce.onblur_event';
198 // Allow plugins to adjust parameters.
199 editor_tinymce_plugin
::all_update_init_params($params, $context, $options);
201 // Remove temporary parameters.
202 unset($params['moodle_config']);
208 * Parse the custom toolbar setting.
209 * @param string $customtoolbar
210 * @return array csv toolbar lines
212 public static function parse_toolbar_setting($customtoolbar) {
214 $customtoolbar = trim($customtoolbar);
215 if ($customtoolbar === '') {
218 $customtoolbar = str_replace("\r", "\n", $customtoolbar);
219 $customtoolbar = strtolower($customtoolbar);
221 foreach (explode("\n", $customtoolbar) as $line) {
222 $line = preg_replace('/[^a-z0-9_,\|\-]/', ',', $line);
223 $line = str_replace('|', ',|,', $line);
224 $line = preg_replace('/,,+/', ',', $line);
225 $line = trim($line, ',|');
230 // Maximum is ten lines, merge the rest to the last line.
231 $result[9] = $result[9].','.$line;
241 * Gets a named plugin object. Will cause fatal error if plugin doesn't
242 * exist. This is intended for use by plugin files themselves.
244 * @param string $plugin Name of plugin e.g. 'moodleemoticon'
245 * @return editor_tinymce_plugin Plugin object
247 public function get_plugin($plugin) {
249 return editor_tinymce_plugin
::get($plugin);
253 * Equivalent to tinyMCE.baseURL value available from JavaScript,
254 * always use instead of /../ when referencing tinymce core code from moodle plugins!
256 * @return moodle_url url pointing to the root of TinyMCE javascript code.
258 public function get_tinymce_base_url() {
260 return new moodle_url("/lib/editor/tinymce/tiny_mce/$this->version/");