Skip to content
Snippets Groups Projects
Commit fa0d6320 authored by Jürgen Haas's avatar Jürgen Haas
Browse files

Issue #3306136 by jurgenhaas, mxh: Required fields are not validated

parent 6eaacce1
No related branches found
No related tags found
1 merge request!224Issue #3306136: Required fields are not validated
......@@ -17,6 +17,7 @@ use Drupal\eca\Entity\Objects\EcaAction;
use Drupal\eca\Entity\Objects\EcaEvent;
use Drupal\eca\Entity\Objects\EcaGateway;
use Drupal\eca\Entity\Objects\EcaObject;
use Drupal\eca\Form\RuntimePluginForm;
use Drupal\eca\Plugin\ECA\Modeller\ModellerInterface;
use Drupal\eca\Plugin\PluginUsageInterface;
......@@ -452,28 +453,62 @@ class Eca extends ConfigEntityBase implements EntityWithPluginCollectionInterfac
}
}
}
// Build form.
// Simulate filling and submitting a form for configuring the plugin.
$form_state = new FormState();
$form = $plugin->buildConfigurationForm([], $form_state);
// Set form field values, simulating the user filling and submitting
// the form.
$form_state->setProgrammed();
$form_state->setSubmitted();
$form_state->setUserInput($fields);
$form_state->setValues($fields);
if (!in_array($plugin_id, self::$ignoreConfigValidationActions, TRUE)) {
// Validate the form.
$plugin->validateConfigurationForm($form, $form_state);
}
// Check for errors.
if ($errors = $form_state->getErrors()) {
foreach ($errors as $error) {
$errorMsg = sprintf('%s "%s" (%s): %s', $type, $plugin->getPluginDefinition()['label'], $label, $error);
$this->messenger()->addError($errorMsg);
// Build a runtime form for validating the plugin.
$form_object = new RuntimePluginForm($plugin);
// Keep the currently stored list of messages in mind.
// The form build will add messages to the messenger, which we want
// to clear from the runtime.
$messenger = $this->messenger();
$messages_by_type = $messenger->all();
// Keep the current "has any errors" flag in mind, and reset this flag
// for the scope of this operation.
$any_errors = FormState::hasAnyErrors();
$form_state->clearErrors();
// Building the form also submits the form, if no errors are there.
$form = $this->formBuilder()->buildForm($form_object, $form_state);
// Now re-add the previously fetched messages.
$messenger->deleteAll();
foreach ($messages_by_type as $type => $messages) {
foreach ($messages as $i => $message) {
$messenger->addMessage($message, $type);
}
}
return FALSE;
// Check for errors.
if ($errors = $form_state->getErrors()) {
foreach ($errors as $error) {
$errorMsg = sprintf('%s "%s" (%s): %s', $type, $plugin->getPluginDefinition()['label'], $label, $error);
$messenger->addError($errorMsg);
}
return FALSE;
}
if ($any_errors) {
// Make sure that the form state will have the any errors flag restored.
(new FormState())->setErrorByName('');
}
}
else {
// Build and execute submit handlers. This makes sure that submit handlers
// have properly set configuration values.
$form = $plugin->buildConfigurationForm([], $form_state);
$plugin->submitConfigurationForm($form, $form_state);
}
// Simulate submitting the form.
$plugin->submitConfigurationForm($form, $form_state);
// Collect the resulting form field values.
$fields = $plugin->getConfiguration() + $fields;
$fields = ($plugin instanceof ConfigurableInterface ? $plugin->getConfiguration() : []) + $fields;
return TRUE;
}
......
......@@ -5,6 +5,7 @@ namespace Drupal\eca\Entity;
use Drupal\Core\Action\ActionManager;
use Drupal\Core\Cache\MemoryCache\MemoryCache;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Logger\LoggerChannel;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\eca\PluginManager\Action;
......@@ -105,6 +106,13 @@ trait EcaTrait {
*/
protected ?MessengerInterface $messenger;
/**
* The form builder service.
*
* @var \Drupal\Core\Form\FormBuilderInterface|null
*/
protected ?FormBuilderInterface $formBuilder;
/**
* Initializes the modeller plugin manager.
*
......@@ -261,4 +269,17 @@ trait EcaTrait {
return $this->messenger;
}
/**
* Initializes the form builder service.
*
* @return \Drupal\Core\Form\FormBuilderInterface
* The form builder service.
*/
protected function formBuilder(): FormBuilderInterface {
if (!isset($this->formBuilder)) {
$this->formBuilder = \Drupal::formBuilder();
}
return $this->formBuilder;
}
}
<?php
namespace Drupal\eca\Form;
use Drupal\Core\Form\FormInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\PluginFormInterface;
/**
* Form class for validating a plugin.
*
* This class solely exists for ECA being able to validate a plugin on runtime,
* using validation mechanics of the Form API.
*
* @see \Drupal\eca\Entity\Eca::validatePlugin
*
* @internal
* This class is not meant to be used as a public API. It is subject for name
* change or may be removed completely, also on minor version updates.
*/
final class RuntimePluginForm implements FormInterface {
/**
* The plugin.
*
* @var \Drupal\Core\Plugin\PluginFormInterface
*/
protected PluginFormInterface $plugin;
/**
* {@inheritdoc}
*/
public function getFormId(): string {
return 'eca_runtime_plugin_form';
}
/**
* Constructs a new RuntimePluginForm object.
*/
public function __construct(PluginFormInterface $plugin) {
$this->plugin = $plugin;
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state): array {
return $this->plugin->buildConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state): void {
$this->plugin->validateConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state): void {
$this->plugin->submitConfigurationForm($form, $form_state);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment