ckeditor5-1.0.x-dev/src/AdminUi.php

src/AdminUi.php
<?php

namespace Drupal\ckeditor5;

use Drupal\Component\Plugin\PluginManagerInterface;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\editor\Entity\Editor;

/**
 * Provide CKEditor5 admin UI functionality.
 */
class AdminUi {

  use StringTranslationTrait;

  /**
   * The CKEditor 5 plugin manager.
   *
   * @var \Drupal\Component\Plugin\PluginManagerInterface
   */
  protected $pluginManager;

  /**
   * Constructs an AdminUi object.
   *
   * @param \Drupal\Component\Plugin\PluginManagerInterface $plugin_manager
   *   The CKEditor 5 plugin manager.
   */
  public function __construct(PluginManagerInterface $plugin_manager) {
    $this->pluginManager = $plugin_manager;
  }

  /**
   * Gets submitted Editor and FilterFormat config entities from form state.
   *
   * This duplicates some form submission logic, but that is better than having
   * every single CKEditor5Plugin plugin implementation hardcoding knowledge
   * about this form — especially since it could be altered.
   *
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state of the filter format form.
   *
   * @return \Drupal\editor\Entity\Editor
   *   The submitted Editor config entity, based on the form values.
   *
   * @throws \ReflectionException
   */
  public static function getSubmittedEditorAndFilterFormat(FormStateInterface $form_state) : Editor {
    // Determine the form is currently switching to CKEditor 5 from another
    // editor. If the form was previously set to a different editor (or no
    // editor), there are two major differences that need to be accounted for:
    // - If the editor isn't CKEditor 5, #limit_validation_errors is set in a
    //   way where the only values available are 'editor' and its children.
    // - The editor may not be available in $form_state->get('editor') yet, but
    //   fortunately it's safe to use Editor::create to create a new CKEditor 5
    //   editor as the editor would be using its default configuration at the
    //   "switching to" stage.
    $switching_to_ck5 = self::isSwitchingToCkeditor5($form_state);

    if ($switching_to_ck5) {
      // Create a hypothetical version of the current editor using CKEditor 5.
      // This makes it possible to validate the editor's compatibility with
      // CKEditor 5 before the editor set within $form_state actually changes.
      $format = $form_state->getFormObject()->getEntity();
      $submitted_editor = Editor::create([
        'format' => $format->isNew() ? NULL : $format->id(),
        'editor' => 'ckeditor5',
      ]);
    }
    else {
      $submitted_editor = clone $form_state->get('editor');
    }

    $submitted_format = clone $form_state->getFormObject()->getEntity();

    // Note: \Drupal\filter\FilterFormatFormBase::validateForm() already ran,
    // so the form values are known to be valid.
    // @see \Drupal\filter\FilterFormatFormBase::submitForm()
    $values = $form_state->getFormObject()->getEntity()->isNew() || $switching_to_ck5
      ? $form_state->getUserInput()
      : $form_state->getValues();
    foreach ($values as $key => $value) {
      if ($key !== 'filters') {
        $submitted_format->set($key, $value);
      }
      else {
        foreach ($value as $instance_id => $config) {
          $submitted_format->setFilterConfig($instance_id, $config);
        }
      }
    }

    // @see \editor_form_filter_admin_format_submit()
    if ($settings = $form_state->getValue(['editor', 'settings'])) {
      // If the editor is new and no button config changes have been made in the
      // UI, skip updating $settings['toolbar']['items'] so that setting can use
      // the value returned by \CKEditor5::getDefaultSettings().
      if (isset($settings['toolbar']['items']) && !is_null($settings['toolbar']['items'])) {
        // Decode form value JSON blob to save as array.
        $settings['toolbar']['items'] = Json::decode($settings['toolbar']['items']);
        $submitted_editor->setSettings($settings);
      }
    }

    // Overwrite the Editor config entity object's $filterFormat property, to
    // prevent calls to Editor::hasAssociatedFilterFormat() and
    // Editor::getFilterFormat() from loading the FilterFormat from storage.
    // @todo Refactor the upstream implementations to remove the need for this.
    $reflector = new \ReflectionObject($submitted_editor);
    $property = $reflector->getProperty('filterFormat');
    $property->setAccessible(TRUE);
    $property->setValue($submitted_editor, $submitted_format);

    return $submitted_editor;
  }

  /**
   * Checks if the form is currently switching to CKEditor 5.
   *
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state of the filter format form.
   *
   * @return bool
   *   True if the form is currently switching to CKEditor 5, otherwise false.
   */
  public static function isSwitchingToCkeditor5(FormStateInterface $form_state) {
    $user_input = $form_state->getUserInput();
    return $form_state->get('ckeditor5_configured_editor') !== 'ckeditor5' && (!empty($user_input['editor']['editor']) && $user_input['editor']['editor'] === 'ckeditor5') && $form_state->getTriggeringElement()['#name'] === 'editor_configure';
  }

  /**
   * Returns the value required by the 'Allowed HTML tags' field.
   *
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The filter form state.
   *
   * @return string
   *   The string listing allowed elements.
   */
  public function getRequiredElements(FormStateInterface $form_state) {
    $submitted_editor = static::getSubmittedEditorAndFilterFormat($form_state);
    $enabled_plugins = array_keys($this->pluginManager->getEnabledDefinitions($submitted_editor));
    $provided = $this->pluginManager->getProvidedElements($enabled_plugins);
    return $this->pluginManager->getReadableElements($provided);
  }

  /**
   * Validate the conditions of each plugin.
   *
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   Editor settings form state.
   */
  public function validateConditions(FormStateInterface $form_state) {
    $submitted_editor = static::getSubmittedEditorAndFilterFormat($form_state);
    $plugins = $this->pluginManager->getEnabledDefinitions($submitted_editor);
    $parents_base = ['editor', 'settings'];
    foreach ($plugins as $definition) {
      $conditions = isset($definition['conditions']) ? $definition['conditions'] : [];

      foreach ($conditions as $condition_type => $required_value) {
        switch ($condition_type) {
          case 'toolbarItem':
            if (!in_array($required_value, $submitted_editor->getSettings()['toolbar']['items'])) {
              $parents = array_merge($parents_base, ['toolbar', 'items']);
              $form_state->setErrorByName(implode('][', $parents), $this->t('The %plugin-id plugin requires the %plugin-button toolbar button.', [
                '%plugin-id' => $definition['id'],
                '%plugin-button' => $required_value,
              ]));
            }
            break;

          case 'imageUploadStatus':
            if ((bool) $submitted_editor->getImageUploadSettings()['status'] !== TRUE) {
              $parents = array_merge($parents_base, [
                'plugins',
                'ckeditor5.imageUpload',
                'image_upload',
                'status',
              ]);
              $form_state->setErrorByName(implode('][', $parents), $this->t('Image upload requires the %image-upload-button toolbar button.', [
                '%image-upload-label' => 'Image upload',
                '%image-upload-button' => 'uploadImage',
              ]));
            }
            break;

          case 'filter':
            $filters = $submitted_editor->getFilterFormat()->filters();
            if (!$filters->has($required_value) || !$filters->get($required_value)->status) {
              $parents = ['filters', $required_value, 'status'];
              // If a button is required, tailor the error message to that.
              if (in_array('toolbarItem', $conditions, TRUE)) {
                $form_state->setErrorByName(implode('][', $parents), $this->t('The %required-filter-label filter must be enabled to use the %plugin-button button.', [
                  '%required-filter-label' => $filters->get($required_value)->getLabel(),
                  '%plugin-button' => $conditions['toolbarItem'],
                ]));
              }
              // Otherwise, fall back to the CKEditor 5 plugin name.
              else {
                $form_state->setErrorByName(implode('][', $parents), $this->t('The %required-filter-label filter must be enabled to use the %plugin-id plugin.', [
                  '%required-filter-label' => $filters->get($required_value)->getLabel(),
                  '%plugin-id' => $definition['id'],
                ]));
              }
            }
            break;
        }
      }
    }
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc