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