Loading modules/form/src/Plugin/Action/FormAddFieldActionBase.php +12 −2 Original line number Diff line number Diff line Loading @@ -67,8 +67,8 @@ abstract class FormAddFieldActionBase extends FormActionBase { if ($this->configuration['description'] !== '') { $field_element['#description'] = $this->tokenServices->replaceClear($this->configuration['description']); } if ($this->configuration['default_value'] !== '') { $field_element['#default_value'] = $this->tokenServices->replaceClear($this->configuration['default_value']); if (trim((string) $this->configuration['default_value']) !== '') { $field_element['#default_value'] = $this->buildDefaultValue(); } return $field_element; } Loading Loading @@ -171,4 +171,14 @@ abstract class FormAddFieldActionBase extends FormActionBase { $this->configuration['default_value'] = $form_state->getValue('default_value'); } /** * Builds up the default value for the form element. * * @return mixed * The default value. */ protected function buildDefaultValue() { return $this->tokenServices->replaceClear($this->configuration['default_value']); } } modules/form/src/Plugin/Action/FormAddOptionsfield.php +12 −4 Original line number Diff line number Diff line Loading @@ -31,7 +31,7 @@ class FormAddOptionsfield extends FormAddFieldActionBase { $element = parent::buildFieldElement(); // Options will be filled up within ::execute(). $element['#options'] = []; $is_multiple = $this->configuration['multiple']; $is_multiple = (bool) $this->configuration['multiple']; $element['#multiple'] = $is_multiple; if (!$is_multiple && $element['#type'] === 'checkboxes') { $element['#type'] = 'radios'; Loading @@ -39,9 +39,6 @@ class FormAddOptionsfield extends FormAddFieldActionBase { elseif ($is_multiple && $element['#type'] === 'radios') { $element['#type'] = 'checkboxes'; } if ($is_multiple && isset($element['#default_value']) && !is_iterable($element['#default_value'])) { $element['#default_value'] = DataTransferObject::buildArrayFromUserInput((string) $element['#default_value']); } return $element; } Loading Loading @@ -110,4 +107,15 @@ class FormAddOptionsfield extends FormAddFieldActionBase { return $dependencies; } /** * {@inheritdoc} */ protected function buildDefaultValue() { if ($default_options = $this->buildOptionsArray($this->configuration['default_value'])) { $is_multiple = (bool) $this->configuration['multiple']; return $is_multiple ? array_keys($default_options) : key($default_options); } return parent::buildDefaultValue(); } } modules/form/src/Plugin/Action/FormFieldSetOptionsTrait.php +43 −32 Original line number Diff line number Diff line Loading @@ -58,38 +58,7 @@ trait FormFieldSetOptionsTrait { } } else { $token = $this->tokenServices; $options = (mb_substr($options, 0, 1) === '[') && (mb_substr($options, -1, 1) === ']') && (mb_strlen($options) <= 255) && $token->hasTokenData($options) ? $token->getTokenData($options) : (string) $token->replaceClear($options); $options_array = []; if (is_string($options)) { $options_array = DataTransferObject::buildArrayFromUserInput($options); } elseif (is_iterable($options)) { foreach ($options as $key => $value) { if ($value instanceof EntityAdapter) { $value = $value->getValue(); } if ($value instanceof EntityInterface) { if (!$value->isNew()) { $key = $value->id(); } elseif ($value->uuid()) { $key = $value->uuid(); } $value = (string) $value->label(); } elseif ($value instanceof TypedDataInterface) { $value = $value->getString(); } elseif (is_object($value) && method_exists($value, '__toString')) { $value = (string) $value; } if (is_scalar($value) && trim((string) $value) !== '') { $options_array[$key] = trim((string) $value); } } } $options = $options_array; $options = $this->buildOptionsArray($options); } $element['#options'] = $options; Loading Loading @@ -146,4 +115,46 @@ trait FormFieldSetOptionsTrait { $this->yamlParser = $yaml_parser; } /** * Builds up an array of options, directly usable in a form element. * * @param string $input * The unprocessed configuration input, which may hold a token or a fixed * value, or any other sort of values. */ protected function buildOptionsArray(string $input): array { $token = $this->tokenServices; $options = (mb_substr($input, 0, 1) === '[') && (mb_substr($input, -1, 1) === ']') && (mb_strlen($input) <= 255) && $token->hasTokenData($input) ? $token->getTokenData($input) : (string) $token->replaceClear($input); $options_array = []; if (is_string($options)) { $options_array = DataTransferObject::buildArrayFromUserInput($options); } elseif (is_iterable($options)) { foreach ($options as $key => $value) { if ($value instanceof EntityAdapter) { $value = $value->getValue(); } if ($value instanceof EntityInterface) { if (!$value->isNew()) { $key = $value->id(); } elseif ($value->uuid()) { $key = $value->uuid(); } $value = (string) $value->label(); } elseif ($value instanceof TypedDataInterface) { $value = $value->getString(); } elseif (is_object($value) && method_exists($value, '__toString')) { $value = (string) $value; } if (is_scalar($value) && trim((string) $value) !== '') { $options_array[$key] = trim((string) $value); } } } return $options_array; } } modules/form/tests/src/Kernel/FormActionsTest.php +120 −1 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ class FormActionsTest extends KernelTestBase { $this->installConfig(static::$modules); User::create(['uid' => 0, 'name' => 'guest'])->save(); User::create(['uid' => 1, 'name' => 'admin'])->save(); User::create(['uid' => 2, 'name' => 'auth'])->save(); // Create the Article content type with a standard body field. /** @var \Drupal\node\NodeTypeInterface $node_type */ Loading Loading @@ -349,7 +350,125 @@ class FormActionsTest extends KernelTestBase { } /** * Tests the action plugin "eca_form_add_optionsfield". * Tests the action plugin "eca_form_add_optionsfield" using checkboxes. */ public function testFormAddCheckboxes(): void { $users = [User::load(0), User::load(1), User::load(2)]; $this->tokenServices->addTokenData('users', $users); /** @var \Drupal\eca_form\Plugin\Action\FormAddOptionsfield $action */ $action = $this->actionManager->createInstance('eca_form_add_optionsfield', [ 'name' => 'mycheckboxes', 'type' => 'checkboxes', 'multiple' => TRUE, 'options' => '[users]', 'default_value' => '1', 'use_yaml' => FALSE, ]); /** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher */ $event_dispatcher = \Drupal::service('event_dispatcher'); $form_builder = \Drupal::formBuilder(); $access_result = NULL; $form = NULL; $event_dispatcher->addListener(FormEvents::PROCESS, function (FormProcess $event) use (&$access_result, &$form, $action) { $action->setEvent($event); $access_result = $access_result ?? $action->access(NULL); if ($action->access(NULL)) { $action->execute(); } $form = $event->getForm(); }); $form_object = \Drupal::entityTypeManager()->getFormObject('node', 'default'); $form_object->setEntity(Node::create([ 'type' => 'article', 'title' => $this->randomMachineName(), ])); $form_state = new FormState(); $build = $form_builder->buildForm($form_object, $form_state); $this->assertTrue($access_result); $this->assertTrue(isset($form['mycheckboxes'])); $this->assertEquals('checkboxes', $form['mycheckboxes']['#type']); $this->assertSame([ '0' => User::load(0)->label(), '1' => User::load(1)->label(), '2' => User::load(2)->label(), ], $form['mycheckboxes']['#options']); /** @var \Drupal\Core\Render\RendererInterface $renderer */ $renderer = \Drupal::service('renderer'); $rendered = $renderer->renderPlain($build); $this->assertStringContainsString('name="mycheckboxes[0]" value="0"', $rendered); $this->assertStringNotContainsString('name="mycheckboxes[0]" value="0" checked="checked"', $rendered); $this->assertStringContainsString('name="mycheckboxes[1]" value="1" checked="checked"', $rendered); $this->assertStringContainsString('name="mycheckboxes[2]" value="2"', $rendered); $this->assertStringNotContainsString('name="mycheckboxes[2]" value="2" checked="checked"', $rendered); } /** * Tests the action plugin "eca_form_add_optionsfield" using checkboxes. * * Default values for the checkboxes are entities. */ public function testFormAddCheckboxesDefaultValueEntities(): void { $users = [User::load(0), User::load(1), User::load(2)]; $this->tokenServices->addTokenData('users', $users); /** @var \Drupal\eca_form\Plugin\Action\FormAddOptionsfield $action */ $action = $this->actionManager->createInstance('eca_form_add_optionsfield', [ 'name' => 'mycheckboxes', 'type' => 'checkboxes', 'multiple' => TRUE, 'options' => '[users]', 'default_value' => '[users]', 'use_yaml' => FALSE, ]); /** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher */ $event_dispatcher = \Drupal::service('event_dispatcher'); $form_builder = \Drupal::formBuilder(); $access_result = NULL; $form = NULL; $event_dispatcher->addListener(FormEvents::PROCESS, function (FormProcess $event) use (&$access_result, &$form, $action) { $action->setEvent($event); $access_result = $access_result ?? $action->access(NULL); if ($action->access(NULL)) { $action->execute(); } $form = $event->getForm(); }); $form_object = \Drupal::entityTypeManager()->getFormObject('node', 'default'); $form_object->setEntity(Node::create([ 'type' => 'article', 'title' => $this->randomMachineName(), ])); $form_state = new FormState(); $build = $form_builder->buildForm($form_object, $form_state); $this->assertTrue($access_result); $this->assertTrue(isset($form['mycheckboxes'])); $this->assertEquals('checkboxes', $form['mycheckboxes']['#type']); $this->assertSame([ '0' => User::load(0)->label(), '1' => User::load(1)->label(), '2' => User::load(2)->label(), ], $form['mycheckboxes']['#options']); /** @var \Drupal\Core\Render\RendererInterface $renderer */ $renderer = \Drupal::service('renderer'); $rendered = $renderer->renderPlain($build); $this->assertStringContainsString('name="mycheckboxes[0]" value="0" checked="checked"', $rendered); $this->assertStringContainsString('name="mycheckboxes[1]" value="1" checked="checked"', $rendered); $this->assertStringContainsString('name="mycheckboxes[2]" value="2" checked="checked"', $rendered); } /** * Tests the action plugin "eca_form_add_submit_button". */ public function testFormAddSubmitButton(): void { /** @var \Drupal\eca_form\Plugin\Action\FormAddSubmitButton $action */ Loading Loading
modules/form/src/Plugin/Action/FormAddFieldActionBase.php +12 −2 Original line number Diff line number Diff line Loading @@ -67,8 +67,8 @@ abstract class FormAddFieldActionBase extends FormActionBase { if ($this->configuration['description'] !== '') { $field_element['#description'] = $this->tokenServices->replaceClear($this->configuration['description']); } if ($this->configuration['default_value'] !== '') { $field_element['#default_value'] = $this->tokenServices->replaceClear($this->configuration['default_value']); if (trim((string) $this->configuration['default_value']) !== '') { $field_element['#default_value'] = $this->buildDefaultValue(); } return $field_element; } Loading Loading @@ -171,4 +171,14 @@ abstract class FormAddFieldActionBase extends FormActionBase { $this->configuration['default_value'] = $form_state->getValue('default_value'); } /** * Builds up the default value for the form element. * * @return mixed * The default value. */ protected function buildDefaultValue() { return $this->tokenServices->replaceClear($this->configuration['default_value']); } }
modules/form/src/Plugin/Action/FormAddOptionsfield.php +12 −4 Original line number Diff line number Diff line Loading @@ -31,7 +31,7 @@ class FormAddOptionsfield extends FormAddFieldActionBase { $element = parent::buildFieldElement(); // Options will be filled up within ::execute(). $element['#options'] = []; $is_multiple = $this->configuration['multiple']; $is_multiple = (bool) $this->configuration['multiple']; $element['#multiple'] = $is_multiple; if (!$is_multiple && $element['#type'] === 'checkboxes') { $element['#type'] = 'radios'; Loading @@ -39,9 +39,6 @@ class FormAddOptionsfield extends FormAddFieldActionBase { elseif ($is_multiple && $element['#type'] === 'radios') { $element['#type'] = 'checkboxes'; } if ($is_multiple && isset($element['#default_value']) && !is_iterable($element['#default_value'])) { $element['#default_value'] = DataTransferObject::buildArrayFromUserInput((string) $element['#default_value']); } return $element; } Loading Loading @@ -110,4 +107,15 @@ class FormAddOptionsfield extends FormAddFieldActionBase { return $dependencies; } /** * {@inheritdoc} */ protected function buildDefaultValue() { if ($default_options = $this->buildOptionsArray($this->configuration['default_value'])) { $is_multiple = (bool) $this->configuration['multiple']; return $is_multiple ? array_keys($default_options) : key($default_options); } return parent::buildDefaultValue(); } }
modules/form/src/Plugin/Action/FormFieldSetOptionsTrait.php +43 −32 Original line number Diff line number Diff line Loading @@ -58,38 +58,7 @@ trait FormFieldSetOptionsTrait { } } else { $token = $this->tokenServices; $options = (mb_substr($options, 0, 1) === '[') && (mb_substr($options, -1, 1) === ']') && (mb_strlen($options) <= 255) && $token->hasTokenData($options) ? $token->getTokenData($options) : (string) $token->replaceClear($options); $options_array = []; if (is_string($options)) { $options_array = DataTransferObject::buildArrayFromUserInput($options); } elseif (is_iterable($options)) { foreach ($options as $key => $value) { if ($value instanceof EntityAdapter) { $value = $value->getValue(); } if ($value instanceof EntityInterface) { if (!$value->isNew()) { $key = $value->id(); } elseif ($value->uuid()) { $key = $value->uuid(); } $value = (string) $value->label(); } elseif ($value instanceof TypedDataInterface) { $value = $value->getString(); } elseif (is_object($value) && method_exists($value, '__toString')) { $value = (string) $value; } if (is_scalar($value) && trim((string) $value) !== '') { $options_array[$key] = trim((string) $value); } } } $options = $options_array; $options = $this->buildOptionsArray($options); } $element['#options'] = $options; Loading Loading @@ -146,4 +115,46 @@ trait FormFieldSetOptionsTrait { $this->yamlParser = $yaml_parser; } /** * Builds up an array of options, directly usable in a form element. * * @param string $input * The unprocessed configuration input, which may hold a token or a fixed * value, or any other sort of values. */ protected function buildOptionsArray(string $input): array { $token = $this->tokenServices; $options = (mb_substr($input, 0, 1) === '[') && (mb_substr($input, -1, 1) === ']') && (mb_strlen($input) <= 255) && $token->hasTokenData($input) ? $token->getTokenData($input) : (string) $token->replaceClear($input); $options_array = []; if (is_string($options)) { $options_array = DataTransferObject::buildArrayFromUserInput($options); } elseif (is_iterable($options)) { foreach ($options as $key => $value) { if ($value instanceof EntityAdapter) { $value = $value->getValue(); } if ($value instanceof EntityInterface) { if (!$value->isNew()) { $key = $value->id(); } elseif ($value->uuid()) { $key = $value->uuid(); } $value = (string) $value->label(); } elseif ($value instanceof TypedDataInterface) { $value = $value->getString(); } elseif (is_object($value) && method_exists($value, '__toString')) { $value = (string) $value; } if (is_scalar($value) && trim((string) $value) !== '') { $options_array[$key] = trim((string) $value); } } } return $options_array; } }
modules/form/tests/src/Kernel/FormActionsTest.php +120 −1 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ class FormActionsTest extends KernelTestBase { $this->installConfig(static::$modules); User::create(['uid' => 0, 'name' => 'guest'])->save(); User::create(['uid' => 1, 'name' => 'admin'])->save(); User::create(['uid' => 2, 'name' => 'auth'])->save(); // Create the Article content type with a standard body field. /** @var \Drupal\node\NodeTypeInterface $node_type */ Loading Loading @@ -349,7 +350,125 @@ class FormActionsTest extends KernelTestBase { } /** * Tests the action plugin "eca_form_add_optionsfield". * Tests the action plugin "eca_form_add_optionsfield" using checkboxes. */ public function testFormAddCheckboxes(): void { $users = [User::load(0), User::load(1), User::load(2)]; $this->tokenServices->addTokenData('users', $users); /** @var \Drupal\eca_form\Plugin\Action\FormAddOptionsfield $action */ $action = $this->actionManager->createInstance('eca_form_add_optionsfield', [ 'name' => 'mycheckboxes', 'type' => 'checkboxes', 'multiple' => TRUE, 'options' => '[users]', 'default_value' => '1', 'use_yaml' => FALSE, ]); /** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher */ $event_dispatcher = \Drupal::service('event_dispatcher'); $form_builder = \Drupal::formBuilder(); $access_result = NULL; $form = NULL; $event_dispatcher->addListener(FormEvents::PROCESS, function (FormProcess $event) use (&$access_result, &$form, $action) { $action->setEvent($event); $access_result = $access_result ?? $action->access(NULL); if ($action->access(NULL)) { $action->execute(); } $form = $event->getForm(); }); $form_object = \Drupal::entityTypeManager()->getFormObject('node', 'default'); $form_object->setEntity(Node::create([ 'type' => 'article', 'title' => $this->randomMachineName(), ])); $form_state = new FormState(); $build = $form_builder->buildForm($form_object, $form_state); $this->assertTrue($access_result); $this->assertTrue(isset($form['mycheckboxes'])); $this->assertEquals('checkboxes', $form['mycheckboxes']['#type']); $this->assertSame([ '0' => User::load(0)->label(), '1' => User::load(1)->label(), '2' => User::load(2)->label(), ], $form['mycheckboxes']['#options']); /** @var \Drupal\Core\Render\RendererInterface $renderer */ $renderer = \Drupal::service('renderer'); $rendered = $renderer->renderPlain($build); $this->assertStringContainsString('name="mycheckboxes[0]" value="0"', $rendered); $this->assertStringNotContainsString('name="mycheckboxes[0]" value="0" checked="checked"', $rendered); $this->assertStringContainsString('name="mycheckboxes[1]" value="1" checked="checked"', $rendered); $this->assertStringContainsString('name="mycheckboxes[2]" value="2"', $rendered); $this->assertStringNotContainsString('name="mycheckboxes[2]" value="2" checked="checked"', $rendered); } /** * Tests the action plugin "eca_form_add_optionsfield" using checkboxes. * * Default values for the checkboxes are entities. */ public function testFormAddCheckboxesDefaultValueEntities(): void { $users = [User::load(0), User::load(1), User::load(2)]; $this->tokenServices->addTokenData('users', $users); /** @var \Drupal\eca_form\Plugin\Action\FormAddOptionsfield $action */ $action = $this->actionManager->createInstance('eca_form_add_optionsfield', [ 'name' => 'mycheckboxes', 'type' => 'checkboxes', 'multiple' => TRUE, 'options' => '[users]', 'default_value' => '[users]', 'use_yaml' => FALSE, ]); /** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher */ $event_dispatcher = \Drupal::service('event_dispatcher'); $form_builder = \Drupal::formBuilder(); $access_result = NULL; $form = NULL; $event_dispatcher->addListener(FormEvents::PROCESS, function (FormProcess $event) use (&$access_result, &$form, $action) { $action->setEvent($event); $access_result = $access_result ?? $action->access(NULL); if ($action->access(NULL)) { $action->execute(); } $form = $event->getForm(); }); $form_object = \Drupal::entityTypeManager()->getFormObject('node', 'default'); $form_object->setEntity(Node::create([ 'type' => 'article', 'title' => $this->randomMachineName(), ])); $form_state = new FormState(); $build = $form_builder->buildForm($form_object, $form_state); $this->assertTrue($access_result); $this->assertTrue(isset($form['mycheckboxes'])); $this->assertEquals('checkboxes', $form['mycheckboxes']['#type']); $this->assertSame([ '0' => User::load(0)->label(), '1' => User::load(1)->label(), '2' => User::load(2)->label(), ], $form['mycheckboxes']['#options']); /** @var \Drupal\Core\Render\RendererInterface $renderer */ $renderer = \Drupal::service('renderer'); $rendered = $renderer->renderPlain($build); $this->assertStringContainsString('name="mycheckboxes[0]" value="0" checked="checked"', $rendered); $this->assertStringContainsString('name="mycheckboxes[1]" value="1" checked="checked"', $rendered); $this->assertStringContainsString('name="mycheckboxes[2]" value="2" checked="checked"', $rendered); } /** * Tests the action plugin "eca_form_add_submit_button". */ public function testFormAddSubmitButton(): void { /** @var \Drupal\eca_form\Plugin\Action\FormAddSubmitButton $action */ Loading