Problem/Motivation

FormState should provide methods to interact with $form_state['values'].

Proposed resolution

Add get/set/has methods.
Instead of just supporting a scalar key, this should also allow arrays to be passed in, to function like #parents does.


// D7
if (isset($form_state['values']['foo']['bar'])) {
}

// D8
if ($form_state->hasValue(array('foo', 'bar'))) {
}

Remaining tasks

User interface changes

API changes

Comments

tim.plunkett’s picture

Status: Active » Needs review
StatusFileSize
new8.74 KB

This includes the methods, unit tests, and one conversion for each.

tim.plunkett’s picture

Version: 8.x-dev » 8.0.x-dev
Status: Needs work » Needs review
StatusFileSize
new101.04 KB
tim.plunkett’s picture

Status: Needs work » Needs review
StatusFileSize
new101.08 KB
new1.8 KB

Whoops, variable name clash.

larowlan’s picture

Thanks Tim

tim.plunkett’s picture

Status: Needs work » Needs review
StatusFileSize
new371.3 KB
new3.22 KB
tim.plunkett’s picture

Status: Needs work » Needs review
StatusFileSize
new371.4 KB
new1.93 KB
larowlan’s picture

Love the API changes

tim.plunkett’s picture

Status: Needs work » Needs review
StatusFileSize
new414.76 KB
new55.24 KB

Hmmm, I'll need a fresh day to tackle those failures. Here's the remaining changes.

tim.plunkett’s picture

Status: Needs work » Needs review
StatusFileSize
new414.76 KB
new845 bytes

This condition didn't use isset originally, it cares about empty string.

This should be it!

Crell’s picture

Oh geez...

I only looked at FormState{Interface], but it looks reasonable. I was about to suggest using ArrayAccess for the values, as it maps pretty 1:1 to what we're doing there. However, Tim in IRC pointed me at #2310255: [meta] Remove ArrayAccess from FormState, which is sad-making because it means we probably won't be able to do that by release. :-( (107 unique top level keys? Really?)

Otherwise I am +1 here.

jibran’s picture

Title: Add getValue/setValue/hasValue to FormState » Add getValue/setValue/hasValue and isValueEmpty to FormState

Minor doc issues. This also needs change notice then it is RTBC.

+++ b/core/lib/Drupal/Core/Entity/Display/EntityFormDisplayInterface.php
@@ -24,14 +24,14 @@
+   * $form_state->getValues(). A different location within $form_state->getValues()

@@ -91,9 +91,9 @@
+   *   $form_state->getValues(). If not specified, $form['#parents'] is set to an

@@ -144,7 +144,7 @@ public function validateFormValues(ContentEntityInterface $entity, array &$form,
+   *   $form_state->getValues() that have been processed. The remaining entries, if

+++ b/core/lib/Drupal/Core/Field/WidgetInterface.php
@@ -83,7 +83,7 @@ public function settingsSummary();
+   *       $form_state->getValues(), and is used to access processing information

+++ b/core/lib/Drupal/Core/Form/FormBuilder.php
@@ -466,7 +466,7 @@ public function processForm($form_id, &$form, FormStateInterface &$form_state) {
+    // and also storing the values in $form_state->getValues(). We need to retain

+++ b/core/lib/Drupal/Core/Form/FormState.php
@@ -686,7 +719,7 @@ public function setErrorByName($name, $message = '') {
+          // $form_state->getValues() that the clicked button requires to be valid,

+++ b/core/lib/Drupal/Core/Form/FormStateInterface.php
@@ -185,12 +185,79 @@ public function addBuildInfo($property, $value);
+   *   string, it will use $values[$key] = $value. If $key is an array, each element
...
+   *   string, it will use unset($values[$key]). If $key is an array, each element

@@ -254,9 +321,9 @@ public static function hasAnyErrors();
+   * $form_state->getValues() that must contain valid values. Each "section" is an

@@ -278,32 +345,32 @@ public static function hasAnyErrors();
+   *       array('foo', 'bar'), // Validate $form_state->getValue(array('foo', 'bar'))
...
+   * (for example, $form_state->getValue(array('step1', 'choice'))) to be valid, so
...
+   * assume that certain data exists within $form_state->getValues(), and while not

+++ b/core/lib/Drupal/Core/Form/FormValidator.php
@@ -130,17 +130,17 @@ protected function handleErrorsWithLimitedValidation(&$form, FormStateInterface
+        // If the section exists within $form_state->getValues(), even if the value

@@ -194,7 +194,7 @@ protected function finalizeValidation(&$form, FormStateInterface &$form_state, $
+   *   in $form_state->getValues(), though form validation functions are passed an

+++ b/core/lib/Drupal/Core/Form/FormValidatorInterface.php
@@ -39,11 +39,11 @@ public function executeValidateHandlers(&$form, FormStateInterface &$form_state)
+   *   in $form_state->getValues(), though form validation functions are passed an

+++ b/core/modules/file/file.module
@@ -1404,9 +1404,9 @@ function file_managed_file_submit($form, FormStateInterface $form_state) {
+    // $form_state->getValues() must be updated in case additional submit handlers

+++ b/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php
@@ -75,7 +75,7 @@ protected function formMultipleElements(FieldItemListInterface $items, array &$f
+    // in $form_state->getValues() because of validation limitations. Also, they are

more then 80 chars.

tim.plunkett’s picture

StatusFileSize
new14.55 KB
new417.89 KB

Thanks! Fixed and rerolled on top of #2315807: Remove support for path-based form redirects.

jibran’s picture

Status: Needs review » Reviewed & tested by the community

Thank you for the fixes. I have updated change notice https://www.drupal.org/node/2310411/revisions/view/7499617/7513005.

andypost’s picture

Skimmed over the patch and found just a nitpicks

  1. +++ b/core/modules/editor/src/Form/EditorImageDialog.php
    @@ -190,14 +190,15 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
    +      $form_state->setValue(array('attributes', 'src'), $file_url);
    +      $form_state->setValue(array('attributes', 'data-editor-file-uuid'), $file->uuid());
    
    +++ b/core/modules/field/src/Tests/FieldAttachOtherTest.php
    @@ -334,8 +334,8 @@ function testEntityFormDisplayExtractFormValues() {
    +    $form_state->setValue($this->fieldTestData->field_name, $values);
    +    $form_state->setValue($this->fieldTestData->field_name_2, $values_2);
    
    +++ b/core/modules/views/src/Plugin/views/area/Text.php
    @@ -48,8 +48,9 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    +    $form_state->setValue(array('options', 'format'), $content['format']);
    +    $form_state->setValue(array('options', 'content'), $content['value']);
    
    +++ b/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php
    @@ -676,32 +679,33 @@ protected function buildGroupValidate($form, FormStateInterface $form_state) {
    +    $form_state->setValue(array('options', 'group_info', 'default_group_multiple'), array_filter($filter_default_multiple));
    ...
    +    $form_state->setValue(array('options', 'group_info', 'group_items'), $groups);
    

    could use chaining

  2. +++ b/core/modules/entity_reference/src/ConfigurableEntityReferenceItem.php
    @@ -252,9 +252,9 @@ public function instanceSettingsForm(array $form, FormStateInterface $form_state
    +    if ($form_state->hasValue('instance')) {
    +      $form_state->unsetValue(array('instance', 'settings', 'handler_submit'));
    +      $form_state['instance']->settings = $form_state->getValue(array('instance', 'settings'));
    

    maybe out of scope, but suppose better to find a way to get rid of arrayaccess here for $form_state['instance']

tim.plunkett’s picture

@jibran thanks!

@andypost, I don't think anything is really gained by chaining those.
And changing other $form_state keys is absolutely out of scope.

kim.pepper’s picture

+1 from me. Love the DX improvement.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs reroll
git ac https://www.drupal.org/files/issues/form_state-2316533-18.patch
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  417k  100  417k    0     0   668k      0 --:--:-- --:--:-- --:--:-- 1536k
error: patch failed: core/modules/views/src/Plugin/views/pager/SqlBase.php:201
error: core/modules/views/src/Plugin/views/pager/SqlBase.php: patch does not apply
tim.plunkett’s picture

Status: Needs work » Reviewed & tested by the community
Issue tags: -Needs reroll
StatusFileSize
new417.97 KB

git rebase handled that, no changes.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed 8196034 and pushed to 8.0.x. Thanks!

diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php
index 5e0ee40..d3a3084 100644
--- a/core/lib/Drupal/Core/Form/FormBuilder.php
+++ b/core/lib/Drupal/Core/Form/FormBuilder.php
@@ -386,7 +386,7 @@ public function submitForm($form_arg, FormStateInterface &$form_state) {
     // the form, to be consistent with what self::buildForm() does for
     // non-programmatic submissions (form builder functions may expect it to be
     // there).
-    $form_state->set('input', $form_state->get('values'));
+    $form_state->set('input', $form_state->getValues());
 
     $form_state->set('programmed', TRUE);
 

  • alexpott committed 8196034 on 8.0.x
    Issue #2316533 by tim.plunkett: Add getValue/setValue/hasValue and...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

gisle’s picture

Deleted contents of spam pdf.