diff --git a/ckeditor.api.php b/ckeditor.api.php index 58e251e..77caa16 100644 --- a/ckeditor.api.php +++ b/ckeditor.api.php @@ -44,11 +44,12 @@ function hook_ckeditor_plugin() { 'name' => 'plugin_name', // Description of the plugin - it would be displayed in the plugins management section of profile settings. 'desc' => t('Plugin description'), - // The full path to the CKEditor plugins directory, with the trailing slash. - 'path' => drupal_get_path('module', 'my_module') . '/plugin_dir/', + // The full URL to the CKEditor plugins directory, with the trailing slash. + 'path' => base_path() . drupal_get_path('module', 'my_module') . '/plugin_dir/', 'buttons' => array( 'button_name' => array( - 'icon' => 'path to button icon', + // Path to an icon relative to the plugins folder. + 'icon' => 'icon/plugin_name.png', 'label' => 'Button Label', ) ) @@ -57,6 +58,17 @@ function hook_ckeditor_plugin() { } /** + * Hook to extend/change CKEditor plugins. + * + * @param $plugins + * An associative array of plugins. + */ +function hook_ckeditor_plugin_alter(&$plugins) { + // Remove a plugin button. + unset($plugins['plugin_name']['buttons']['button']); +} + +/** * Hook to register the CKEditor security filter - it would appear in the security filters list on the profile setting page. */ function hook_ckeditor_security_filter() { diff --git a/ckeditor.ckeditor.inc b/ckeditor.ckeditor.inc new file mode 100644 index 0000000..572ae5b --- /dev/null +++ b/ckeditor.ckeditor.inc @@ -0,0 +1,222 @@ +') { + if (file_exists($_editor_path . '/plugins/tableresize/plugin.js')) { + $plugins['tableresize'] = array( + 'name' => 'tableresize', + 'desc' => t('Table Resize plugin'), + 'path' => $editor_path . '/plugins/tableresize/', + 'buttons' => FALSE, + 'default' => 't' + ); + } + + if (file_exists($_editor_path . '/plugins/autogrow/plugin.js')) { + $plugins['autogrow'] = array( + 'name' => 'autogrow', + 'desc' => t('Auto Grow plugin'), + 'path' => $editor_path . '/plugins/autogrow/', + 'buttons' => FALSE, + 'default' => 'f' + ); + } + + if (file_exists($_editor_path . '/plugins/stylesheetparser/plugin.js')) { + $plugins['stylesheetparser'] = array( + 'name' => 'stylesheetparser', + 'desc' => t('Stylesheet Parser plugin'), + 'path' => $editor_path . '/plugins/stylesheetparser/', + 'buttons' => FALSE, + 'default' => 'f' + ); + } + } + else { + $_editor_url = ckeditor_path('url'); + if (preg_match("/\/(standard|full)-all/", $_editor_url)) { + $plugins['tableresize'] = array( + 'name' => 'tableresize', + 'desc' => t('Table Resize plugin. See !link for more details.', array( + '!link' => l(t('addon page'), 'http://ckeditor.com/addon/tableresize') + )), + 'path' => $_editor_url . '/plugins/tableresize/', + 'buttons' => FALSE, + 'default' => 't' + ); + $plugins['autogrow'] = array( + 'name' => 'autogrow', + 'desc' => t('Auto Grow plugin. See !link for more details.', array( + '!link' => l(t('addon page'), 'http://ckeditor.com/addon/autogrow') + )), + 'path' => $_editor_url . '/plugins/autogrow/', + 'buttons' => FALSE, + 'default' => 'f' + ); + $plugins['stylesheetparser'] = array( + 'name' => 'stylesheetparser', + 'desc' => t('Stylesheet Parser plugin. See !link for more details.', array( + '!link' => l(t('addon page'), 'http://ckeditor.com/addon/stylesheetparser') + )), + 'path' => $_editor_url . '/plugins/stylesheetparser/', + 'buttons' => FALSE, + 'default' => 'f' + ); + $plugins['codesnippet'] = array( + 'name' => 'codesnippet', + 'desc' => t('Plugin for inserting Code Snippets. See !link for more details. See !help for additional instructions.', array( + '!link' => l(t('addon page'), 'http://ckeditor.com/addon/codesnippet'), + '!help' => l(t('help'), 'admin/help/ckeditor', array('fragment' => 'codesnippet')) + )), + 'path' => $_editor_url . '/plugins/codesnippet/', + 'buttons' => array( + 'CodeSnippet' => array( + 'icon' => 'icons/codesnippet.png', + 'label' => 'Insert Code Snippet', + ) + ), + 'default' => 'f' + ); + $plugins['mathjax'] = array( + 'name' => 'mathjax', + 'desc' => t('Plugin for inserting Mathematical Formula (MathJax). See !link for more details. See !help for additional instructions.', array( + '!link' => l(t('addon page'), 'http://ckeditor.com/addon/mathjax'), + '!help' => l(t('help'), 'admin/help/ckeditor', array('fragment' => 'mathjax')) + )), + 'path' => $_editor_url . '/plugins/mathjax/', + 'buttons' => array( + 'Mathjax' => array( + 'icon' => 'icons/mathjax.png', + 'label' => 'Insert Mathematical Formulas', + ) + ), + 'default' => 'f' + ); + } + } + + /* + * Plugins located directly in the CKEditor module folder. + */ + $_plugin_dir = ckeditor_module_path('local') . '/plugins/'; + if ($handle = opendir($_plugin_dir)) { + while (false !== ($file = readdir($handle))) { + if (is_dir($_plugin_dir . $file) && file_exists($_plugin_dir . $file . '/plugin.js')) { + $source = file_get_contents($_plugin_dir . $file . '/plugin.js'); + $buttons = array(); + if (preg_match_all($pattern, $source, $matches)) { + foreach ($matches[1] as $i => $button_name) { + if (preg_match('#(icon)[\s]*\:[\s]*([^\,\n]*)#', $matches[2][$i], $matches2)) { + $buttons[$button_name] = array(); + $buttons[$button_name]['label'] = $button_name; + $matches2[2] = str_replace(array('this.path', '+', '\'', '"'), array('', '', '', ''), $matches2[2]); + $buttons[$button_name]['icon'] = trim($matches2[2]); + } + } + } + if (preg_match('#@file ([^\n\r]*)#', $source, $matches)) { + $plugins[$file] = array( + 'name' => $file, + 'desc' => t($matches[1]), + 'path' => $plugin_dir . $file . '/', + 'buttons' => (count($buttons) > 0) ? $buttons : FALSE, + 'default' => 'f' + ); + } + else { + $plugins[$file] = array( + 'name' => $file, + 'desc' => t('Plugin file: ' . $file), + 'path' => $plugin_dir . $file . '/', + 'buttons' => (count($buttons) > 0) ? $buttons : FALSE, + 'default' => 'f' + ); + } + } + } + closedir($handle); + } + + /* + * Plugins located in a folder specified in the CKEditor Global Profile. + */ + $_plugin_dir_additional = ckeditor_plugins_path('local') . '/'; + if ($_plugin_dir != $_plugin_dir_additional && is_dir($_plugin_dir_additional) && $handle = opendir($_plugin_dir_additional)) { + while (false !== ($file = readdir($handle))) { + if (is_dir($_plugin_dir_additional . $file) && file_exists($_plugin_dir_additional . $file . '/plugin.js')) { + $source = file_get_contents($_plugin_dir_additional . $file . '/plugin.js'); + $buttons = array(); + if (preg_match_all($pattern, $source, $matches)) { + foreach ($matches[1] as $i => $button_name) { + if (preg_match('#(icon)[\s]*\:[\s]*([^\,\n]*)#', $matches[2][$i], $matches2)) { + $buttons[$button_name] = array(); + $buttons[$button_name]['label'] = $button_name; + $matches2[2] = str_replace(array('this.path', '+', '\'', '"'), array('', '', '', ''), $matches2[2]); + $buttons[$button_name]['icon'] = trim($matches2[2]); + } + } + } + if (preg_match('#@file ([^\n\r]*)#', $source, $matches)) { + $plugins[$file] = array( + 'name' => $file, + 'desc' => t($matches[1]), + 'path' => $plugin_dir_additional . $file . '/', + 'buttons' => (count($buttons) > 0) ? $buttons : FALSE, + 'default' => 'f' + ); + } + else { + $plugins[$file] = array( + 'name' => $file, + 'desc' => t('Plugin file: ' . $file), + 'path' => $plugin_dir_additional . $file . '/', + 'buttons' => (count($buttons) > 0) ? $buttons : FALSE, + 'default' => 'f' + ); + } + } + } + + closedir($handle); + } + + // Remove the Media plugin if the Media module isn't installed. + if (isset($plugins['media']) && module_exists('media') == FALSE) { + unset($plugins['media']); + } + + // Remove the IMCE plugin if the IMCE module isn't installed. + if (isset($plugins['imce']) && module_exists('imce') == FALSE) { + unset($plugins['imce']); + } + + // Enable the Drupal Breaks plugin by default if the plugin is available. + if (isset($plugins['drupalbreaks'])) { + $plugins['drupalbreaks']['default'] = 't'; + + // Remove the page break button if there is no module to handle it. + if (isset($plugins['drupalbreaks']['buttons']['DrupalPageBreak']) && !module_exists('paging') && !module_exists('pagebreak')) { + unset($plugins['drupalbreaks']['buttons']['DrupalPageBreak']); + } + } + + return $plugins; +} diff --git a/ckeditor.module b/ckeditor.module index 630714d..da64f3e 100644 --- a/ckeditor.module +++ b/ckeditor.module @@ -51,6 +51,21 @@ $_ckeditor_configuration = array(); $_ckeditor_ids = array(); /** + * Implements hook_hook_info(). + */ +function ckeditor_hook_info() { + $hooks = array( + 'ckeditor_plugin', + 'ckeditor_plugin_alter', + 'ckeditor_security_filter', + 'ckeditor_security_filter_alter', + 'ckeditor_settings_alter', + ); + + return array_fill_keys($hooks, array('group' => 'ckeditor')); +} + +/** * Implementation of hook_menu(). */ function ckeditor_menu() { diff --git a/includes/ckeditor.lib.inc b/includes/ckeditor.lib.inc index e2395f3..c384b49 100644 --- a/includes/ckeditor.lib.inc +++ b/includes/ckeditor.lib.inc @@ -330,286 +330,25 @@ function ckeditor_scayt_langcode($lang) { * @return array */ function ckeditor_load_plugins($render = FALSE) { - $arr = array(); - $base_path = '%base_path%'; - $editor_path = '%editor_path%'; - $plugin_dir = '%plugin_dir%'; - $plugin_dir_additional = '%plugin_dir_extra%'; - $pattern = '#\.addButton\([\s]*[\'"](.*?)[\'"][\s]*\,[\s]*\{[\s]*(.*?)[\s]*\}#s'; - - /* - * External plugins - */ - if (module_exists('ckeditor_swf') && file_exists(drupal_get_path('module', 'ckeditor_swf') . '/plugins/swf/plugin.js')) { - $arr['ckeditor_swf'] = array( - 'name' => 'swf', - 'desc' => t('Support for the CKEditor SWF module'), - 'path' => $base_path . drupal_get_path('module', 'ckeditor_swf') . '/plugins/swf/', - 'buttons' => FALSE, - 'default' => 't' - ); - } - - if (module_exists('ckeditor_link') && file_exists(drupal_get_path('module', 'ckeditor_link') . '/plugins/link/plugin.js')) { - $arr['ckeditor_link'] = array( - 'name' => 'drupal_path', - 'desc' => t('Support for the CKEditor Link module'), - 'path' => $base_path . drupal_get_path('module', 'ckeditor_link') . '/plugins/link/', - 'buttons' => FALSE, - 'default' => 't' - ); - } - - if (module_exists('linkit') && file_exists(drupal_get_path('module', 'linkit') . '/editors/ckeditor/plugin.js')) { - $arr['linkit'] = array( - 'name' => 'Linkit', - 'desc' => t('Support for the Linkit module (buttons: Linkit)'), - 'path' => $base_path . drupal_get_path('module', 'linkit') . '/editors/ckeditor/', - 'buttons' => array( - 'Linkit' => array( - 'title' => 'Linkit', - 'icon' => $base_path . drupal_get_path('module', 'linkit') . '/editors/ckeditor/linkit.png' - ) - ), - 'default' => 't' - ); - } - - /* - * CKEditor build-in plugins - */ - $_editor_path = ckeditor_path('local'); - //die($editor_path); - if ($_editor_path != '') { - if (file_exists($_editor_path . '/plugins/tableresize/plugin.js')) { - $arr['tableresize'] = array( - 'name' => 'tableresize', - 'desc' => t('Table Resize plugin'), - 'path' => $editor_path . '/plugins/tableresize/', - 'buttons' => FALSE, - 'default' => 't' - ); - } - - if (file_exists($_editor_path . '/plugins/autogrow/plugin.js')) { - $arr['autogrow'] = array( - 'name' => 'autogrow', - 'desc' => t('Auto Grow plugin'), - 'path' => $editor_path . '/plugins/autogrow/', - 'buttons' => FALSE, - 'default' => 'f' - ); - } - - if (file_exists($_editor_path . '/plugins/stylesheetparser/plugin.js')) { - $arr['stylesheetparser'] = array( - 'name' => 'stylesheetparser', - 'desc' => t('Stylesheet Parser plugin'), - 'path' => $editor_path . '/plugins/stylesheetparser/', - 'buttons' => FALSE, - 'default' => 'f' - ); - } - } - else { - $_editor_url = ckeditor_path('url'); - if (preg_match("/\/(standard|full)-all/", $_editor_url)) { - $arr['tableresize'] = array( - 'name' => 'tableresize', - 'desc' => t('Table Resize plugin. See !link for more details.', array( - '!link' => l(t('addon page'), 'http://ckeditor.com/addon/tableresize') - )), - 'path' => $_editor_url . '/plugins/tableresize/', - 'buttons' => FALSE, - 'default' => 't' - ); - $arr['autogrow'] = array( - 'name' => 'autogrow', - 'desc' => t('Auto Grow plugin. See !link for more details.', array( - '!link' => l(t('addon page'), 'http://ckeditor.com/addon/autogrow') - )), - 'path' => $_editor_url . '/plugins/autogrow/', - 'buttons' => FALSE, - 'default' => 'f' - ); - $arr['stylesheetparser'] = array( - 'name' => 'stylesheetparser', - 'desc' => t('Stylesheet Parser plugin. See !link for more details.', array( - '!link' => l(t('addon page'), 'http://ckeditor.com/addon/stylesheetparser') - )), - 'path' => $_editor_url . '/plugins/stylesheetparser/', - 'buttons' => FALSE, - 'default' => 'f' - ); - $arr['codesnippet'] = array( - 'name' => 'codesnippet', - 'desc' => t('Plugin for inserting Code Snippets. See !link for more details. See !help for additional instructions.', array( - '!link' => l(t('addon page'), 'http://ckeditor.com/addon/codesnippet'), - '!help' => l(t('help'), 'admin/help/ckeditor', array('fragment' => 'codesnippet')) - )), - 'path' => $_editor_url . '/plugins/codesnippet/', - 'buttons' => array( - 'CodeSnippet' => array( - 'icon' => 'icons/codesnippet.png', - 'label' => 'Insert Code Snippet', - ) - ), - 'default' => 'f' - ); - $arr['mathjax'] = array( - 'name' => 'mathjax', - 'desc' => t('Plugin for inserting Mathematical Formula (MathJax). See !link for more details. See !help for additional instructions.', array( - '!link' => l(t('addon page'), 'http://ckeditor.com/addon/mathjax'), - '!help' => l(t('help'), 'admin/help/ckeditor', array('fragment' => 'mathjax')) - )), - 'path' => $_editor_url . '/plugins/mathjax/', - 'buttons' => array( - 'Mathjax' => array( - 'icon' => 'icons/mathjax.png', - 'label' => 'Insert Mathematical Formulas', - ) - ), - 'default' => 'f' - ); - } - } - - /* - * CKEditor module plugins - */ - $_plugin_dir = ckeditor_module_path('local') . '/plugins/'; - if ($handle = opendir($_plugin_dir)) { - while (false !== ($file = readdir($handle))) { - if (is_dir($_plugin_dir . $file) && file_exists($_plugin_dir . $file . '/plugin.js')) { - $source = file_get_contents($_plugin_dir . $file . '/plugin.js'); - $buttons = array(); - if (preg_match_all($pattern, $source, $matches)) { - foreach ($matches[1] as $i => $button_name) { - if (preg_match('#(icon)[\s]*\:[\s]*([^\,\n]*)#', $matches[2][$i], $matches2)) { - $buttons[$button_name] = array(); - $buttons[$button_name]['label'] = $button_name; - $matches2[2] = str_replace(array('this.path', '+', '\'', '"'), array('', '', '', ''), $matches2[2]); - $buttons[$button_name]['icon'] = trim($matches2[2]); - } - } - } - if (preg_match('#@file ([^\n\r]*)#', $source, $matches)) { - $arr[$file] = array( - 'name' => $file, - 'desc' => t($matches[1]), - 'path' => $plugin_dir . $file . '/', - 'buttons' => (count($buttons) > 0) ? $buttons : FALSE, - 'default' => 'f' - ); - } - else { - $arr[$file] = array( - 'name' => $file, - 'desc' => t('Plugin file: ' . $file), - 'path' => $plugin_dir . $file . '/', - 'buttons' => (count($buttons) > 0) ? $buttons : FALSE, - 'default' => 'f' - ); - } - } - } - closedir($handle); - } - - /* - * CKEditor module plugins - additional directory - */ - $_plugin_dir_additional = ckeditor_plugins_path('local') . '/'; - if ($_plugin_dir != $_plugin_dir_additional && is_dir($_plugin_dir_additional) && $handle = opendir($_plugin_dir_additional)) { - while (false !== ($file = readdir($handle))) { - if (is_dir($_plugin_dir_additional . $file) && file_exists($_plugin_dir_additional . $file . '/plugin.js')) { - $source = file_get_contents($_plugin_dir_additional . $file . '/plugin.js'); - $buttons = array(); - if (preg_match_all($pattern, $source, $matches)) { - foreach ($matches[1] as $i => $button_name) { - if (preg_match('#(icon)[\s]*\:[\s]*([^\,\n]*)#', $matches[2][$i], $matches2)) { - $buttons[$button_name] = array(); - $buttons[$button_name]['label'] = $button_name; - $matches2[2] = str_replace(array('this.path', '+', '\'', '"'), array('', '', '', ''), $matches2[2]); - $buttons[$button_name]['icon'] = trim($matches2[2]); - } - } - } - if (preg_match('#@file ([^\n\r]*)#', $source, $matches)) { - $arr[$file] = array( - 'name' => $file, - 'desc' => t($matches[1]), - 'path' => $plugin_dir_additional . $file . '/', - 'buttons' => (count($buttons) > 0) ? $buttons : FALSE, - 'default' => 'f' - ); - } - else { - $arr[$file] = array( - 'name' => $file, - 'desc' => t('Plugin file: ' . $file), - 'path' => $plugin_dir_additional . $file . '/', - 'buttons' => (count($buttons) > 0) ? $buttons : FALSE, - 'default' => 'f' - ); - } - } - } - - closedir($handle); - } - - /* - * CKEditor plugins registered by hook - */ $plugins = module_invoke_all('ckeditor_plugin'); + // [#2159403] introduced a slight change in CKEditor API, expecting the path to a plugin returned by hook_ckeditor_plugin() to be a full URL. + // This breaks backwards compatibility for external plugins, so we're fixing it below. foreach ($plugins as $i => $plugin) { - if (file_exists($plugin['path'] . 'plugin.js')) { - $source = file_get_contents($plugin['path'] . 'plugin.js'); - $plugins[$i]['path'] = $base_path . $plugin['path']; - if (!isset($plugin['buttons']) || count($plugin['buttons']) == 0) { - $buttons = array(); - if (preg_match_all($pattern, $source, $matches)) { - foreach ($matches[1] as $j => $button_name) { - if (preg_match('#(icon)[\s]*\:[\s]*([^\,\n]*)#', $matches[2][$j], $matches2)) { - $buttons[$button_name] = array(); - $buttons[$button_name]['label'] = $button_name; - $matches2[2] = str_replace(array('this.path', '+', '\'', '"'), array('', '', '', ''), $matches2[2]); - $buttons[$button_name]['icon'] = trim($matches2[2]); - } - } - } - $plugins[$i]['buttons'] = (count($buttons) > 0) ? $buttons : FALSE; - } - } - else { - unset($plugins[$i]); + if (strpos($plugin['path'], '%') !== 0 && !preg_match('|^(http(s)?:)?\/?\/|i', $plugin['path'])) { + $plugins[$i]['path'] = '%base_path%' . $plugin['path']; } } - $arr = array_merge($arr, $plugins); - if (isset($arr['media']) && module_exists('media') == FALSE) { - unset($arr['media']); - } + drupal_alter('ckeditor_plugin', $plugins); - if (isset($arr['imce']) && module_exists('imce') == FALSE) { - unset($arr['imce']); - } - //remove page break button if there is no module to do this - if (isset($arr['drupalbreaks']['buttons']['DrupalPageBreak']) && !module_exists('paging') && !module_exists('pagebreak') && !module_exists('smart_paging')) { - unset($arr['drupalbreaks']['buttons']['DrupalPageBreak']); - } - - if (isset($arr['drupalbreaks'])) { - $arr['drupalbreaks']['default'] = 't'; - } + ksort($plugins); - ksort($arr); if ($render === TRUE) { - $arr = ckeditor_plugins_render($arr); + $plugins = ckeditor_plugins_render($plugins); } - return $arr; + + return $plugins; } /** @@ -888,7 +627,7 @@ function ckeditor_profile_settings_compile($global_profile, $profile) { if (isset($conf['loadPlugins'])) { $settings['loadPlugins'] = ckeditor_plugins_render($conf['loadPlugins']); - if (array_key_exists('media', $settings['loadPlugins']) && module_exists('media')) { + if (array_key_exists('media', $settings['loadPlugins']) && module_exists('media') && module_hook('media', 'filter_info')) { module_load_include('inc', 'media', 'includes/media.browser'); $javascript = media_browser_js(); foreach ($javascript as $key => $definitions) { diff --git a/plugins/mediaembed/plugin.js b/plugins/mediaembed/plugin.js index e617008..7e93dc3 100644 --- a/plugins/mediaembed/plugin.js +++ b/plugins/mediaembed/plugin.js @@ -4,7 +4,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license */ /** - * @file Plugin for inserting Drupal embeded media + * @file Plugin for inserting embeded media */ ( function() { var numberRegex = /^\d+(?:\.\d+)?$/;