Field not saved when change of 0 on string start

Created on 1 February 2022, over 2 years ago
Updated 19 May 2024, about 1 month ago

Problem/Motivation

During the modification of a taxonomy term text field by adding or removing a "0" as first character if it is the only change, it isn't saved. The problem is the same with the other entities (Node, User).

Examples :
- Changing 01 to 1, stay 01.
- Changing 1 to 01, stay 1.
- Changing 01 to 2, work 2 is saved.

Steps to reproduce

Create a taxonomy with a text field, create an instance with the value "01" save. Then modify, change the value to 1, save.

Proposed resolution

On the save process, change the equals test to take this 0 into account.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

🐛 Bug report
Status

Needs work

Version

11.0 🔥

Component
Field 

Last updated about 14 hours ago

Created by

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇧🇩Bangladesh eashika

    @nicolas.hod what is your drupal version?
    Tested on 9.5.3 and 10.1.0-dev , could not reproduce. followed the steps mentioned on #3.

  • 🇩🇪Germany mericone

    I am experiencing the same issue as @nicolas.hod described above. It seems as if Drupal or PHP checks the value before saving and ignores a leading zero as a change.

    Drupal 9.5.10, a simple textfield (string) which was used to enter a number with leading 0, no extra field modules installed, PHP 8.1.13

  • 🇦🇺Australia HappyPanda

    I'm also seeing the same bug - in a text field being used for phone numbers attached to user accounts.

  • 🇦🇺Australia HappyPanda

    Update:
    Bug is still there with in the following config:

    Drupal Version: 9.5.10
    Web Server: LiteSpeed
    PHP Version 8.1.18: (more information)
    Memory limit: 1024M
    Database Version: 8.0.33
    System: MySQL, Percona Server, or equivalent

    I've added a text field to users ( /admin/config/people/accounts/fields ) for phone number.

    Using Module: "field formatter pattern" 1.0.0 with the following pattern: "[0-9]{8,10}"
    (Note I have tested without the field formatter pattern and the problem still exists

    To replicate:
    - Add a user, give them a phone number of "12345678". Save
    - Edit that user again.
    - Change the phone number to "012345678". Save.
    - Note that the phone number has not changed and is still "12345678".

  • Hi,

    we're facing the same issue with Text (plain) fields used for phone numbers.

    Drupal 9.5.10
    PHP 8.1.16

  • 🇨🇱Chile mnico Santiago, Chile

    I have a similar problem. With a string field I save the value 100.0 and then edit it to 100, the new value is not saved (the same happens inversely). This occurs only when saving content without creating a new revision.

    This happens to me in Drupal 10.1

    Reviewing the code I found the following:

    In the core/lib/Drupal/Core/Field/FieldItemList.php class there is the "equals" method:

      /**
       * {@inheritdoc}
       */
      public function equals(FieldItemListInterface $list_to_compare) {
        $count1 = count($this);
        $count2 = count($list_to_compare);
        if ($count1 === 0 && $count2 === 0) {
          // Both are empty we can safely assume that it did not change.
          return TRUE;
        }
        if ($count1 !== $count2) {
          // One of them is empty but not the other one so the value changed.
          return FALSE;
        }
        $value1 = $this->getValue();
        $value2 = $list_to_compare->getValue();
        if ($value1 === $value2) {
          return TRUE;
        }
        // If the values are not equal ensure a consistent order of field item
        // properties and remove properties which will not be saved.
        $property_definitions = $this->getFieldDefinition()->getFieldStorageDefinition()->getPropertyDefinitions();
        $non_computed_properties = array_filter($property_definitions, function (DataDefinitionInterface $property) {
          return !$property->isComputed();
        });
        $callback = function (&$value) use ($non_computed_properties) {
          if (is_array($value)) {
            $value = array_intersect_key($value, $non_computed_properties);
    
            // Also filter out properties with a NULL value as they might exist in
            // one field item and not in the other, depending on how the values are
            // set. Do not filter out empty strings or other false-y values as e.g.
            // a NULL or FALSE in a boolean field is not the same.
            $value = array_filter($value, function ($property) {
              return $property !== NULL;
            });
    
            ksort($value);
          }
        };
        array_walk($value1, $callback);
        array_walk($value2, $callback);
    
        return $value1 == $value2;
      }
    
    

    With the previous example we would be comparing at the end:

    $value1 = [
      0 => [
         'value' => 10,
      ],
    ];
    $value2 = [
      0 = > [
         'value' => 10.0,
      ],
    ];
    

    And this would return true, which means it should not be updated. It is solved if "===" is placed but I don't know if this would affect it in general.

  • 🇨🇱Chile mnico Santiago, Chile

    #8 To reproduce this you must update the entity without creating a new revision. Otherwise it will update it.

  • 🇨🇱Chile mnico Santiago, Chile

    The "equals" method would be designed to indicate that the value 2 and '2' (string) are equal. This is according to what I see in the FieldItemListTest tests. For this reason '02' and '2' or '2.0' and '2' would also be considered "equal" when it should not be for the String field in my opinion.

    I think a solution would be that in the "equals" method, transform the values that are numeric to string and end up doing the strict comparison, something like this:

    Index: core/lib/Drupal/Core/Field/FieldItemList.php
    <+>UTF-8
    ===================================================================
    diff --git a/core/lib/Drupal/Core/Field/FieldItemList.php b/core/lib/Drupal/Core/Field/FieldItemList.php
    --- a/core/lib/Drupal/Core/Field/FieldItemList.php	
    +++ b/core/lib/Drupal/Core/Field/FieldItemList.php	(date 1701355884003)
    @@ -416,13 +416,17 @@
               return $property !== NULL;
             });
     
    +        foreach ($value as &$item) {
    +          $item = is_numeric($item) ? (string) $item : $item;
    +        }
    +
             ksort($value);
           }
         };
         array_walk($value1, $callback);
         array_walk($value2, $callback);
     
    -    return $value1 == $value2;
    +    return $value1 === $value2;
       }
     
       /**
    
  • Status changed to Needs review 7 months ago
  • 🇨🇱Chile mnico Santiago, Chile
  • Status changed to Needs work 7 months ago
  • 🇺🇸United States smustgrave

    Can you please update MR to 11.x

    Before anyone opens a new one lets try and update the existing one first.

  • Status changed to Needs review 7 months ago
  • 🇨🇱Chile mnico Santiago, Chile

    My mistake, I tried to update the existing one but I had already created a new one.

  • Status changed to Needs work 7 months ago
  • The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

    This does not mean that the patch needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

    Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

  • We ran into the very same issue.
    Confirmed that 5633.patch works and resolves this issue!

  • 🇦🇺Australia HappyPanda

    Patch 5633 works for me as well, when manually applied to Drupal 9.5.10.
    Thanks!

  • Status changed to Needs review about 1 month ago
  • 🇩🇪Germany akoe

    Patch from MR 5633 works and applied with core 10.2.5 as well as with 11.0.0-alpha1.

  • 🇮🇹Italy robertoperuzzo 🇮🇹 Tezze sul Brenta, VI

    I applied the patch MR 5633 in a Drupal Commerce project (D10.0.11) and I have some problems running our custom Kernel tests. In particular, when we create a commerce_order sample containing a couple of order_items the test fails with the message "Test was run in the child process and ended unexpectedly".

    Debugging with xDebug I get the message "Error: Xdebug has detected a possible infinite loop, and aborted your script with a stack depth of '256' frames".

    I think it is related to the double reference between order and order_item:
    1. in the order we have the entity reference to the order_items

    $fields['order_items'] = BaseFieldDefinition::create('entity_reference')
          ->setLabel(t('Order items'))
          ->setDescription(t('The order items.'))
          ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED)
          ->setSetting('target_type', 'commerce_order_item')
          ->setSetting('handler', 'default')
          ->setDisplayOptions('form', [
            'type' => 'inline_entity_form_complex',
            'weight' => 0,
            'settings' => [
              'override_labels' => TRUE,
              'label_singular' => t('order item'),
              'label_plural' => t('order items'),
              'removed_reference' => 'delete',
            ],
          ])
          ->setDisplayOptions('view', [
            'type' => 'commerce_order_item_table',
            'weight' => 0,
          ])
          ->setDisplayConfigurable('form', TRUE)
          ->setDisplayConfigurable('view', TRUE);
    

    2. in the order_item we have the entity reference to the order

        // The order backreference, populated by Order::postSave().
        $fields['order_id'] = BaseFieldDefinition::create('entity_reference')
          ->setLabel(t('Order'))
          ->setDescription(t('The parent order.'))
          ->setSetting('target_type', 'commerce_order')
          ->setReadOnly(TRUE);
    

    Probably, the recursive walk in the patch

            array_walk_recursive($value, function (&$item) {
              if (is_bool($item)) {
                $item = (int) $item;
              }
              if (is_numeric($item)) {
                $item = (string) $item;
              }
            });
    

    drives crazy the order creation.

  • Status changed to Needs work about 1 month ago
  • The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

    This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

    Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

Production build 0.69.0 2024