Problem/Motivation

Currently /core/modules/options/src/Plugin/Field/FieldType/ListItemBase::isEmpty() uses the following conditional to test whether a field is empty:

return empty($this->value) && (string) $this->value !== '0';

If the value of the field is also not zero, then it is empty. This seems fine for most list fields, but causes big problems when writing code for Boolean fields. One would reasonably expect this function to return TRUE for a value of 0, which in the context of a single on/off checkbox, is empty. However, this function will always return FALSE for Booleans, whether you pass it 0 or 1.

Proposed resolution

Update conditions for manage boolean fields.

Text of the original report by [venutip ]

Currently, list_field_is_empty() uses the following conditional to test whether a field is empty:

if (empty($item['value']) && (string) $item['value'] !== '0')

In other words, if the empty() function returns TRUE and the string value of the field is also not zero, then it is empty. This seems fine for most list fields, but causes big problems when writing code for Boolean fields. One would reasonably expect this function to return TRUE for a value of 0, which in the context of a single on/off checkbox, is empty. However, this function will always return FALSE for Booleans, whether you pass it 0 or 1.

One place where this causes problems is with field collections. Suppose you have a field collection that consists of two required fields and one optional Boolean (a single on/off checkbox). The field collection module uses the emptiness of the collection to decide whether to enforce validation of required fields. But because list_field_is_empty() always returns FALSE for single on/off checkboxes, the collection can never be considered empty.

The attached patch adds a check to see if we're dealing with a list_boolean field and, if so, considers 0 to be empty.

CommentFileSizeAuthor
#74 2028085-74.patch949 bytesranjith_kumar_k_u
#73 2028085-73.patch1.18 KBAbhisheksingh27
#72 2028085-72.patch1.22 KBkkalashnikov
#71 interdiff_63-71.txt604 byteskkalashnikov
#71 2028085-71.patch1.24 KBkkalashnikov
#70 2028085-nr-bot.txt1.19 KBneeds-review-queue-bot
#68 list_field_is_empty.png2.78 MBrudrakumar188
#63 list_field_is_empty-2028085-63.patch949 bytespradeepjha
#56 2028085-clean-listitembase.patch21.72 KBkalyansamanta
#44 list_field_is_empty-2028085-44-d7.patch886 bytes0livier
#41 interdiff.txt1.05 KBsnehi
#41 list_field_is_empty-2028085-41.patch937 bytessnehi
#39 interdiff-2028085-34-35.txt674 bytesmohit_aghera
#39 list_field_is_empty-2028085-34.patch946 bytesmohit_aghera
#38 list_field_is_empty-2028085-38.patch946 bytesmgifford
#34 list_field_is_empty-2028085-34.patch945 bytesdcmul
#31 interdiff-28-30.txt699 byteschananapeeyush
#31 list_field_is_empty-2028085-30.patch943 byteschananapeeyush
#28 interdiff-23-28.txt1.46 KBcbanman
#28 list_field_is_empty-2028085-28.patch947 bytescbanman
#23 list_field_is_empty-2028085-23.patch930 bytesdabbor
#8 list_field_is_empty-2028085-7.patch643 bytesjiqiang
field-return_true_for_booleans.patch616 bytesvenutip
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Status: Needs review » Needs work

The last submitted patch, field-return_true_for_booleans.patch, failed testing.

jaredsmith’s picture

Issue summary: View changes
Issue tags: +sprint, +Novice
jaredsmith’s picture

laurenm’s picture

Assigned: Unassigned » laurenm

i've never committed a patch before so i'm going to give this one a whirl.

laurenm’s picture

Assigned: laurenm » Unassigned

I am unable to re-produce this issue. Here is what I tried:

1) Made a content type with multiple value boolean field. I let it have up to two values.

2) Created 3 nodes; one with two checked, one with one checked and one with none checked.

3) I wrote some PHP code in Devel that retrieved all three nodes from the database and then tested the results of running list_field_is_empty() on each of them:

$empty = list_field_is_empty($node->field_values['und'][0], 'field_values') ? "empty" : "not empty";

4) Ran the script and the function correctly saw that the first two where not empty and that the last one was.

I would love to continue working on this; would someone be able to send me some steps to reproduce that worked for them?

Thank you!

jiqiang’s picture

Assigned: Unassigned » jiqiang

I would like to work on this issue.

jiqiang’s picture

I am able to reproduce this issue when test a boolean field in field collection.

$entities = entity_load('field_collection_item', array(1));
$entity = reset($entities);
$is_empty = list_field_is_empty($entity->field_check_me['und'][0], 'field_check_me');

$is_empty is always set to FALSE no matter $field_check_me has the value 0 or 1.

jiqiang’s picture

jiqiang’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 8: list_field_is_empty-2028085-7.patch, failed testing.

dcam’s picture

Version: 7.22 » 8.0.x-dev

I checked the Options module in 8.0.x. It looks like this same code still exists there, so it must be fixed in Drupal 8 first.

jiqiang’s picture

@dcam, thanks for your suggestion and I will keep working on it for Drupal 8 first. Now I need to figure it out why my patch was failed by testbot. Can any community member give me some clues?

skh’s picture

As per 1969728, this functionality/check is now in \Drupal\Core\TypedData\Plugin\DataType\Map, and I can confirm that isEmpty() on BooleanItem's is returning TRUE for unchecked boxes. It also appears to function correctly when a new field gets added and there is no value set on an entity for a boolean field.

skh’s picture

Status: Needs work » Needs review
mgifford’s picture

Status: Needs review » Needs work
smostafa’s picture

At the DrupalCon sprint and am looking into this

smostafa’s picture

This issue no longer applies to Drupal 8 since the list module was removed from Core and merged with the Options module: https://www.drupal.org/node/1691614

However the same function seems to exist in D8 at core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php on line 80:

public function isEmpty() {
  return empty($this->value) && (string) $this->value !== '0';
}
dinarcon’s picture

Component: field system » options.module
Assigned: jiqiang » Unassigned

Unassigning and changing to appropriate component

lauriii’s picture

Issue tags: +Needs reroll

Instructions on writing a reroll https://www.drupal.org/patch/reroll

dabbor’s picture

Hello, the patch seems to be really simple to reroll by hand (just one line) by putting it to right location. Plus I can see a what a problem is in the patch so I'll fix it and push new patch soon.

leeotzu’s picture

Assigned: Unassigned » leeotzu
leeotzu’s picture

Assigned: leeotzu » Unassigned

On a second thought isn't isEmpty method of abstract class \Drupal\Core\TypedData\Plugin\DataType\Map which is extended by \Drupal\Core\Field\FieldItemBase responsible for checking that. Why do we need to define a separate method? Unless we are altering the behaviour of method isEmpty.

dabbor’s picture

Hi guys, I've created a patch that should be solving the problem with "list_boolean" type. I wasn't able to test the method ListItemBase::isEmpty() it locally as I would need to play with it (and Drupal 8) more and I have no time for it now. Sorry.

My patch contains if-else clauses instead of one complex line (that is in my opinion not readable enough). I believe that if-else substitution for some &&, || should result in the same performance, but provides more readability (and thus better understanding for future modifications).

One question about best practice: wouldn't be the best to write tests first when someone find a bug that wasn't recognized by any existing test?

lauriii’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll

It would make fixing the bug easier since when we have failing test its easy to see whether the failing test is passing after the fix or not.

Status: Needs review » Needs work

The last submitted patch, 23: list_field_is_empty-2028085-23.patch, failed testing.

lauriii’s picture

Issue tags: +Needs reroll
tstoeckler’s picture

I think it would be preferred if the ListBooleanItem class would override the isEmpty() method. Then we don't need an if-else at all.

cbanman’s picture

Re-rolled most recent patch.

cbanman’s picture

Status: Needs work » Needs review
leeotzu’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php
    @@ -78,7 +78,18 @@ public static function generateSampleValue(FieldDefinitionInterface $field_defin
    +      return (string) $this->value === '0';
    +    }
    

    return value should be typecast to bool instead of (string)

  2. +++ b/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php
    @@ -78,7 +78,18 @@ public static function generateSampleValue(FieldDefinitionInterface $field_defin
    +      return (string) $this->value !== '0';
    

    return value should be typecast to bool instead of (string)

chananapeeyush’s picture

Status: Needs work » Needs review
FileSize
943 bytes
699 bytes

Addressed #30.Thanks!

Status: Needs review » Needs work

The last submitted patch, 31: list_field_is_empty-2028085-30.patch, failed testing.

The last submitted patch, 31: list_field_is_empty-2028085-30.patch, failed testing.

dcmul’s picture

Another small change.

dcmul’s picture

Status: Needs work » Needs review
Nitebreed’s picture

+++ b/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php
@@ -78,7 +78,18 @@ public static function generateSampleValue(FieldDefinitionInterface $field_defin
+    if(!empty($this->value)) {

Following coding standards, the '(' after the if should have a space before it, like 'if ('

Nitebreed’s picture

Status: Needs review » Needs work
mgifford’s picture

Status: Needs work » Needs review
FileSize
946 bytes

Adding a space. Thanks for pointing that out.

mohit_aghera’s picture

Fixing code formatting issue.

Sam152’s picture

Status: Needs review » Needs work

Is it possible to create a test which fails on HEAD that demonstrates this bug?

Also some feedback:

  1. +++ b/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php
    @@ -78,7 +78,18 @@ public static function generateSampleValue(FieldDefinitionInterface $field_defin
    +    // Based on the PHP empty() function the value is not empty, so there's no need to continue.
    

    This is longer than 80 columns.

  2. +++ b/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php
    @@ -78,7 +78,18 @@ public static function generateSampleValue(FieldDefinitionInterface $field_defin
    +    // Type of list_boolean
    

    Comment seems superfluous and is missing a full stop.

  3. +++ b/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php
    @@ -78,7 +78,18 @@ public static function generateSampleValue(FieldDefinitionInterface $field_defin
    +      return (bool) ($this->value == '0');
    

    The expression doesn't need to the parens and does not need to be cast to bool.

  4. +++ b/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php
    @@ -78,7 +78,18 @@ public static function generateSampleValue(FieldDefinitionInterface $field_defin
    +      return (bool) ($this->value != '0');
    

    Same here.

snehi’s picture

Done as suggested.

mgifford’s picture

Does this need the <h3>Why this should be an RC target</h3> info & RC phase evaluation table? Also there's the "rc target triage" tag.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Status: Needs review » Needs work

The last submitted patch, 44: list_field_is_empty-2028085-44-d7.patch, failed testing.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

aburrows’s picture

We'll take this issue at Drupalcon Dublin

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

mayurjadhav’s picture

Issue tags: +DrupalMumbaiCodeSprint
snehi’s picture

Are we good at this ?

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

mohit1604’s picture

Adding test in patch #41 for version 8.5.x :)

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

izus’s picture

Status: Needs work » Needs review

#41 still applies

kalyansamanta’s picture

Status: Needs review » Needs work

The last submitted patch, 56: 2028085-clean-listitembase.patch, failed testing. View results

vacho’s picture

Issue summary: View changes
Status: Needs work » Needs review
Issue tags: -Needs issue summary update
alonaoneill’s picture

Status: Needs review » Needs work
Issue tags: +Needs reroll
vacho’s picture

Issue tags: -Needs reroll

The patch can apply well on branch 8.6.x and 8.8.x

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

pradeepjha’s picture

Re-rolling patch for Drupal 8.8.x

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

rudrakumar188’s picture

FileSize
2.78 MB

The patch #63 applied successfully and working fine on the current 9.4.x version. Added a screenshot of the patch.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
FileSize
1.19 KB

The Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.

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

kkalashnikov’s picture

Patch for Drupal version 10.1.x

kkalashnikov’s picture

FileSize
1.22 KB
Abhisheksingh27’s picture

Status: Needs work » Needs review
FileSize
1.18 KB

Adding Reroll for 10.1.x

ranjith_kumar_k_u’s picture

Re-rolled #63 for 10.1

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs Review Queue Initiative, +Needs tests

This issue is being reviewed by the kind folks in Slack, #needs-review-queue-initiative. We are working to keep the size of Needs Review queue [2700+ issues] to around 400 (1 month or less), following Review a patch or merge request as a guide.

As a bug this will need a test case

Version: 9.5.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.