StylesCombo.php 4.68 KB
Newer Older
1 2 3 4
<?php

/**
 * @file
5
 * Contains \Drupal\ckeditor\Plugin\CKEditorPlugin\StylesCombo.
6 7
 */

8
namespace Drupal\ckeditor\Plugin\CKEditorPlugin;
9 10 11 12

use Drupal\ckeditor\CKEditorPluginBase;
use Drupal\ckeditor\CKEditorPluginConfigurableInterface;
use Drupal\Component\Utility\NestedArray;
13
use Drupal\editor\Entity\Editor;
14 15 16 17

/**
 * Defines the "stylescombo" plugin.
 *
18
 * @CKEditorPlugin(
19
 *   id = "stylescombo",
20
 *   label = @Translation("Styles dropdown")
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
 * )
 */
class StylesCombo extends CKEditorPluginBase implements CKEditorPluginConfigurableInterface {

  /**
   * Implements \Drupal\ckeditor\Plugin\CKEditorPluginInterface::isInternal().
   */
  public function isInternal() {
    return TRUE;
  }

  /**
   * Implements \Drupal\ckeditor\Plugin\CKEditorPluginInterface::getFile().
   */
  public function getFile() {
    // This plugin is already part of Drupal core's CKEditor build.
    return FALSE;
  }

  /**
   * Implements \Drupal\ckeditor\Plugin\CKEditorPluginInterface::getConfig().
   */
  public function getConfig(Editor $editor) {
    $config = array();
45 46
    $settings = $editor->getSettings();
    if (!isset($settings['plugins']['stylescombo']['styles'])) {
47 48
      return $config;
    }
49
    $styles = $settings['plugins']['stylescombo']['styles'];
50
    $config['stylesSet'] = $this->generateStylesSetSetting($styles);
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
    return $config;
  }

  /**
   * Implements \Drupal\ckeditor\Plugin\CKEditorPluginButtonsInterface::getButtons().
   */
  public function getButtons() {
    return array(
      'Styles' => array(
        'label' => t('Font style'),
        'image_alternative' => '<a href="#" role="button" aria-label="' . t('Styles') . '"><span class="ckeditor-button-dropdown">' . t('Styles') . '<span class="ckeditor-button-arrow"></span></span></a>',
      ),
    );
  }

  /**
   * Implements \Drupal\ckeditor\Plugin\CKEditorPluginConfigurableInterface::settingsForm().
   */
  public function settingsForm(array $form, array &$form_state, Editor $editor) {
    // Defaults.
    $config = array('styles' => '');
72 73 74
    $settings = $editor->getSettings();
    if (isset($settings['plugins']['stylescombo'])) {
      $config = $settings['plugins']['stylescombo'];
75 76 77 78 79 80 81 82 83
    }

    $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: element.class|Label. Example: h1.title|Title.<br />These styles should be available in your theme\'s CSS file.'),
      '#attached' => array(
84
        'library' => array('ckeditor/drupal.ckeditor.stylescombo.admin'),
85 86 87 88 89 90 91 92 93 94 95 96 97 98
      ),
      '#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) {
99
      form_error($element, $form_state, t('The provided list of styles is syntactically incorrect.'));
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
    }
  }

  /**
   * 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;
      }

132 133
      // Validate syntax: element[.class...]|label pattern expected.
      if (!preg_match('@^ *[a-zA-Z0-9]+ *(\\.[a-zA-Z0-9_-]+ *)*\\| *.+ *$@', $style)) {
134 135 136 137 138 139 140 141 142 143
        return FALSE;
      }

      // Parse.
      list($selector, $label) = explode('|', $style);
      $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
144
      $configured_style = array(
145 146 147
        'name' => trim($label),
        'element' => trim($element),
      );
148 149 150 151 152 153
      if (!empty($classes)) {
        $configured_style['attributes'] = array(
          'class' => implode(' ', array_map('trim', $classes))
        );
      }
      $styles_set[] = $configured_style;
154 155 156 157 158
    }
    return $styles_set;
  }

}