From 0b7858221c3e3f6445e8d2d93e0efac6129b135d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20S=CC=8Ckoda?= Date: Sat, 18 Aug 2012 18:55:33 +0200 Subject: [PATCH] MDL-34955 add full TinyMCE subplugin management --- lib/editor/tinymce/adminlib.php | 186 +++++++++++++++++- lib/editor/tinymce/classes/plugin.php | 26 +++ lib/editor/tinymce/lang/en/editor_tinymce.php | 4 +- lib/editor/tinymce/lib.php | 5 - lib/editor/tinymce/plugins/dragmath/lib.php | 3 + .../tinymce/plugins/moodleemoticon/lib.php | 3 + .../tinymce/plugins/moodleimage/lib.php | 10 + .../tinymce/plugins/moodlemedia/lib.php | 10 + .../tinymce/plugins/moodlenolink/lib.php | 3 + .../tinymce/plugins/spellchecker/lib.php | 3 + lib/editor/tinymce/settings.php | 5 +- lib/editor/tinymce/subplugins.php | 23 +++ 12 files changed, 273 insertions(+), 8 deletions(-) diff --git a/lib/editor/tinymce/adminlib.php b/lib/editor/tinymce/adminlib.php index 4d2dba28876..3c923d4936f 100644 --- a/lib/editor/tinymce/adminlib.php +++ b/lib/editor/tinymce/adminlib.php @@ -26,11 +26,15 @@ defined('MOODLE_INTERNAL') || die(); require_once("$CFG->libdir/pluginlib.php"); + /** * Editor subplugin info class. + * + * @package editor_tinymce + * @copyright 2012 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class plugininfo_tinymce extends plugininfo_base { - public function get_uninstall_url() { return new moodle_url('/lib/editor/tinymce/subplugins.php', array('delete' => $this->name, 'sesskey' => sesskey())); } @@ -43,4 +47,184 @@ class plugininfo_tinymce extends plugininfo_base { return null; } } + + public function is_enabled() { + static $disabledsubplugins = null; // TODO: remove this once get_config() is cached via MUC! + + if (is_null($disabledsubplugins)) { + $disabledsubplugins = array(); + $config = get_config('editor_tinymce', 'disabledsubplugins'); + if ($config) { + $config = explode(',', $config); + foreach ($config as $sp) { + $sp = trim($sp); + if ($sp !== '') { + $disabledsubplugins[$sp] = $sp; + } + } + } + } + + return !isset($disabledsubplugins[$this->name]); + } +} + + +/** + * Special class for TinyMCE subplugin administration. + * + * @package editor_tinymce + * @copyright 2012 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class tiynce_subplugins_settings extends admin_setting { + public function __construct() { + $this->nosave = true; + parent::__construct('tinymcesubplugins', get_string('subplugintype_tinymce_plural', 'editor_tinymce'), '', ''); + } + + /** + * Always returns true, does nothing. + * + * @return true + */ + public function get_setting() { + return true; + } + + /** + * Always returns true, does nothing. + * + * @return true + */ + public function get_defaultsetting() { + return true; + } + + /** + * Always returns '', does not write anything. + * + * @param string $data + * @return string Always returns '' + */ + public function write_setting($data) { + // Do not write any setting. + return ''; + } + + /** + * Checks if $query is one of the available subplugins. + * + * @param string $query The string to search for + * @return bool Returns true if found, false if not + */ + public function is_related($query) { + if (parent::is_related($query)) { + return true; + } + + $subplugins = get_plugin_list('tinymce'); + foreach ($subplugins as $name=>$dir) { + if (stripos($name, $query) !== false) { + return true; + } + + $namestr = get_string('pluginname', 'tinymce_'.$name); + if (strpos(textlib::strtolower($namestr), textlib::strtolower($query)) !== false) { + return true; + } + } + return false; + } + + /** + * Builds the XHTML to display the control. + * + * @param string $data Unused + * @param string $query + * @return string + */ + public function output_html($data, $query='') { + global $CFG, $OUTPUT; + require_once("$CFG->libdir/editorlib.php"); + require_once("$CFG->libdir/pluginlib.php"); + require_once(__DIR__.'/lib.php'); + $tinymce = new tinymce_texteditor(); + $pluginmanager = plugin_manager::instance(); + + // display strings + $strbuttons = get_string('availablebuttons', 'editor_tinymce'); + $strdisable = get_string('disable'); + $strenable = get_string('enable'); + $strname = get_string('name'); + $strsettings = get_string('settings'); + $struninstall = get_string('uninstallplugin', 'admin'); + $strversion = get_string('version'); + + $subplugins = get_plugin_list('tinymce'); + + $return = $OUTPUT->heading(get_string('subplugins', 'editor_tinymce'), 3, 'main', true); + $return .= $OUTPUT->box_start('generalbox tinymcesubplugins'); + + $table = new html_table(); + $table->head = array($strname, $strbuttons, $strversion, $strenable, $strsettings, $struninstall); + $table->align = array('left', 'left', 'center', 'center', 'center', 'center'); + $table->data = array(); + $table->width = '100%'; + + // Iterate through subplugins. + foreach ($subplugins as $name => $dir) { + $namestr = get_string('pluginname', 'tinymce_'.$name); + $version = get_config('tinymce_'.$name, 'version'); + if ($version === false) { + $version = ''; + } + $plugin = $tinymce->get_plugin($name); + $plugininfo = $pluginmanager->get_plugin_info('tinymce_'.$name); + + // Add hide/show link. + if (!$version) { + $hideshow = ''; + $displayname = html_writer::tag('span', $name, array('class'=>'error')); + } else if ($plugininfo->is_enabled()) { + $url = new moodle_url('/lib/editor/tinymce/subplugins.php', array('sesskey'=>sesskey(), 'return'=>'settings', 'disable'=>$name)); + $hideshow = html_writer::empty_tag('img', array('src'=>$OUTPUT->pix_url('i/hide'), 'class'=>'icon', 'alt'=>$strdisable)); + $hideshow = html_writer::link($url, $hideshow); + $displayname = html_writer::tag('span', $namestr); + } else { + $url = new moodle_url('/lib/editor/tinymce/subplugins.php', array('sesskey'=>sesskey(), 'return'=>'settings', 'enable'=>$name)); + $hideshow = html_writer::empty_tag('img', array('src'=>$OUTPUT->pix_url('i/show'), 'class'=>'icon', 'alt'=>$strenable)); + $hideshow = html_writer::link($url, $hideshow); + $displayname = html_writer::tag('span', $namestr, array('class'=>'dimmed_text')); + } + + // Add available buttons. + $buttons = implode(', ', $plugin->get_buttons()); + $buttons = html_writer::tag('span', $buttons, array('class'=>'tinamcebuttons')); + + // Add settings link. + if (!$version) { + $settings = ''; + } else if ($url = $plugininfo->get_settings_url()) { + $settings = html_writer::link($url, $strsettings); + } else { + $settings = ''; + } + + // Add uninstall info. + if ($version) { + $url = new moodle_url($plugininfo->get_uninstall_url(), array('return'=>'settings')); + $uninstall = html_writer::link($url, $struninstall); + } else { + $uninstall = ''; + } + + // Add a row to the table. + $table->data[] = array($displayname, $buttons, $version, $hideshow, $settings, $uninstall); + } + $return .= html_writer::table($table); + $return .= html_writer::tag('p', get_string('tablenosave', 'admin')); + $return .= $OUTPUT->box_end(); + return highlight($query, $return); + } } diff --git a/lib/editor/tinymce/classes/plugin.php b/lib/editor/tinymce/classes/plugin.php index 8dca9b6a00f..305f8275c7b 100644 --- a/lib/editor/tinymce/classes/plugin.php +++ b/lib/editor/tinymce/classes/plugin.php @@ -40,6 +40,9 @@ abstract class editor_tinymce_plugin { /** @var array Plugin settings */ protected $config = null; + /** @var array list of buttons defined by this plugin */ + protected $buttons = array(); + /** * @param string $plugin Name of folder */ @@ -47,6 +50,15 @@ abstract class editor_tinymce_plugin { $this->plugin = $plugin; } + /** + * Returns list of buttons defined by this plugin. + * useful mostly as information when setting custom toolbar. + * + * @return array + */ + public function get_buttons() { + return $this->buttons; + } /** * Makes sure config is loaded and cached. * @return void @@ -326,9 +338,23 @@ abstract class editor_tinymce_plugin { // Get list of plugin directories. $plugins = get_plugin_list('tinymce'); + // Get list of disabled subplugins. + $disabled = array(); + if ($params['moodle_config']->disabledsubplugins) { + foreach (explode(',', $params['moodle_config']->disabledsubplugins) as $sp) { + $sp = trim($sp); + if ($sp !== '') { + $disabled[$sp] = $sp; + } + } + } + // Construct all the plugins. $pluginobjects = array(); foreach ($plugins as $plugin => $dir) { + if (isset($disabled[$plugin])) { + continue; + } require_once($dir . '/lib.php'); $classname = 'tinymce_' . $plugin; $pluginobjects[] = new $classname($plugin); diff --git a/lib/editor/tinymce/lang/en/editor_tinymce.php b/lib/editor/tinymce/lang/en/editor_tinymce.php index 2fbb5124d81..d08d0f11745 100644 --- a/lib/editor/tinymce/lang/en/editor_tinymce.php +++ b/lib/editor/tinymce/lang/en/editor_tinymce.php @@ -24,15 +24,17 @@ //== Custom Moodle strings that are not part of upstream TinyMCE == +$string['availablebuttons'] = 'Available buttons'; $string['common:browseimage'] = 'Find or upload an image...'; $string['common:browsemedia'] = 'Find or upload a sound, video or applet...'; $string['customtoolbar'] = 'Custom editor toolbar'; -$string['customtoolbar_desc'] = 'Each line contains a list of comma separated button names, use "|" as a group separator. Leave empty if you want standard toolbar.'; +$string['customtoolbar_desc'] = 'Each line contains a list of comma separated button names, use "|" as a group separator. Leave empty if you want standard toolbar. See {$a} for the list of default TinyMCE buttons.'; $string['fontselectlist'] = 'Available fonts list'; $string['media_dlg:filename'] = 'Filename'; $string['pluginname'] = 'TinyMCE HTML editor'; $string['settings'] = 'General settings'; $string['subplugindeleteconfirm'] = 'You are about to completely delete TinyMCE subplugin \'{$a}\'. This will completely delete everything in the database associated with this subplugin. Are you SURE you want to continue?'; +$string['subplugintype_tinymce_plural'] = 'Plugins'; // == TinyMCE upstream lang strings from all standard upstream plugins == diff --git a/lib/editor/tinymce/lib.php b/lib/editor/tinymce/lib.php index ac25047e031..6ffef3927ad 100644 --- a/lib/editor/tinymce/lib.php +++ b/lib/editor/tinymce/lib.php @@ -177,11 +177,6 @@ class tinymce_texteditor extends texteditor { $params['extended_valid_elements'] = 'nolink,tex,algebra,lang[lang]'; $params['custom_elements'] = 'nolink,~tex,~algebra,lang'; - if (empty($options['legacy'])) { - if (isset($options['maxfiles']) and $options['maxfiles'] != 0) { - $params['file_browser_callback'] = "M.editor_tinymce.filepicker"; - } - } //Add onblur event for client side text validation if (!empty($options['required'])) { $params['init_instance_callback'] = 'M.editor_tinymce.onblur_event'; diff --git a/lib/editor/tinymce/plugins/dragmath/lib.php b/lib/editor/tinymce/plugins/dragmath/lib.php index 6532313bcb7..1cacacf1253 100644 --- a/lib/editor/tinymce/plugins/dragmath/lib.php +++ b/lib/editor/tinymce/plugins/dragmath/lib.php @@ -24,6 +24,9 @@ defined('MOODLE_INTERNAL') || die(); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class tinymce_dragmath extends editor_tinymce_plugin { + /** @var array list of buttons defined by this plugin */ + protected $buttons = array('dragmath'); + protected function update_init_params(array &$params, context $context, array $options = null) { diff --git a/lib/editor/tinymce/plugins/moodleemoticon/lib.php b/lib/editor/tinymce/plugins/moodleemoticon/lib.php index 09f23c5d503..910cd569354 100644 --- a/lib/editor/tinymce/plugins/moodleemoticon/lib.php +++ b/lib/editor/tinymce/plugins/moodleemoticon/lib.php @@ -24,6 +24,9 @@ defined('MOODLE_INTERNAL') || die(); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class tinymce_moodleemoticon extends editor_tinymce_plugin { + /** @var array list of buttons defined by this plugin */ + protected $buttons = array('moodleemoticon'); + protected function update_init_params(array &$params, context $context, array $options = null) { global $OUTPUT; diff --git a/lib/editor/tinymce/plugins/moodleimage/lib.php b/lib/editor/tinymce/plugins/moodleimage/lib.php index afec3435d0c..f284b7a8b78 100644 --- a/lib/editor/tinymce/plugins/moodleimage/lib.php +++ b/lib/editor/tinymce/plugins/moodleimage/lib.php @@ -24,9 +24,19 @@ defined('MOODLE_INTERNAL') || die(); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class tinymce_moodleimage extends editor_tinymce_plugin { + /** @var array list of buttons defined by this plugin */ + protected $buttons = array('image'); + protected function update_init_params(array &$params, context $context, array $options = null) { + // Add file picker callback. + if (empty($options['legacy'])) { + if (isset($options['maxfiles']) and $options['maxfiles'] != 0) { + $params['file_browser_callback'] = "M.editor_tinymce.filepicker"; + } + } + // This plugin overrides standard 'image' button, no need to insert new button. // Add JS file, which uses default name. diff --git a/lib/editor/tinymce/plugins/moodlemedia/lib.php b/lib/editor/tinymce/plugins/moodlemedia/lib.php index 5669f477a14..048b1f5ef0d 100644 --- a/lib/editor/tinymce/plugins/moodlemedia/lib.php +++ b/lib/editor/tinymce/plugins/moodlemedia/lib.php @@ -24,9 +24,19 @@ defined('MOODLE_INTERNAL') || die(); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class tinymce_moodlemedia extends editor_tinymce_plugin { + /** @var array list of buttons defined by this plugin */ + protected $buttons = array('moodlemedia'); + protected function update_init_params(array &$params, context $context, array $options = null) { + // Add file picker callback. + if (empty($options['legacy'])) { + if (isset($options['maxfiles']) and $options['maxfiles'] != 0) { + $params['file_browser_callback'] = "M.editor_tinymce.filepicker"; + } + } + // Add button after emoticon button in advancedbuttons3. $added = $this->add_button_after($params, 3, 'moodlemedia', 'moodleemoticon', false); diff --git a/lib/editor/tinymce/plugins/moodlenolink/lib.php b/lib/editor/tinymce/plugins/moodlenolink/lib.php index fb12c77c735..fedb3cc00e2 100644 --- a/lib/editor/tinymce/plugins/moodlenolink/lib.php +++ b/lib/editor/tinymce/plugins/moodlenolink/lib.php @@ -24,6 +24,9 @@ defined('MOODLE_INTERNAL') || die(); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class tinymce_moodlenolink extends editor_tinymce_plugin { + /** @var array list of buttons defined by this plugin */ + protected $buttons = array('moodlenolink'); + protected function update_init_params(array &$params, context $context, array $options = null) { diff --git a/lib/editor/tinymce/plugins/spellchecker/lib.php b/lib/editor/tinymce/plugins/spellchecker/lib.php index 2a4cfde6788..b2aee6d4bff 100644 --- a/lib/editor/tinymce/plugins/spellchecker/lib.php +++ b/lib/editor/tinymce/plugins/spellchecker/lib.php @@ -25,6 +25,9 @@ defined('MOODLE_INTERNAL') || die(); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class tinymce_spellchecker extends editor_tinymce_plugin { + /** @var array list of buttons defined by this plugin */ + protected $buttons = array('spellchecker'); + protected function update_init_params(array &$params, context $context, array $options = null) { global $CFG; diff --git a/lib/editor/tinymce/settings.php b/lib/editor/tinymce/settings.php index 45c1bc84eeb..d7ffb88332d 100644 --- a/lib/editor/tinymce/settings.php +++ b/lib/editor/tinymce/settings.php @@ -28,8 +28,11 @@ $ADMIN->add('editorsettings', new admin_category('editortinymce', new lang_strin $settings = new admin_settingpage('editorsettingstinymce', new lang_string('settings', 'editor_tinymce')); if ($ADMIN->fulltree) { + require_once(__DIR__.'/adminlib.php'); + $settings->add(new tiynce_subplugins_settings()); + $settings->add(new admin_setting_heading('tinymcegeneralheader', new lang_string('settings'), '')); $settings->add(new admin_setting_configtextarea('editor_tinymce/customtoolbar', - get_string('customtoolbar', 'editor_tinymce'), get_string('customtoolbar_desc', 'editor_tinymce'), '', PARAM_RAW, 100, 6)); + get_string('customtoolbar', 'editor_tinymce'), get_string('customtoolbar_desc', 'editor_tinymce', 'http://www.tinymce.com/wiki.php/Buttons/controls'), '', PARAM_RAW, 100, 6)); $settings->add(new admin_setting_configtextarea('editor_tinymce/fontselectlist', get_string('fontselectlist', 'editor_tinymce'), '', 'Trebuchet=Trebuchet MS,Verdana,Arial,Helvetica,sans-serif;Arial=arial,helvetica,sans-serif;Courier New=courier new,courier,monospace;Georgia=georgia,times new roman,times,serif;Tahoma=tahoma,arial,helvetica,sans-serif;Times New Roman=times new roman,times,serif;Verdana=verdana,arial,helvetica,sans-serif;Impact=impact;Wingdings=wingdings', PARAM_RAW)); diff --git a/lib/editor/tinymce/subplugins.php b/lib/editor/tinymce/subplugins.php index beba8f432ef..57c153a7e36 100644 --- a/lib/editor/tinymce/subplugins.php +++ b/lib/editor/tinymce/subplugins.php @@ -27,6 +27,8 @@ require_once($CFG->libdir.'/adminlib.php'); $delete = optional_param('delete', '', PARAM_PLUGIN); $confirm = optional_param('confirm', '', PARAM_BOOL); +$disable = optional_param('disable', '', PARAM_PLUGIN); +$enable = optional_param('enable', '', PARAM_PLUGIN); $return = optional_param('return', 'overview', PARAM_ALPHA); $PAGE->set_context(context_system::instance()); @@ -69,6 +71,27 @@ if ($delete) { echo $OUTPUT->footer(); die(); } + +} else { + $disabled = array(); + $disabledsubplugins = get_config('editor_tinymce', 'disabledsubplugins'); + if ($disabledsubplugins) { + $disabledsubplugins = explode(',', $disabledsubplugins); + foreach ($disabledsubplugins as $sp) { + $sp = trim($sp); + if ($sp !== '') { + $disabled[$sp] = $sp; + } + } + } + + if ($disable) { + $disabled[$disable] = $disable; + } else if ($enable) { + unset($disabled[$enable]); + } + + set_config('disabledsubplugins', implode(',', $disabled), 'editor_tinymce'); } redirect($returnurl);