diff --git a/core/modules/ckeditor/ckeditor.admin.inc b/core/modules/ckeditor/ckeditor.admin.inc index 21be21d..9bffcc8 100644 --- a/core/modules/ckeditor/ckeditor.admin.inc +++ b/core/modules/ckeditor/ckeditor.admin.inc @@ -21,6 +21,7 @@ */ function template_preprocess_ckeditor_settings_toolbar(&$variables) { $language_interface = \Drupal::languageManager()->getCurrentLanguage(); + $language_direction = $language_interface->getDirection(); // Create lists of active and disabled buttons. $editor = $variables['editor']; @@ -60,53 +61,49 @@ function template_preprocess_ckeditor_settings_toolbar(&$variables) { } $disabled_buttons = array_diff_key($buttons, $multiple_buttons); - $rtl = $language_interface->getDirection() === LanguageInterface::DIRECTION_RTL ? '_rtl' : ''; - - $build_button_item = function($button, $rtl) { - // Value of the button item. - if (isset($button['image_alternative' . $rtl])) { - $value = $button['image_alternative' . $rtl]; - } - elseif (isset($button['image_alternative'])) { - $value = $button['image_alternative']; - } - elseif (isset($button['image'])) { - $value = array( - '#theme' => 'image', - '#uri' => $button['image' . $rtl], - '#title' => $button['label'], - '#prefix' => '', - '#suffix' => '', - ); - } - else { - $value = '?'; + // Create the internal & external buttons for the CKEditor toolbar. + $build_button = function($button, $language_direction) { + // Set additional attribute on the button if it can occur multiple times. + if (!empty($button['multiple'])) { + $button['attributes']['class'][] = 'ckeditor-multiple-button'; } - // Build the button attributes. - $attributes = array( - 'data-drupal-ckeditor-button-name' => $button['name'], - ); - if (!empty($button['attributes'])) { - $attributes = array_merge($attributes, $button['attributes']); - } + $button['attributes']['data-drupal-ckeditor-button-name'] = $button['name']; + $button['attributes']['class'][] = 'ckeditor-button'; + $button['attributes'] = new Attribute($button['attributes']); + + // Add language direction property. + $button['language_direction'] = $language_direction; - // Build the button item. - $button_item = array( - 'value' => $value, - 'attributes' => new Attribute($attributes), - ); - // If this button has group information, add it to the attributes. - if (!empty($button['group'])) { - $button_item['group'] = $button['group']; + // Check for the image button to be present and convert file URI to URL. + if (!empty($button['image_button']) || !empty($button['image_button_rtl'])) { + // The language direction is RTL, check for image_rtl otherwise use the + // default image button path. + if ($language_direction === LanguageInterface::DIRECTION_RTL && !empty($button['image_button_rtl'])) { + $button['image_url'] = file_create_url($button['image_button_rtl']); + } + elseif(!empty($button['image_button'])) { + $button['image_url'] = file_create_url($button['image_button']); + } + } + // Check for the HTML markup for a button and convert it to safe markup. + if (!empty($button['html_button']) || !empty($button['html_button_rtl'])) { + // The language direction is RTL, check for html_button_rtl otherwise use the + // default html_button. + if ($language_direction === LanguageInterface::DIRECTION_RTL && !empty($button['html_button_rtl'])) { + $button['html_button_safemarkup'] = SafeMarkup::checkAdminXss($button['html_button_rtl']); + } + elseif (!empty($button['html_button'])) { + $button['html_button_safemarkup'] = SafeMarkup::checkAdminXss($button['html_button']); + } } // Set additional flag on the button if it can occur multiple times. if (!empty($button['multiple'])) { - $button_item['multiple'] = true; + $button['multiple'] = true; } - return $button_item; + return $button; }; // Assemble list of disabled buttons (which are always a single row). @@ -121,18 +118,18 @@ function template_preprocess_ckeditor_settings_toolbar(&$variables) { return $button['group'] === $group_name; }); foreach ($buttons as $button) { - $variables['active_buttons'][$row_number][$group_name]['buttons'][] = $build_button_item($button, $rtl); + $variables['active_buttons'][$row_number][$group_name]['buttons'][] = $build_button($button, $language_direction); } } } // Assemble list of disabled buttons (which are always a single row). $variables['disabled_buttons'] = array(); foreach ($disabled_buttons as $button) { - $variables['disabled_buttons'][] = $build_button_item($button, $rtl); + $variables['disabled_buttons'][] = $build_button($button, $language_direction); } // Assemble list of multiple buttons that may be added multiple times. $variables['multiple_buttons'] = array(); foreach ($multiple_buttons as $button) { - $variables['multiple_buttons'][] = $build_button_item($button, $rtl); + $variables['multiple_buttons'][] = $build_button($button, $language_direction); } } diff --git a/core/modules/ckeditor/src/CKEditorPluginButtonsInterface.php b/core/modules/ckeditor/src/CKEditorPluginButtonsInterface.php index 494e345..d1172d2 100644 --- a/core/modules/ckeditor/src/CKEditorPluginButtonsInterface.php +++ b/core/modules/ckeditor/src/CKEditorPluginButtonsInterface.php @@ -42,12 +42,27 @@ * Each button should by keyed by its CKEditor button name, and should * contain an array of button properties, including: * - label: A human-readable, translated button name. - * - image: An image for the button to be used in the toolbar. - * - image_rtl: If the image needs to have a right-to-left version, specify - * an alternative file that will be used in RTL editors. - * - image_alternative: If this button does not render as an image, specify - * an HTML string representing the contents of this button. - * - image_alternative_rtl: Similar to image_alternative, but a + * - text_button: A button that only supplies the name of the button in the + * plugin declaration which to be used in the toolbar. If used with + * "text_button_alt_label" key then the value in the "text_button_alt_label" is + * displayed instead of "label" in the front end CKEditor toolbar. + * - text_button_rtl: A flag that sets as TRUE or FALSE to tell the system + * about the language direction. If TRUE then system loades the RTL + * version of the button too. + * - text_button_alt_label: An alternative button label. This can be used if a + * plugin wants to show a different button label instead of the actual + * "label". + * - is_dropdown: Flag to specify if the button is a type of a drop-down + * button. If set to TRUE then "ckeditor-button-dropdown" class is added to + * the button's HTML. + * - image_button: An image for the button to be used in the toolbar. + * - image_button_rtl: If the image needs to have a right-to-left version, specify + * an alternative file that will be used in RTL editors else the default + * "image_button" is loaded. + * - html_button: If the button doesn't render as an text button or an image + * button then this can be used. Basically designed for those plugins which + * supply raw HTML for their buttons to be displayed in the editor toolbar. + * - html_button_rtl: Similar to html_button, but a * right-to-left version. * - attributes: An array of HTML attributes which should be added to this * button when rendering the button in the administrative section for diff --git a/core/modules/ckeditor/src/Plugin/CKEditorPlugin/DrupalImage.php b/core/modules/ckeditor/src/Plugin/CKEditorPlugin/DrupalImage.php index 080c017..8060e78 100644 --- a/core/modules/ckeditor/src/Plugin/CKEditorPlugin/DrupalImage.php +++ b/core/modules/ckeditor/src/Plugin/CKEditorPlugin/DrupalImage.php @@ -56,7 +56,7 @@ public function getButtons() { return array( 'DrupalImage' => array( 'label' => t('Image'), - 'image' => drupal_get_path('module', 'ckeditor') . '/js/plugins/drupalimage/image.png', + 'image_button' => drupal_get_path('module', 'ckeditor') . '/js/plugins/drupalimage/image.png', ), ); } diff --git a/core/modules/ckeditor/src/Plugin/CKEditorPlugin/DrupalLink.php b/core/modules/ckeditor/src/Plugin/CKEditorPlugin/DrupalLink.php index dbfc07f..3f91209 100644 --- a/core/modules/ckeditor/src/Plugin/CKEditorPlugin/DrupalLink.php +++ b/core/modules/ckeditor/src/Plugin/CKEditorPlugin/DrupalLink.php @@ -55,11 +55,11 @@ public function getButtons() { return array( 'DrupalLink' => array( 'label' => t('Link'), - 'image' => $path . '/link.png', + 'image_button' => $path . '/link.png', ), 'DrupalUnlink' => array( 'label' => t('Unlink'), - 'image' => $path . '/unlink.png', + 'image_button' => $path . '/unlink.png', ), ); } diff --git a/core/modules/ckeditor/src/Tests/CKEditorLanguageDirectionTest.php b/core/modules/ckeditor/src/Tests/CKEditorLanguageDirectionTest.php new file mode 100644 index 0000000..53126e6 --- /dev/null +++ b/core/modules/ckeditor/src/Tests/CKEditorLanguageDirectionTest.php @@ -0,0 +1,77 @@ + 'full_html', + 'name' => 'Full HTML', + 'weight' => 1, + 'filters' => array(), + ))->save(); + Editor::create(array( + 'format' => 'full_html', + 'editor' => 'ckeditor', + ))->save(); + + // Create a new user with admin rights. + $this->admin_user = $this->drupalCreateUser(array( + 'administer languages', + 'access administration pages', + 'administer site configuration', + 'administer filters', + )); + } + + /** + * Tests that CKEditor RTL classes are being added. + */ + public function testLanguageDirectionChange() { + $this->drupalLogin($this->admin_user); + + // Install the Arabic language (which is RTL) and configure as the default. + $edit = array(); + $edit['predefined_langcode'] = 'ar'; + $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language')); + + $edit = array('site_default_language' => 'ar'); + $this->drupalPostForm('admin/config/regional/settings', $edit, t('Save configuration')); + + // Once the default language is changed, go to the tested text format + // configuration page. + $this->drupalGet('admin/config/content/formats/manage/full_html'); + $this->assertPattern('|cke_rtl|', 'Correct language direction classes are being added.'); + } + +} diff --git a/core/modules/ckeditor/templates/ckeditor-settings-toolbar.html.twig b/core/modules/ckeditor/templates/ckeditor-settings-toolbar.html.twig index 4f5f43b..8d33e52 100644 --- a/core/modules/ckeditor/templates/ckeditor-settings-toolbar.html.twig +++ b/core/modules/ckeditor/templates/ckeditor-settings-toolbar.html.twig @@ -3,7 +3,23 @@ * @file * Default theme implementation for the CKEditor settings toolbar. * + * This template uses Twig macro to create the CKEditor buttons. + * @see http://twig.sensiolabs.org/doc/tags/macro.html + * * Available variables: + * - button: A list containing the CKEditor buttons. + * - text_button: Indentifier of a text only button. + * - is_dropdown: Flag for showing a dropdown type button (Optional). If the + * value is true then a dropdown button is generated. + * - is_separator: Flag for showing a separator "button" (Optional). If the + * value is true then a separator button is generated for the toolbar UI. + * - label: A human-readable, translated button name. + * - text_button_alt_label: Same as label but this can be used as a custom button name. + * - language_direction: The direction, left-to-right, or right-to-left. + * - image_url: Image URL for the button. If the button is an image, then + * this has to be used. + * - html_button_safemarkup: Generated from the html_button or html_button_rtl as + * a safe markup HTML. * - multiple_buttons: A list of buttons that may be added multiple times. * - disabled_buttons: A list of disabled buttons. * - active_buttons: A list of active button rows. @@ -13,6 +29,43 @@ * @ingroup themeable */ #} +{% macro button(button) %} + {# Buttons with text as labels #} + {% if button.text_button %} + {# Set the button's title provided by the plugin #} + {% set button_text = not button.text_button_alt_label ? button.label : button.text_button_alt_label %} + {# Dropdown Buttons. #} + {% if button.is_dropdown %} + + {{ button_text }} + + {# Separator Buttons. #} + {% elseif button.is_separator %} + + {# Normal Buttons. #} + {% else %} + + {{ button_text }} + + {% endif %} + {# Buttons with image as labels. #} + {% elseif button.image_url %} + + + {{ button.label }} + + + {% elseif button.html_button_safemarkup %} + {{ button.html_button_safemarkup }} + {% endif %} + +{% endmacro %} + +{# + Reference the defined macro to be used in the same template. + @see http://twig.sensiolabs.org/doc/templates.html#global-variables +#} +{% import _self as ckeditor %} {% spaceless %}
{{ 'Toolbar configuration'|t }} @@ -28,7 +81,7 @@ @@ -37,7 +90,7 @@ @@ -56,7 +109,7 @@

{{ group_name }}