public function CKEditor5::validateConfigurationForm in Drupal 10
File
- core/
modules/ ckeditor5/ src/ Plugin/ Editor/ CKEditor5.php, line 605
Class
- CKEditor5
- Defines a CKEditor 5-based text editor for Drupal.
Namespace
Drupal\ckeditor5\Plugin\EditorCode
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
$json = $form_state
->getValue([
'toolbar',
'items',
]);
$toolbar_items = Json::decode($json);
// This basic validation must live in the form logic because it can only
// occur in a form context.
if (!$toolbar_items) {
$form_state
->setErrorByName('toolbar][items', $this
->t('Invalid toolbar value.'));
return;
}
// Construct a Text Editor config entity with the submitted values for
// validation. Do this on a clone: do not manipulate form state.
$submitted_editor = clone $form_state
->get('editor');
$settings = $submitted_editor
->getSettings();
// Update settings first to match the submitted toolbar items. This is
// necessary for ::shouldHaveVisiblePluginSettingsForm() to work.
$settings['toolbar']['items'] = $toolbar_items;
$submitted_editor
->setSettings($settings);
$eventual_editor_and_format_for_plugin_settings_visibility = $this
->getEventualEditorWithPrimedFilterFormat($form_state, $submitted_editor);
$settings['plugins'] = [];
$default_configurations = [];
foreach ($this->ckeditor5PluginManager
->getDefinitions() as $plugin_id => $definition) {
if (!$definition
->isConfigurable()) {
continue;
}
// Create a fresh instance of this CKEditor 5 plugin, not tied to a text
// editor configuration entity.
$plugin = $this->ckeditor5PluginManager
->getPlugin($plugin_id, NULL);
// If this plugin is configurable but it has empty default configuration,
// that means the configuration must be stored out of band.
// @see \Drupal\ckeditor5\Plugin\CKEditor5Plugin\ImageUpload
// @see editor_image_upload_settings_form()
$default_configuration = $plugin
->defaultConfiguration();
$configuration_stored_out_of_band = empty($default_configuration);
// If this plugin is configurable but has not yet had user interaction,
// the default configuration will still be active and may trigger
// validation errors. Do not trigger those validation errors until the
// form is actually saved, to allow the user to first configure other
// CKEditor 5 functionality.
$default_configurations[$plugin_id] = $default_configuration;
if ($form_state
->hasValue([
'plugins',
$plugin_id,
])) {
$subform = $form['plugins'][$plugin_id];
$subform_state = SubformState::createForSubform($subform, $form, $form_state);
$plugin
->validateConfigurationForm($subform, $subform_state);
$plugin
->submitConfigurationForm($subform, $subform_state);
// If the configuration is stored out of band, ::submitConfigurationForm
// will already have stored it. If it is not stored out of band,
// populate $settings, to populate $submitted_editor.
if (!$configuration_stored_out_of_band) {
$settings['plugins'][$plugin_id] = $plugin
->getConfiguration();
}
}
elseif ($this
->shouldHaveVisiblePluginSettingsForm($definition, $eventual_editor_and_format_for_plugin_settings_visibility)) {
if (!$configuration_stored_out_of_band) {
$settings['plugins'][$plugin_id] = $default_configuration;
}
}
}
// All plugin settings have been collected, including defaults that depend
// on visibility. Store the collected settings, throw away the interim state
// that allowed determining which defaults to add.
unset($eventual_editor_and_format_for_plugin_settings_visibility);
$submitted_editor
->setSettings($settings);
// Validate the text editor + text format pair.
// Note that the eventual pair is computed and validated, not the received
// pair: if the filter_html filter is in use, the CKEditor 5 configuration
// dictates the filter_html's filter plugin's "allowed_html" setting.
// @see ckeditor5_form_filter_format_form_alter()
// @see ::getGeneratedAllowedHtmlValue()
$eventual_editor_and_format = $this
->getEventualEditorWithPrimedFilterFormat($form_state, $submitted_editor);
$violations = CKEditor5::validatePair($eventual_editor_and_format, $eventual_editor_and_format
->getFilterFormat());
foreach ($violations as $violation) {
$property_path_parts = explode('.', $violation
->getPropertyPath());
// Special case: AJAX updates that do not submit the form (that cannot
// result in configuration being saved).
if ($form_state
->getSubmitHandlers() === [
'editor_form_filter_admin_format_editor_configure',
]) {
// Ensure that plugins' validation constraints do not immediately
// trigger a validation error: the user may choose to configure other
// CKEditor 5 aspects first.
if ($property_path_parts[0] === 'settings' && $property_path_parts[1] === 'plugins') {
$plugin_id = $property_path_parts[2];
// This CKEditor 5 plugin settings form was just added: the user has
// not yet had a chance to configure it.
if (!$form_state
->hasValue([
'plugins',
$plugin_id,
])) {
continue;
}
// This CKEditor 5 plugin settings form was added recently, the user
// is triggering AJAX rebuilds of the configuration UI because they're
// configuring other functionality first. Only require these to be
// valid at form submission time.
if ($form_state
->getValue([
'plugins',
$plugin_id,
]) === $default_configurations[$plugin_id]) {
continue;
}
}
}
$form_item_name = static::mapPairViolationPropertyPathsToFormNames($violation
->getPropertyPath(), $form);
// When adding a toolbar item, it is possible that not all conditions for
// using it have been met yet. FormBuilder refuses to rebuild forms when a
// validation error is present. But to meet the condition for the toolbar
// item, configuration must be set in a vertical tab that must still
// appear. Work-around: reduce the validation error to a warning message.
// @see \Drupal\ckeditor5\Plugin\Validation\Constraint\ToolbarItemConditionsMetConstraintValidator
if ($form_state
->isRedirectDisabled() && $form_item_name === 'editor][settings][toolbar][items') {
$this
->messenger()
->addWarning($violation
->getMessage());
continue;
}
$form_state
->getCompleteFormState()
->setErrorByName($form_item_name, $violation
->getMessage());
}
// Pass it on to ::submitConfigurationForm().
$form_state
->get('editor')
->setSettings($settings);
// 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);
assert(TRUE === $this
->checkConfigSchema(\Drupal::getContainer()
->get('config.typed'), 'editor.editor.id_does_not_matter', $submitted_editor
->toArray()), 'Schema errors: ' . print_r($this
->checkConfigSchema(\Drupal::getContainer()
->get('config.typed'), 'editor.editor.id_does_not_matter', $submitted_editor
->toArray()), TRUE));
}