Verified Commit 2a333220 authored by Dave Long's avatar Dave Long
Browse files

fix: #3274635 [upstream] Use CKEditor 5's native <ol type> and <ul type> UX

By: metasim
By: s_leu
By: osman
By: bnjmnm
By: jweowu
By: mstrelan
By: acbramley
By: gwvoigt
By: ericgsmith
By: taran2l
By: chrisla
By: loopy1492
By: isampo
By: wim leers
By: joaopauloc.dev
By: longwave
By: catch
By: phenaproxima
By: xjm
By: godotislate
(cherry picked from commit 70a49ee7)
parent 7a7152db
Loading
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -24,9 +24,16 @@ function ckeditor5_removed_post_updates(): array {
}

/**
 * Updates Text Editors using CKEditor 5 to native List "type" functionality.
 * No-op update that didn't update quite enough the first time.
 */
function ckeditor5_post_update_list_type(array &$sandbox = []): void {
  // This update is intentionally left blank.
}

/**
 * Updates Text Editors using CKEditor 5 to native List "type" functionality.
 */
function ckeditor5_post_update_list_type_again(array &$sandbox = []): void {
  $config_entity_updater = \Drupal::classResolver(ConfigEntityUpdater::class);
  $config_entity_updater->update($sandbox, 'editor', function (Editor $editor): bool {
    // Only try to update editors using CKEditor 5.
@@ -36,7 +43,6 @@ function ckeditor5_post_update_list_type(array &$sandbox = []): void {
    $settings = $editor->getSettings();

    // @see Ckeditor5Hooks::editorPresave()
    return array_key_exists('ckeditor5_list', $settings['plugins'])
      && array_key_exists('ckeditor5_sourceEditing', $settings['plugins']);
    return array_key_exists('ckeditor5_list', $settings['plugins']);
  });
}
+3 −0
Original line number Diff line number Diff line
@@ -435,6 +435,9 @@ public function editorPresave(EditorInterface $editor): void {
          ->diff($ul_type)
          ->toCKEditor5ElementsArray();
      }
      elseif (array_key_exists('ckeditor5_list', $settings['plugins']) && !array_key_exists('styles', $settings['plugins']['ckeditor5_list']['properties'])) {
        $settings['plugins']['ckeditor5_list']['properties']['styles'] = FALSE;
      }

      $editor->setSettings($settings);
    }
+28 −0
Original line number Diff line number Diff line
<?php

/**
 * @file
 * Removes the source editing plugin from the full_html editor.
 */

use Drupal\Core\Database\Database;

$connection = Database::getConnection();

$data = $connection->select('config')
  ->condition('name', 'editor.editor.full_html')
  ->fields('config', ['data'])
  ->execute()
  ->fetchField();
$data = unserialize($data);
// Remove the source editing plugin from the full_html editor to test that the
// 'styles' property still gets added to the list plugin.
// The basic_html editor stays unchanged to test that the 'styles' property gets
// added to the list plugin if editor has the source editing plugin.
unset($data['settings']['plugins']['ckeditor5_sourceEditing']);
$connection->update('config')
  ->condition('name', 'editor.editor.full_html')
  ->fields([
    'data' => serialize($data),
  ])
  ->execute();
+64 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Drupal\Tests\ckeditor5\Functional\Update;

use Drupal\editor\Entity\Editor;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;

/**
 * Tests creating base field overrides for the promote field on node types.
 */
#[Group('Update')]
#[RunTestsInSeparateProcesses]
class AddListPluginStylesTest extends UpdatePathTestBase {

  /**
   * {@inheritdoc}
   */
  protected function setDatabaseDumpFiles(): void {
    $this->databaseDumpFiles = [
      __DIR__ . '/../../../../../system/tests/fixtures/update/drupal-10.3.0.bare.standard.php.gz',
      __DIR__ . '/../../../fixtures/update/remove-source-editing-from-full-html-editor.php',
    ];
  }

  /**
   * Tests update path that adds 'styles' property to editors with list plugin.
   */
  public function testRunUpdates(): void {
    // Basic HTML editor has list plugin and source editing plugin.
    $basic = Editor::load('basic_html');
    $basic_data = $basic->toArray();
    $this->assertArrayHasKey('ckeditor5_list', $basic_data['settings']['plugins']);
    $this->assertArrayHasKey('ckeditor5_sourceEditing', $basic_data['settings']['plugins']);
    $this->assertArrayNotHasKey('styles', $basic_data['settings']['plugins']['ckeditor5_list']['properties']);

    // Full HTML editor has list plugin, but does not have source editing
    // plugin.
    $full = Editor::load('full_html');
    $full_data = $full->toArray();
    $this->assertArrayHasKey('ckeditor5_list', $full_data['settings']['plugins']);
    $this->assertArrayNotHasKey('ckeditor5_sourceEditing', $full_data['settings']['plugins']);
    $this->assertArrayNotHasKey('styles', $full_data['settings']['plugins']['ckeditor5_list']['properties']);

    // After updates, both Basic and Full HTML editors have the 'styles'
    // property set for the list plugin.
    $this->runUpdates();
    $basic = Editor::load('basic_html');
    $basic_data = $basic->toArray();
    $this->assertArrayHasKey('ckeditor5_list', $basic_data['settings']['plugins']);
    $this->assertTrue($basic_data['settings']['plugins']['ckeditor5_list']['properties']['styles']);
    $this->assertArrayHasKey('ckeditor5_sourceEditing', $basic_data['settings']['plugins']);

    $full = Editor::load('full_html');
    $full_data = $full->toArray();
    $this->assertArrayHasKey('ckeditor5_list', $full_data['settings']['plugins']);
    $this->assertFalse($full_data['settings']['plugins']['ckeditor5_list']['properties']['styles']);
    $this->assertArrayNotHasKey('ckeditor5_sourceEditing', $full_data['settings']['plugins']);
  }

}
+29 −6
Original line number Diff line number Diff line
@@ -568,7 +568,7 @@ public function testListPlugin(): void {
      ],
      'settings' => [
        'toolbar' => [
          'items' => ['sourceEditing', 'numberedList', 'bulletedList'],
          'items' => ['numberedList', 'bulletedList'],
        ],
        'plugins' => [
          'ckeditor5_list' => [
@@ -579,12 +579,37 @@ public function testListPlugin(): void {
            ],
            'multiBlock' => TRUE,
          ],
          'ckeditor5_sourceEditing' => [
            'allowed_tags' => [],
          ],
        ],
      ],
    ])->save();

    // Test that checking the list styles checkbox saves correctly.
    $page = $this->getSession()->getPage();
    $assert_session = $this->assertSession();
    $this->drupalGet('admin/config/content/formats/manage/test_format');
    $this->assertSame(['List'], $this->getVerticalTabs('#plugin-settings-wrapper', FALSE));
    $this->clickLink('List');
    $this->assertNotNull($assert_session->waitForElementVisible('css', '[data-drupal-selector="edit-editor-settings-plugins-ckeditor5-list-styles"]'));
    $this->assertTrue($page->hasUncheckedField('editor[settings][plugins][ckeditor5_list][styles]'));
    $page->checkField('editor[settings][plugins][ckeditor5_list][styles]');
    $page->pressButton('Save');

    /** @var \Drupal\editor\EditorInterface $editor */
    $editor = Editor::load('test_format');
    $settings = $editor->getSettings();
    $this->assertTrue($settings['plugins']['ckeditor5_list']['properties']['styles']);
    $this->drupalGet('admin/config/content/formats/manage/test_format');
    $this->assertSame(['List'], $this->getVerticalTabs('#plugin-settings-wrapper', FALSE));
    $this->clickLink('List');
    $this->assertNotNull($assert_session->waitForElementVisible('css', '[data-drupal-selector="edit-editor-settings-plugins-ckeditor5-list-styles"]'));
    $this->assertTrue($page->hasCheckedField('editor[settings][plugins][ckeditor5_list][styles]'));

    // Add source editing plugin.
    $settings['toolbar']['items'] = ['sourceEditing', 'numberedList', 'bulletedList'];
    $settings['plugins']['ckeditor5_list']['properties']['styles'] = FALSE;
    $settings['plugins']['ckeditor5_sourceEditing']['allowed_tags'] = [];
    $editor->setSettings($settings)->save();

    $this->assertSame([], array_map(
      function (ConstraintViolationInterface $v) {
        return (string) $v->getMessage();
@@ -595,8 +620,6 @@ function (ConstraintViolationInterface $v) {
      ))
    ));
    $ordered_list_html = '<ol><li>apple</li><li>banana</li><li>cantaloupe</li></ol>';
    $page = $this->getSession()->getPage();
    $assert_session = $this->assertSession();
    $this->drupalGet('node/add/page');
    $page->fillField('title[0][value]', 'My test content');
    $this->pressEditorButton('Source');