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.
Comment | File | Size | Author |
---|---|---|---|
#74 | 2028085-74.patch | 949 bytes | ranjith_kumar_k_u |
| |||
#73 | 2028085-73.patch | 1.18 KB | Abhisheksingh27 |
#72 | 2028085-72.patch | 1.22 KB | kkalashnikov |
#70 | 2028085-nr-bot.txt | 1.19 KB | needs-review-queue-bot |
#68 | list_field_is_empty.png | 2.78 MB | rudrakumar188 |
Comments
Comment #2
jaredsmith CreditAttribution: jaredsmith commentedComment #3
jaredsmith CreditAttribution: jaredsmith commentedComment #4
laurenm CreditAttribution: laurenm commentedi've never committed a patch before so i'm going to give this one a whirl.
Comment #5
laurenm CreditAttribution: laurenm commentedI 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!
Comment #6
jiqiang CreditAttribution: jiqiang commentedI would like to work on this issue.
Comment #7
jiqiang CreditAttribution: jiqiang commentedI am able to reproduce this issue when test a boolean field in field collection.
$is_empty
is always set toFALSE
no matter$field_check_me
has the value 0 or 1.Comment #8
jiqiang CreditAttribution: jiqiang commentedComment #9
jiqiang CreditAttribution: jiqiang commentedComment #11
dcam CreditAttribution: dcam commentedI 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.
Comment #12
jiqiang CreditAttribution: jiqiang commented@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?
Comment #13
skh CreditAttribution: skh commentedAs 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.
Comment #14
skh CreditAttribution: skh commentedComment #15
mgiffordComment #16
smostafa CreditAttribution: smostafa as a volunteer commentedAt the DrupalCon sprint and am looking into this
Comment #17
smostafa CreditAttribution: smostafa as a volunteer commentedThis 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:
Comment #18
dinarcon CreditAttribution: dinarcon commentedUnassigning and changing to appropriate component
Comment #19
lauriiiInstructions on writing a reroll https://www.drupal.org/patch/reroll
Comment #20
dabbor CreditAttribution: dabbor commentedHello, 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.
Comment #21
leeotzu CreditAttribution: leeotzu as a volunteer and at Srijan | A Material+ Company commentedComment #22
leeotzu CreditAttribution: leeotzu as a volunteer and at Srijan | A Material+ Company commentedOn 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.
Comment #23
dabbor CreditAttribution: dabbor commentedHi 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?
Comment #24
lauriiiIt 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.
Comment #26
lauriiiComment #27
tstoecklerI think it would be preferred if the
ListBooleanItem
class would override theisEmpty()
method. Then we don't need an if-else at all.Comment #28
cbanman CreditAttribution: cbanman at Acro Commerce commentedRe-rolled most recent patch.
Comment #29
cbanman CreditAttribution: cbanman at Acro Commerce commentedComment #30
leeotzu CreditAttribution: leeotzu as a volunteer and at Srijan | A Material+ Company commentedreturn value should be typecast to bool instead of (string)
return value should be typecast to bool instead of (string)
Comment #31
chananapeeyush CreditAttribution: chananapeeyush as a volunteer and commentedAddressed #30.Thanks!
Comment #34
dcmul CreditAttribution: dcmul as a volunteer commentedAnother small change.
Comment #35
dcmul CreditAttribution: dcmul as a volunteer commentedComment #36
NitebreedFollowing coding standards, the '(' after the if should have a space before it, like 'if ('
Comment #37
NitebreedComment #38
mgiffordAdding a space. Thanks for pointing that out.
Comment #39
mohit_aghera CreditAttribution: mohit_aghera as a volunteer and at Axelerant commentedFixing code formatting issue.
Comment #40
Sam152 CreditAttribution: Sam152 commentedIs it possible to create a test which fails on HEAD that demonstrates this bug?
Also some feedback:
This is longer than 80 columns.
Comment seems superfluous and is missing a full stop.
The expression doesn't need to the parens and does not need to be cast to bool.
Same here.
Comment #41
snehi CreditAttribution: snehi as a volunteer and at Publicis Sapient for Publicis Sapient commentedDone as suggested.
Comment #42
mgiffordDoes 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.Comment #44
0livier CreditAttribution: 0livier at Alter Way for Michelin Travel Partner commentedD7 version base on https://www.drupal.org/files/issues/list_field_is_empty-2028085-41.patch
Comment #47
aburrows CreditAttribution: aburrows as a volunteer commentedWe'll take this issue at Drupalcon Dublin
Comment #50
mayurjadhav CreditAttribution: mayurjadhav at Blisstering Solutions commentedComment #51
snehi CreditAttribution: snehi as a volunteer and at Publicis Sapient for Publicis Sapient commentedAre we good at this ?
Comment #53
mohit1604 CreditAttribution: mohit1604 at Google Summer of Code commentedAdding test in patch #41 for version 8.5.x :)
Comment #55
izus CreditAttribution: izus commented#41 still applies
Comment #56
kalyansamanta CreditAttribution: kalyansamanta commentedNeeds review
Comment #58
kalyansamanta CreditAttribution: kalyansamanta commentedComment #59
vacho CreditAttribution: vacho at Skilld commentedComment #60
alonaoneill CreditAttribution: alonaoneill at Hook 42 commentedComment #61
vacho CreditAttribution: vacho at Skilld commentedThe patch can apply well on branch 8.6.x and 8.8.x
Comment #63
pradeepjha CreditAttribution: pradeepjha at Srijan | A Material+ Company for Drupal India Association commentedRe-rolling patch for Drupal 8.8.x
Comment #68
rudrakumar188 CreditAttribution: rudrakumar188 at Srijan | A Material+ Company for Drupal India Association commentedThe patch #63 applied successfully and working fine on the current 9.4.x version. Added a screenshot of the patch.
Comment #70
needs-review-queue-bot CreditAttribution: needs-review-queue-bot as a volunteer commentedThe 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.
Comment #71
kkalashnikov CreditAttribution: kkalashnikov as a volunteer and at Srijan | A Material+ Company for Drupal India Association commentedPatch for Drupal version 10.1.x
Comment #72
kkalashnikov CreditAttribution: kkalashnikov as a volunteer and at Srijan | A Material+ Company for Drupal India Association commentedComment #73
Abhisheksingh27 CreditAttribution: Abhisheksingh27 at OpenSense Labs for DrupalFit commentedAdding Reroll for 10.1.x
Comment #74
ranjith_kumar_k_u CreditAttribution: ranjith_kumar_k_u as a volunteer and at Srijan | A Material+ Company for Drupal India Association commentedRe-rolled #63 for 10.1
Comment #75
smustgrave CreditAttribution: smustgrave at Mobomo commentedThis 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