Skip to content
Snippets Groups Projects
Verified Commit 9117ebf1 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3265626 by bnjmnm, Wim Leers, nod_, lauriii, alexpott, andregp: Changes...

Issue #3265626 by bnjmnm, Wim Leers, nod_, lauriii, alexpott, andregp: Changes to "Manually editable HTML tags" lost if form is submitted without triggering AJAX
parent 05d87619
No related branches found
No related tags found
37 merge requests!12227Issue #3181946 by jonmcl, mglaman,!7471uncessary 5 files are moved from media-library folder to misc folder,!7452Issue #1797438. HTML5 validation is preventing form submit and not fully...,!54479.5.x SF update,!5014Issue #3071143: Table Render Array Example Is Incorrect,!4868Issue #1428520: Improve menu parent link selection,!4289Issue #1344552 by marcingy, Niklas Fiekas, Ravi.J, aleevas, Eduardo Morales...,!4114Issue #2707291: Disable body-level scrolling when a dialog is open as a modal,!3630Issue #2815301 by Chi, DanielVeza, kostyashupenko, smustgrave: Allow to create...,!3291Issue #3336463: Rewrite rules for gzipped CSS and JavaScript aggregates never match,!3143Issue #3313342: [PHP 8.1] Deprecated function: strpos(): Passing null to parameter #1 LayoutBuilderUiCacheContext.php on line 28,!3102Issue #3164428 by DonAtt, longwave, sahil.goyal, Anchal_gupta, alexpott: Use...,!2853#3274419 Makes BaseFieldOverride inherit the internal property from the base field.,!2719Issue #3110137: Remove Classy from core.,!2437Issue #3238257 by hooroomoo, Wim Leers: Fragment link pointing to <textarea>...,!2378Issue #2875033: Optimize joins and table selection in SQL entity query implementation,!2074Issue #2707689: NodeForm::actions() checks for delete access on new entities,!2062Issue #3246454: Add weekly granularity to views date sort,!1591Issue #3199697: Add JSON:API Translation experimental module,!1484Exposed filters get values from URL when Ajax is on,!1255Issue #3238922: Refactor (if feasible) uses of the jQuery serialize function to use vanillaJS,!1254Issue #3238915: Refactor (if feasible) uses of the jQuery ready function to use VanillaJS,!1162Issue #3100350: Unable to save '/' root path alias,!1073issue #3191727: Focus states on mobile second level navigation items fixed,!10223132456: Fix issue where views instances are emptied before an ajax request is complete,!957Added throwing of InvalidPluginDefinitionException from getDefinition().,!925Issue #2339235: Remove taxonomy hard dependency on node module,!877Issue #2708101: Default value for link text is not saved,!873Issue #2875228: Site install not using batch API service,!872Draft: Issue #3221319: Race condition when creating menu links and editing content deletes menu links,!844Resolve #3036010 "Updaters",!712Issue #2909128: Autocomplete intermittent on Chrome Android,!579Issue #2230909: Simple decimals fail to pass validation,!560Move callback classRemove outside of the loop,!555Issue #3202493,!485Sets the autocomplete attribute for username/password input field on login form.,!30Issue #3182188: Updates composer usage to point at ./vendor/bin/composer
......@@ -7,6 +7,7 @@
declare(strict_types = 1);
use Drupal\ckeditor5\HTMLRestrictions;
use Drupal\ckeditor5\Plugin\Editor\CKEditor5;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Ajax\AjaxResponse;
......@@ -245,6 +246,28 @@ function _add_ajax_listeners_to_plugin_inputs(array &$plugins_config_form): void
$form['#after_build'][] = [CKEditor5::class, 'assessActiveTextEditorAfterBuild'];
$form['#validate'][] = [CKEditor5::class, 'validateSwitchingToCKEditor5'];
array_unshift($form['actions']['submit']['#submit'], 'ckeditor5_filter_format_edit_form_submit');
}
/**
* Form submission handler for filter format forms.
*/
function ckeditor5_filter_format_edit_form_submit(array $form, FormStateInterface $form_state) {
$limit_allowed_html_tags = isset($form['filters']['settings']['filter_html']['allowed_html']);
$manually_editable_tags = $form_state->getValue(['editor', 'settings', 'plugins', 'ckeditor5_sourceEditing', 'allowed_tags']);
if ($limit_allowed_html_tags && is_array($manually_editable_tags)) {
// When "Manually editable tags" and "limit allowed HTML tags" are both
// configured, the former informs the value of the latter. This dependent
// value is typically updated via AJAX, but it's possible for "Manually
// editable tags" to update without triggering the AJAX rebuild. That value
// is recalculated here on save to ensure it happens even if the AJAX
// rebuild doesn't happen.
$manually_editable_tags_restrictions = HTMLRestrictions::fromString(implode($manually_editable_tags));
$format = $form_state->get('ckeditor5_validated_pair')->getFilterFormat();
$allowed_html = HTMLRestrictions::fromTextFormat($format);
$combined_tags_string = $manually_editable_tags_restrictions->merge($allowed_html)->toFilterHtmlAllowedTagsString();
$form_state->setValue(['filters', 'filter_html', 'settings', 'allowed_html'], $combined_tags_string);
}
}
/**
......
......@@ -6,6 +6,26 @@
((Drupal, once) => {
Drupal.behaviors.allowedTagsListener = {
attach: function attach(context) {
once(
'ajax-conflict-prevention',
'[data-drupal-selector="filter-format-edit-form"], [data-drupal-selector="filter-format-add-form"]',
context,
).forEach((form) => {
// When the form is submitted, remove the disabled attribute from all
// AJAX enabled form elements. The disabled state is added as part of
// AJAX processing, but will prevent the value from being added to
// $form_state.
form.addEventListener('submit', () => {
once
.filter(
'drupal-ajax',
'[data-drupal-selector="filter-format-edit-form"] [disabled], [data-drupal-selector="filter-format-add-form"] [disabled]',
)
.forEach((disabledElement) => {
disabledElement.removeAttribute('disabled');
});
});
});
once(
'allowed-tags-listener',
context.querySelector(
......
......@@ -8,6 +8,13 @@
((Drupal, once) => {
Drupal.behaviors.allowedTagsListener = {
attach: function attach(context) {
once('ajax-conflict-prevention', '[data-drupal-selector="filter-format-edit-form"], [data-drupal-selector="filter-format-add-form"]', context).forEach(form => {
form.addEventListener('submit', () => {
once.filter('drupal-ajax', '[data-drupal-selector="filter-format-edit-form"] [disabled], [data-drupal-selector="filter-format-add-form"] [disabled]').forEach(disabledElement => {
disabledElement.removeAttribute('disabled');
});
});
});
once('allowed-tags-listener', context.querySelector('[data-drupal-selector="edit-filters-filter-html-settings-allowed-html"]')).forEach(textarea => {
const editorSelect = document.querySelector('[data-drupal-selector="edit-editor-editor"]');
const filterCheckbox = document.querySelector('[data-drupal-selector="edit-filters-filter-html-status"]');
......
......@@ -9,7 +9,7 @@
use Drupal\ckeditor5\Plugin\Editor\CKEditor5;
use Symfony\Component\Validator\ConstraintViolation;
// cspell:ignore gramma
// cspell:ignore gramma sourceediting
/**
* @coversDefaultClass \Drupal\ckeditor5\Plugin\CKEditor5Plugin\SourceEditing
......@@ -117,6 +117,52 @@ function (ConstraintViolation $v) {
$this->drupalLogin($this->adminUser);
}
/**
* @covers \Drupal\ckeditor5\Plugin\CKEditor5Plugin\SourceEditing::buildConfigurationForm
*/
public function testSourceEditingSettingsForm() {
$this->drupalLogin($this->drupalCreateUser(['administer filters']));
$page = $this->getSession()->getPage();
$assert_session = $this->assertSession();
$this->createNewTextFormat($page, $assert_session);
$assert_session->assertWaitOnAjaxRequest();
// The Source Editing plugin settings form should not be present.
$assert_session->elementNotExists('css', '[data-drupal-selector="edit-editor-settings-plugins-ckeditor5-sourceediting"]');
$this->assertNotEmpty($assert_session->waitForElement('css', '.ckeditor5-toolbar-item-sourceEditing'));
$this->triggerKeyUp('.ckeditor5-toolbar-item-sourceEditing', 'ArrowDown');
$assert_session->assertWaitOnAjaxRequest();
// The Source Editing plugin settings form should now be present and should
// have no allowed tags configured.
$page->clickLink('Source editing');
$this->assertNotNull($assert_session->waitForElementVisible('css', '[data-drupal-selector="edit-editor-settings-plugins-ckeditor5-sourceediting-allowed-tags"]'));
$javascript = <<<JS
const allowedTags = document.querySelector('[data-drupal-selector="edit-editor-settings-plugins-ckeditor5-sourceediting-allowed-tags"]');
allowedTags.value = '<div data-foo>';
allowedTags.dispatchEvent(new Event('input'));
JS;
$this->getSession()->executeScript($javascript);
// Immediately save the configuration. Intentionally do nothing that would
// trigger an AJAX rebuild.
$page->pressButton('Save configuration');
// Verify that the configuration was saved.
$this->drupalGet('admin/config/content/formats/manage/ckeditor5');
$page->clickLink('Source editing');
$this->assertNotNull($ghs_textarea = $assert_session->waitForElementVisible('css', '[data-drupal-selector="edit-editor-settings-plugins-ckeditor5-sourceediting-allowed-tags"]'));
$ghs_string = '<div data-foo>';
$this->assertSame($ghs_string, $ghs_textarea->getValue());
$allowed_html_field = $assert_session->fieldExists('filters[filter_html][settings][allowed_html]');
$this->assertStringContainsString($ghs_string, $allowed_html_field->getValue(), "$ghs_string not found in the allowed tags value of: {$allowed_html_field->getValue()}");
}
/**
* Tests allowing extra attributes on already supported tags using GHS.
*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment