core/modules/ckeditor/ckeditor.admin.inc | 8 +- core/modules/ckeditor/ckeditor.module | 13 +- core/modules/ckeditor/js/ckeditor.admin.js | 18 ++- .../ckeditor/js/ckeditor.stylescombo.admin.js | 52 +++++++ .../Drupal/ckeditor/CKEditorPluginInterface.php | 2 +- .../ckeditor/Plugin/ckeditor/plugin/Internal.php | 52 ++----- .../Plugin/ckeditor/plugin/StylesCombo.php | 159 ++++++++++++++++++++ .../ckeditor/Plugin/editor/editor/CKEditor.php | 2 +- .../Drupal/ckeditor/Tests/CKEditorAdminTest.php | 21 +-- .../ckeditor/Tests/CKEditorPluginManagerTest.php | 6 +- .../lib/Drupal/ckeditor/Tests/CKEditorTest.php | 94 ++++++++++-- 11 files changed, 346 insertions(+), 81 deletions(-) diff --git a/core/modules/ckeditor/ckeditor.admin.inc b/core/modules/ckeditor/ckeditor.admin.inc index f7e414d..c5b459b 100644 --- a/core/modules/ckeditor/ckeditor.admin.inc +++ b/core/modules/ckeditor/ckeditor.admin.inc @@ -20,8 +20,8 @@ function template_preprocess_ckeditor_settings_toolbar(&$variables) { $plugins = $variables['plugins']; $buttons = array(); $variables['multiple_buttons'] = array(); - foreach ($plugins as $plugin => $buttons) { - foreach ($buttons as $button_name => $button) { + foreach ($plugins as $plugin => $plugin_buttons) { + foreach ($plugin_buttons as $button_name => $button) { $button['name'] = $button_name; if (!empty($button['multiple'])) { $variables['multiple_buttons'][$button_name] = $button; @@ -113,7 +113,7 @@ function theme_ckeditor_settings_toolbar($variables) { // active or disabled list, as theme_item_list() will not print an empty UL. $output = ''; $output .= '' . t('Active toolbar') . ''; - $output .= '
'; + $output .= '
'; foreach ($active_buttons as $button_row) { $output .= '
'; $output .= '' . t('Available buttons') . ''; - $output .= '
'; + $output .= '
'; $output .= '
    '; $output .= $print_buttons($disabled_buttons); $output .= '
'; diff --git a/core/modules/ckeditor/ckeditor.module b/core/modules/ckeditor/ckeditor.module index be8c834..2a7a3bf 100644 --- a/core/modules/ckeditor/ckeditor.module +++ b/core/modules/ckeditor/ckeditor.module @@ -36,7 +36,7 @@ function ckeditor_library_info() { ), ); $libraries['drupal.ckeditor.admin'] = array( - 'title' => 'Drupal behavior to enable CKEditor on textareas.', + 'title' => 'Drupal behavior for drag-and-drop CKEditor toolbar builder UI.', 'version' => VERSION, 'js' => array( $module_path . '/js/ckeditor.admin.js' => array(), @@ -51,6 +51,17 @@ function ckeditor_library_info() { array('system', 'jquery.ui.draggable'), ), ); + $libraries['drupal.ckeditor.stylescombo.admin'] = array( + 'title' => 'Only show the "stylescombo" plugin settings when its button is enabled.', + 'version' => VERSION, + 'js' => array( + $module_path . '/js/ckeditor.stylescombo.admin.js' => array(), + ), + 'dependencies' => array( + array('system', 'jquery.once'), + array('system', 'drupal.vertical-tabs'), + ), + ); $libraries['ckeditor'] = array( 'title' => 'Loads the main CKEditor library.', 'version' => '4.0.1', diff --git a/core/modules/ckeditor/js/ckeditor.admin.js b/core/modules/ckeditor/js/ckeditor.admin.js index d22ac6e..18c070f 100644 --- a/core/modules/ckeditor/js/ckeditor.admin.js +++ b/core/modules/ckeditor/js/ckeditor.admin.js @@ -73,7 +73,8 @@ Drupal.behaviors.ckeditorAdmin = { } /** - * jQuery Sortable stop event. Save updated toolbar positions to the textarea. + * jQuery Sortable stop event. Save updated toolbar positions to the + * textarea. */ function adminToolbarValue(event, ui) { // Update the toolbar config after updating a sortable. @@ -89,12 +90,21 @@ Drupal.behaviors.ckeditorAdmin = { } }); $textarea.val(JSON.stringify(toolbarConfig, null, ' ')); + + // Determine whether we should trigger an event. + var from = $(event.target).parents('div[data-toolbar]').attr('data-toolbar'); + var to = $(event.toElement).parents('div[data-toolbar]').attr('data-toolbar'); + if (from !== to) { + $wrapper + .find('.ckeditor-toolbar-active') + .trigger('CKEditorToolbarChanged', [ + (to === 'active') ? 'added' : 'removed', + $(ui.item).get(0).getAttribute('data-button-name') + ]); + } } }); - }, - detach: function (context, settings) { - // @todo } }; diff --git a/core/modules/ckeditor/js/ckeditor.stylescombo.admin.js b/core/modules/ckeditor/js/ckeditor.stylescombo.admin.js new file mode 100644 index 0000000..707bf4b --- /dev/null +++ b/core/modules/ckeditor/js/ckeditor.stylescombo.admin.js @@ -0,0 +1,52 @@ +(function ($, Drupal) { + +"use strict"; + +/** + * Shows the "stylescombo" plugin settings only when the button is enabled. + */ +Drupal.behaviors.ckeditorStylesComboSettingsVisibility = { + attach: function (context, settings) { + var $stylesComboVerticalTab = $('#edit-editor-settings-plugins-stylescombo').data('verticalTab'); + + // Hide if the "Styles" button is disabled. + if ($('.ckeditor-toolbar-disabled li[data-button-name="Styles"]').length === 1) { + $stylesComboVerticalTab.tabHide(); + } + + // React to added/removed toolbar buttons. + $(context) + .find('.ckeditor-toolbar-active') + .on('CKEditorToolbarChanged', function (e, action, button) { + if (button === 'Styles') { + if (action === 'added') { + $stylesComboVerticalTab.tabShow(); + } + else { + $stylesComboVerticalTab.tabHide(); + } + } + }); + } +}; + +/** + * Provides the summary for the "stylescombo" plugin settings vertical tab. + */ +Drupal.behaviors.ckeditorStylesComboSettingsSummary = { + attach: function (context, settings) { + $('#edit-editor-settings-plugins-stylescombo') + .drupalSetSummary(function (context) { + var styles = $.trim($('#edit-editor-settings-plugins-stylescombo-styles').val()); + if (styles.length === 0) { + return Drupal.t('No styles configured'); + } + else { + var count = $.trim(styles).split("\n").length; + return Drupal.t('@count styles configured', { '@count': count}); + } + }); + } +}; + +})(jQuery, Drupal); diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/CKEditorPluginInterface.php b/core/modules/ckeditor/lib/Drupal/ckeditor/CKEditorPluginInterface.php index 7ce1f99..601cafb 100644 --- a/core/modules/ckeditor/lib/Drupal/ckeditor/CKEditorPluginInterface.php +++ b/core/modules/ckeditor/lib/Drupal/ckeditor/CKEditorPluginInterface.php @@ -14,7 +14,7 @@ * Defines an interface for (loading of) CKEditor plugins. * * This is the most basic CKEditor plugin interface; it provides the bare - * minimal information. Solely implementing this interface is not sufficient to + * minimum information. Solely implementing this interface is not sufficient to * be able to enable the plugin though — a CKEditor plugin can either be enabled * automatically when a button it provides is present in the toolbar, or when * some programmatically defined condition is true. In the former case, diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/ckeditor/plugin/Internal.php b/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/ckeditor/plugin/Internal.php index fffed1d..0260abf 100644 --- a/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/ckeditor/plugin/Internal.php +++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/ckeditor/plugin/Internal.php @@ -8,14 +8,13 @@ namespace Drupal\ckeditor\Plugin\ckeditor\plugin; use Drupal\ckeditor\CKEditorPluginBase; -use Drupal\ckeditor\CKEditorPluginConfigurableInterface; use Drupal\Component\Utility\NestedArray; use Drupal\Core\Annotation\Plugin; use Drupal\Core\Annotation\Translation; use Drupal\editor\Plugin\Core\Entity\Editor; /** - * Defines the "internal" plugin (i.e. CKEditor plugins shipped with our build). + * Defines the "internal" plugin (i.e. core plugins part of our CKEditor build). * * @Plugin( * id = "internal", @@ -23,19 +22,19 @@ * module = "ckeditor" * ) */ -class Internal extends CKEditorPluginBase implements CKEditorPluginConfigurableInterface { +class Internal extends CKEditorPluginBase { /** * Implements \Drupal\ckeditor\Plugin\CKEditorPluginInterface::isInternal(). */ - function isInternal() { + public function isInternal() { return TRUE; } /** * Implements \Drupal\ckeditor\Plugin\CKEditorPluginInterface::getFile(). */ - function getFile() { + public function getFile() { // This plugin is already part of Drupal core's CKEditor build. return FALSE; } @@ -52,6 +51,11 @@ public function getConfig(Editor $editor) { 'coreStyles_underline' => array('element' => 'span', 'attributes' => array('class' => 'underline')), 'removeDialogTabs' => 'image:Link;image:advanced;link:advanced', 'resize_dir' => 'vertical', + 'keystrokes' => array( + // 0x11000 is CKEDITOR.CTRL, see http://docs.ckeditor.com/#!/api/CKEDITOR-property-CTRL. + array(0x110000 + 75, 'link'), + array(0x110000 + 76, NULL), + ), ); // Next, add the format_tags setting, if its button is enabled. @@ -60,24 +64,13 @@ public function getConfig(Editor $editor) { $config['format_tags'] = $this->generateFormatTagsSetting($editor); } - // Finally, set the configurable settings. - if (isset($editor->settings['plugins']['internal'])) { - if ($editor->settings['plugins']['internal']['link_shortcut'] === 'CTRL+K') { - $config['keystrokes'] = array( - // 0x11000 is CKEDITOR.CTRL, see http://docs.ckeditor.com/#!/api/CKEDITOR-property-CTRL. - array(0x110000 + 75, 'link'), - array(0x110000 + 76, NULL), - ); - } - } - return $config; } /** * Implements \Drupal\ckeditor\Plugin\CKEditorPluginButtonsInterface::getButtons(). */ - function getButtons() { + public function getButtons() { $button = function($name, $direction = 'ltr') { return ' '; }; @@ -267,30 +260,6 @@ function getButtons() { } /** - * Implements \Drupal\ckeditor\Plugin\CKEditorPluginConfigurableInterface::settingsForm(). - */ - function settingsForm(array $form, array &$form_state, Editor $editor) { - // Defaults. - $config = array('link_shortcut' => 'CTRL+L'); - if (isset($editor->settings['plugins']['internal'])) { - $config = $editor->settings['plugins']['internal']; - } - - $form['link_shortcut'] = array( - '#title' => t('"Create link" keyboard shortcut'), - '#type' => 'radios', - '#options' => array( - 'CTRL+L' => t('CTRL+L (default)'), - 'CTRL+K' => t('CTRL+K'), - ), - '#default_value' => $config['link_shortcut'], - '#description' => t('In most browsers, CTRL+L will take you to the URL bar. Many online writing tools hence use CTRL+K.') - ); - - return $form; - } - - /** * Builds the "format_tags" configuration part of the CKEditor JS settings. * * @see getConfig() @@ -318,4 +287,5 @@ protected function generateFormatTagsSetting(Editor $editor) { return implode(';', $format_tags); } + } diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/ckeditor/plugin/StylesCombo.php b/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/ckeditor/plugin/StylesCombo.php new file mode 100644 index 0000000..e40e5ca --- /dev/null +++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/ckeditor/plugin/StylesCombo.php @@ -0,0 +1,159 @@ +settings['toolbar']['buttons'])); + if (in_array('Styles', $toolbar_buttons)) { + $styles = $editor->settings['plugins']['stylescombo']['styles']; + $config['stylesSet'] = $this->generateStylesSetSetting($styles); + } + + return $config; + } + + /** + * Implements \Drupal\ckeditor\Plugin\CKEditorPluginButtonsInterface::getButtons(). + */ + public function getButtons() { + return array( + 'Styles' => array( + 'label' => t('Font style'), + 'image_alternative' => '' . t('Styles') . '', + ), + ); + } + + /** + * Implements \Drupal\ckeditor\Plugin\CKEditorPluginConfigurableInterface::settingsForm(). + */ + public function settingsForm(array $form, array &$form_state, Editor $editor) { + // Defaults. + $config = array('styles' => ''); + if (isset($editor->settings['plugins']['stylescombo'])) { + $config = $editor->settings['plugins']['stylescombo']; + } + + $form['styles'] = array( + '#title' => t('Styles'), + '#title_display' => 'invisible', + '#type' => 'textarea', + '#default_value' => $config['styles'], + '#description' => t('A list of classes that will be provided in the "Styles" dropdown. Enter one class on each line in the format: label|element.class. Example: title|h1.title.
These styles should be available in your theme\'s CKEditor stylesheets as well as in your theme\'s main CSS file.'), + '#attached' => array( + 'library' => array(array('ckeditor', 'drupal.ckeditor.stylescombo.admin')), + ), + '#element_validate' => array( + array($this, 'validateStylesValue'), + ), + ); + + return $form; + } + + /** + * #element_validate handler for the "styles" element in settingsForm(). + */ + public function validateStylesValue(array $element, array &$form_state) { + if ($this->generateStylesSetSetting($element['#value']) === FALSE) { + form_error($element, t('The provided list of styles is syntactically incorrect.')); + } + } + + /** + * Builds the "stylesSet" configuration part of the CKEditor JS settings. + * + * @see getConfig() + * + * @param string $styles + * The "styles" setting. + * @return array|FALSE + * An array containing the "stylesSet" configuration, or FALSE when the + * syntax is invalid. + */ + protected function generateStylesSetSetting($styles) { + $styles_set = array(); + + // Early-return when empty. + $styles = trim($styles); + if (empty($styles)) { + return $styles_set; + } + + $styles = str_replace(array("\r\n", "\r"), "\n", $styles); + foreach (explode("\n", $styles) as $style) { + $style = trim($style); + + // Ignore empty lines in between non-empty lines. + if (empty($style)) { + continue; + } + + // Validate syntax: label|element.class[.class...] pattern expected. + if (!preg_match('@^.+\\| *[a-zA-Z0-9]+ *(\\.[a-zA-Z0-9_-]+ *)+$@', $style)) { + return FALSE; + } + + // Parse. + list($label, $selector) = explode('|', $style, 2); + $classes = explode('.', $selector); + $element = array_shift($classes); + + // Build the data structure CKEditor's stylescombo plugin expects. + // @see http://docs.cksource.com/CKEditor_3.x/Developers_Guide/Styles + $styles_set[] = array( + 'name' => trim($label), + 'element' => trim($element), + 'attributes' => array( + 'class' => implode(' ', array_map('trim', $classes)) + ), + ); + } + return $styles_set; + } + +} diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/editor/editor/CKEditor.php b/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/editor/editor/CKEditor.php index ee7cc32..379d00e 100644 --- a/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/editor/editor/CKEditor.php +++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/editor/editor/CKEditor.php @@ -74,7 +74,7 @@ public function settingsForm(array $form, array &$form_state, Editor $editor) { // CKEditor plugin settings, if any. $form['plugin_settings'] = array( '#type' => 'vertical_tabs', - '#title' => t('CKEditor plugin settings'), + '#title' => t('Optional settings'), ); $manager->injectPluginSettingsForm($form, $form_state, $editor); if (count(element_children($form['plugins'])) === 0) { diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorAdminTest.php b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorAdminTest.php index 72811e9..fa0adc9 100644 --- a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorAdminTest.php +++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorAdminTest.php @@ -64,8 +64,8 @@ function testAdmin() { $this->assertTrue(count($select) === 1, 'The Text Editor select exists.'); $this->assertTrue(count($select_is_disabled) === 0, 'The Text Editor select is not disabled.'); $this->assertTrue(count($options) === 2, 'The Text Editor select has two options.'); - $this->assertTrue(((string) $options[0]) === 'None', 'Option 1 in the he Text Editor select is "None".'); - $this->assertTrue(((string) $options[1]) === 'CKEditor', 'Option 2 in the he Text Editor select is "CKEditor".'); + $this->assertTrue(((string) $options[0]) === 'None', 'Option 1 in the Text Editor select is "None".'); + $this->assertTrue(((string) $options[1]) === 'CKEditor', 'Option 2 in the Text Editor select is "CKEditor".'); $this->assertTrue(((string) $options[0]['selected']) === 'selected', 'Option 1 ("None") is selected.'); // Select the "CKEditor" editor and click the "Configure" button. @@ -80,29 +80,24 @@ function testAdmin() { // Default configuration. $default_buttons_value = '[["Source","|","Bold","Italic","|","NumberedList","BulletedList","Blockquote","|","JustifyLeft","JustifyCenter","JustifyRight","|","Link","Unlink","|","Image","Maximize"]]'; $this->assertFieldByName('editor[settings][toolbar][buttons]', $default_buttons_value, 'Buttons configuration'); - $ctrl_l_radio = $this->xpath('//input[@type="radio" and @name="editor[settings][plugins][internal][link_shortcut]" and @value="CTRL+L" and @checked="checked"]'); - $ctrl_k_radio = $this->xpath('//input[@type="radio" and @name="editor[settings][plugins][internal][link_shortcut]" and @value="CTRL+K" and not(@checked)]'); - $this->assertTrue(count($ctrl_l_radio) === 1, 'The CTRL+L radio exists and is checked.'); - $this->assertTrue(count($ctrl_k_radio) === 1, 'The CTRL+K radio exists and is not checked.'); + $styles_textarea = $this->xpath('//textarea[@name="editor[settings][plugins][stylescombo][styles]"]'); + $this->assertFieldByXPath('//textarea[@name="editor[settings][plugins][stylescombo][styles]"]', '', 'The styles textarea exists and is empty.'); + $this->assertTrue(count($styles_textarea) === 1, 'The "styles" textarea exists.'); $this->drupalPost(NULL, $edit, t('Save configuration')); // Ensure an Editor object exists now, with the proper settings. $expected_settings = $ckeditor->getDefaultSettings(); - $expected_settings['plugins']['internal']['link_shortcut'] = 'CTRL+L'; + $expected_settings['plugins']['stylescombo']['styles'] = ''; $editor = entity_load('editor', 'filtered_html'); $this->assertTrue($editor instanceof Editor, 'An Editor config entity exists now.'); $this->assertIdentical($expected_settings, $editor->settings, 'The Editor config entity has the correct settings.'); // Configure a plugin. $edit = array( - 'editor[settings][plugins][internal][link_shortcut]' => 'CTRL+K', + 'editor[settings][plugins][stylescombo][styles]' => "Title|h1.title\nCallout|p.callout\n\n", ); $this->drupalPost(NULL, $edit, t('Save configuration')); - $ctrl_l_radio = $this->xpath('//input[@type="radio" and @name="editor[settings][plugins][internal][link_shortcut]" and @value="CTRL+L" and not(@checked)]'); - $ctrl_k_radio = $this->xpath('//input[@type="radio" and @name="editor[settings][plugins][internal][link_shortcut]" and @value="CTRL+K" and @checked="checked"]'); - $this->assertTrue(count($ctrl_l_radio) === 1, 'The CTRL+L radio exists and is not checked.'); - $this->assertTrue(count($ctrl_k_radio) === 1, 'The CTRL+K radio exists and is checked.'); - $expected_settings['plugins']['internal']['link_shortcut'] = 'CTRL+K'; + $expected_settings['plugins']['stylescombo']['styles'] = "Title|h1.title\nCallout|p.callout\n\n"; $editor = entity_load('editor', 'filtered_html'); $this->assertTrue($editor instanceof Editor, 'An Editor config entity exists.'); $this->assertIdentical($expected_settings, $editor->settings, 'The Editor config entity has the correct settings.'); diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorPluginManagerTest.php b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorPluginManagerTest.php index 4eb5524..c3e8828 100644 --- a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorPluginManagerTest.php +++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorPluginManagerTest.php @@ -67,8 +67,8 @@ function testEnabledPlugins() { $editor = entity_load('editor', 'filtered_html'); // Case 1: no CKEditor plugins. - $this->assertIdentical(array('internal'), array_keys($this->manager->getDefinitions()), 'No CKEditor plugins found besides the built-in ones.'); - $this->assertIdentical(array(), $this->manager->getEnabledPlugins($editor), 'Only the internal plugins is enabled.'); + $this->assertIdentical(array('internal', 'stylescombo'), array_keys($this->manager->getDefinitions()), 'No CKEditor plugins found besides the built-in ones.'); + $this->assertIdentical(array(), $this->manager->getEnabledPlugins($editor), 'Only built-in plugins are enabled.'); $this->assertIdentical(array('internal' => NULL), $this->manager->getEnabledPlugins($editor, TRUE), 'Only the "internal" plugin is enabled.'); // Enable the CKEditor Test module, which has the Llama plugin (plus three @@ -80,7 +80,7 @@ function testEnabledPlugins() { // Case 2: CKEditor plugins are available. $plugin_ids = array_keys($this->manager->getDefinitions()); sort($plugin_ids); - $this->assertIdentical(array('internal', 'llama', 'llama_button', 'llama_contextual', 'llama_contextual_and_button'), $plugin_ids, 'Additional CKEditor plugins found.'); + $this->assertIdentical(array('internal', 'llama', 'llama_button', 'llama_contextual', 'llama_contextual_and_button', 'stylescombo'), $plugin_ids, 'Additional CKEditor plugins found.'); $this->assertIdentical(array(), $this->manager->getEnabledPlugins($editor), 'Only the internal plugins are enabled.'); $this->assertIdentical(array('internal' => NULL), $this->manager->getEnabledPlugins($editor, TRUE), 'Only the "internal" plugin is enabled.'); diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorTest.php b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorTest.php index db2af6f..6fd31cc 100644 --- a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorTest.php +++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorTest.php @@ -74,17 +74,8 @@ function setUp() { function testGetJSSettings() { $editor = entity_load('editor', 'filtered_html'); - $ckeditor_base_config = array( - 'pasteFromWordPromptCleanup' => TRUE, - 'indentClasses' => array('indent1', 'indent2', 'indent3'), - 'justifyClasses' => array('align-left', 'align-center', 'align-right', 'align-justify'), - 'coreStyles_underline' => array('element' => 'span', 'attributes' => array('class' => 'underline')), - 'removeDialogTabs' => 'image:Link;image:advanced;link:advanced', - 'resize_dir' => 'vertical', - ); - // Default toolbar. - $expected_config = $ckeditor_base_config + array( + $expected_config = $this->getDefaultInternalConfig() + array( 'toolbar' => $this->getDefaultToolbarConfig(), 'contentsCss' => $this->getDefaultContentsCssConfig(), 'extraPlugins' => '', @@ -165,10 +156,87 @@ function testBuildContentsCssJSSetting() { } /** - * Tests CKEditor::buildFormatTagsJSSetting(). + * Tests Internal::getConfig(). + */ + function testInternalGetConfig() { + $editor = entity_load('editor', 'filtered_html'); + $manager = drupal_container()->get('plugin.manager.ckeditor.plugin'); + $internal_plugin = $manager->createInstance('internal'); + + // Default toolbar. + $expected = $this->getDefaultInternalConfig(); + $this->assertIdentical($expected, $internal_plugin->getConfig($editor), '"Internal" plugin configuration built correctly for default toolbar.'); + + // Format dropdown/button enabled: new setting should be present. + $editor->settings['toolbar']['buttons'][0][] = 'Format'; + $expected['format_tags'] = 'p;h4;h5;h6'; + $this->assertIdentical($expected, $internal_plugin->getConfig($editor), '"Internal" plugin configuration built correctly for customized toolbar.'); + } + + /** + * Tests StylesCombo::getConfig(). */ - function testBuildFormatTagsJSSetting() { - // @todo + function testStylesComboGetConfig() { + $editor = entity_load('editor', 'filtered_html'); + $manager = drupal_container()->get('plugin.manager.ckeditor.plugin'); + $stylescombo_plugin = $manager->createInstance('stylescombo'); + + // Default toolbar. + $expected = $this->getDefaultStylesComboConfig(); + $this->assertIdentical($expected, $stylescombo_plugin->getConfig($editor), '"StylesCombo" plugin configuration built correctly for default toolbar.'); + + // Styles dropdown/button enabled: new setting should be present. + $editor->settings['toolbar']['buttons'][0][] = 'Styles'; + $editor->settings['plugins']['stylescombo']['styles'] = ''; + $editor->save(); + $expected['stylesSet'] = array(); + $this->assertIdentical($expected, $stylescombo_plugin->getConfig($editor), '"StylesCombo" plugin configuration built correctly for customized toolbar.'); + + // Configure the optional "styles" setting in odd ways that shouldn't affect + // the end result. + $editor->settings['plugins']['stylescombo']['styles'] = " \n"; + $editor->save(); + $this->assertIdentical($expected, $stylescombo_plugin->getConfig($editor)); + $editor->settings['plugins']['stylescombo']['styles'] = "\r\n \n \r \n "; + $editor->save(); + $this->assertIdentical($expected, $stylescombo_plugin->getConfig($editor), '"StylesCombo" plugin configuration built correctly for customized toolbar.'); + + // Now configure it properly, the end result should change. + $editor->settings['plugins']['stylescombo']['styles'] = "Title|h1.title\nCallout|p.mAgical.Callout"; + $editor->save(); + $expected['stylesSet'] = array( + array('name' => 'Title', 'element' => 'h1', 'attributes' => array('class' => 'title')), + array('name' => 'Callout', 'element' => 'p', 'attributes' => array('class' => 'mAgical Callout')), + ); + $this->assertIdentical($expected, $stylescombo_plugin->getConfig($editor), '"StylesCombo" plugin configuration built correctly for customized toolbar.'); + + // Same configuration, but now interspersed with nonsense. Should yield the + // same result. + $editor->settings['plugins']['stylescombo']['styles'] = "Title | h1 .title\r \n\r \nCallout|p.mAgical .Callout\r"; + $editor->save(); + $this->assertIdentical($expected, $stylescombo_plugin->getConfig($editor), '"StylesCombo" plugin configuration built correctly for customized toolbar.'); + + // Invalid syntax should cause stylesSet to be set to FALSE. + $editor->settings['plugins']['stylescombo']['styles'] = "Title|h1"; + $editor->save(); + $expected['stylesSet'] = FALSE; + $this->assertIdentical($expected, $stylescombo_plugin->getConfig($editor), '"StylesCombo" plugin configuration built correctly for customized toolbar.'); + } + + protected function getDefaultInternalConfig() { + return array( + 'pasteFromWordPromptCleanup' => TRUE, + 'indentClasses' => array('indent1', 'indent2', 'indent3'), + 'justifyClasses' => array('align-left', 'align-center', 'align-right', 'align-justify'), + 'coreStyles_underline' => array('element' => 'span', 'attributes' => array('class' => 'underline')), + 'removeDialogTabs' => 'image:Link;image:advanced;link:advanced', + 'resize_dir' => 'vertical', + 'keystrokes' => array(array(0x110000 + 75, 'link'), array(0x110000 + 76, NULL)), + ); + } + + protected function getDefaultStylesComboConfig() { + return array(); } protected function getDefaultToolbarConfig() {