You are here

public function CKEditor5::buildConfigurationForm in Drupal 10

File

core/modules/ckeditor5/src/Plugin/Editor/CKEditor5.php, line 264

Class

CKEditor5
Defines a CKEditor 5-based text editor for Drupal.

Namespace

Drupal\ckeditor5\Plugin\Editor

Code

public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
  $editor = $form_state
    ->get('editor');
  assert($editor instanceof Editor);
  $language = $this->languageManager
    ->getCurrentLanguage();

  // When enabling CKEditor 5, generate sensible settings from the
  // pre-existing text editor/format rather than the hardcoded defaults
  // whenever possible.
  // @todo Remove after https://www.drupal.org/project/drupal/issues/3226673.
  $format = $form_state
    ->getFormObject()
    ->getEntity();
  assert($format instanceof FilterFormatInterface);
  if ($editor
    ->isNew() && !$form_state
    ->get('ckeditor5_is_active') && $form_state
    ->get('ckeditor5_is_selected')) {
    assert($editor
      ->getSettings() === $this
      ->getDefaultSettings());
    if (!$format
      ->isNew()) {
      [
        $editor,
        $messages,
      ] = $this->smartDefaultSettings
        ->computeSmartDefaultSettings($editor, $format);
      $form_state
        ->set('used_smart_default_settings', TRUE);
      foreach ($messages as $type => $messages_per_type) {
        foreach ($messages_per_type as $message) {
          $this
            ->messenger()
            ->addMessage($message, $type);
        }
      }
      if (isset($messages[MessengerInterface::TYPE_WARNING]) || isset($messages[MessengerInterface::TYPE_ERROR])) {
        $this
          ->messenger()
          ->addMessage($this
          ->t('Check <a href=":handbook">this handbook page</a> for details about compatibility issues of contrib modules.', [
          ':handbook' => 'https://www.drupal.org/node/3273985',
        ]), MessengerInterface::TYPE_WARNING);
      }
    }
    $eventual_editor_and_format = $this
      ->getEventualEditorWithPrimedFilterFormat($form_state, $editor);

    // Provide the validated eventual pair in form state to
    // ::getGeneratedAllowedHtmlValue(), to update filter_html's
    // "allowed_html".
    $form_state
      ->set('ckeditor5_validated_pair', $eventual_editor_and_format);

    // Ensure that CKEditor 5 plugins that need to interact with the Editor
    // config entity are able to access the computed Editor, which was cloned
    // from $form_state->get('editor').
    // @see \Drupal\ckeditor5\Plugin\CKEditor5Plugin\ImageUpload::buildConfigurationForm
    $form_state
      ->set('editor', $editor);
  }
  if ($css_warning = $this->stylesheetsMessage
    ->getWarning()) {

    // Explicitly render this single warning message visually close to the
    // text editor since this is a very long form. Otherwise, it may be
    // interpreted as a text format problem, or ignored entirely.
    // All other messages will be rendered in the default location.
    // @see \Drupal\Core\Render\Element\StatusMessages
    $form['css_warning'] = [
      '#theme' => 'status_messages',
      '#message_list' => [
        'warning' => [
          $css_warning,
        ],
      ],
      '#status_headings' => [
        'warning' => t('Warning message'),
      ],
    ];
  }

  // AJAX validation errors should appear visually close to the text editor
  // since this is a very long form: otherwise they would not be noticed.
  $form['real_time_validation_errors_location'] = [
    '#type' => 'container',
    '#id' => 'ckeditor5-realtime-validation-messages-container',
  ];
  $form['toolbar'] = [
    '#type' => 'container',
    '#title' => $this
      ->t('CKEditor 5 toolbar configuration'),
    '#theme' => 'ckeditor5_settings_toolbar',
    '#attached' => [
      'library' => $this->ckeditor5PluginManager
        ->getAdminLibraries(),
      'drupalSettings' => [
        'ckeditor5' => [
          'language' => [
            'dir' => $language
              ->getDirection(),
            'langcode' => $language
              ->getId(),
          ],
        ],
      ],
    ],
  ];
  $form['available_items_description'] = [
    '#type' => 'container',
    '#markup' => $this
      ->t('Press the down arrow key to add to the toolbar.'),
    '#id' => 'available-button-description',
    '#attributes' => [
      'class' => [
        'visually-hidden',
      ],
    ],
  ];
  $form['active_items_description'] = [
    '#type' => 'container',
    '#markup' => $this
      ->t('Move this button in the toolbar by pressing the left or right arrow keys. Press the up arrow key to remove from the toolbar.'),
    '#id' => 'active-button-description',
    '#attributes' => [
      'class' => [
        'visually-hidden',
      ],
    ],
  ];

  // The items are encoded in markup to provide a no-JS fallback.
  // Although CKEditor 5 is useless without JS it would still be possible
  // to see all the available toolbar items provided by plugins in the format
  // that needs to be entered in the textarea. The UI app parses this list.
  $form['toolbar']['available'] = [
    '#type' => 'container',
    '#title' => 'Available items',
    '#id' => 'ckeditor5-toolbar-buttons-available',
    'available_items' => [
      '#markup' => Json::encode($this->ckeditor5PluginManager
        ->getToolbarItems()),
    ],
  ];
  $editor_settings = $editor
    ->getSettings();

  // This form field requires a JSON-style array of valid toolbar items.
  // e.g. ["bold","italic","|","uploadImage"].
  // CKEditor 5 config for toolbar items takes an array of strings which
  // correspond to the keys under toolbar_items in a plugin yml or annotation.
  // @see https://ckeditor.com/docs/ckeditor5/latest/features/toolbar/toolbar.html
  $form['toolbar']['items'] = [
    '#type' => 'textarea',
    '#title' => $this
      ->t('Toolbar items'),
    '#rows' => 1,
    '#default_value' => Json::encode($editor_settings['toolbar']['items']),
    '#id' => 'ckeditor5-toolbar-buttons-selected',
    '#attributes' => [
      'tabindex' => '-1',
      'aria-hidden' => 'true',
    ],
  ];
  $form['plugin_settings'] = [
    '#type' => 'vertical_tabs',
    '#title' => $this
      ->t('CKEditor5 plugin settings'),
    '#id' => 'ckeditor5-plugin-settings',
  ];
  $this
    ->injectPluginSettingsForm($form, $form_state, $editor);

  // Allow reliable detection of switching to CKEditor 5 from another text
  // editor (or none at all).
  $form['is_already_using_ckeditor5'] = [
    '#type' => 'hidden',
    '#default_value' => TRUE,
  ];
  return $form;
}