Problem/Motivation
It is possible to create an entity with label "0". However, this entity will be ignored by the entity autocomplete form element.
Steps to reproduce
Create a new term with name "0". Take any node type and configure a new field that refers to terms. Set any autocomplete widget for this field. Take any node of this type and open the edit form. Input "0" in the field - there are no autocomplete suggestions. After saving the node, the field will remain empty. However, if you input "0 " (trailing space), then the field value will be saved correctly.
Proposed resolution
Do not use empty()
to check the form element value. Do not use the (bool)
cast to check the typed string from the URL.
Comment | File | Size | Author |
---|
Issue fork drupal-3383131
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 3383131-entity-autocomplete-form changes, plain diff MR !5390
Comments
Comment #2
WalkingDexter CreditAttribution: WalkingDexter as a volunteer and at Initlab commentedComment #3
WalkingDexter CreditAttribution: WalkingDexter as a volunteer and at Initlab commentedDrupal 7 also has this problem with taxonomy autocomplete.
Comment #4
WalkingDexter CreditAttribution: WalkingDexter as a volunteer and at Initlab commentedFix for terms without core patch (Drupal 7).
Comment #5
needs-review-queue-bot CreditAttribution: needs-review-queue-bot as a volunteer commentedThe 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.
Comment #6
WalkingDexter CreditAttribution: WalkingDexter as a volunteer and at Initlab commentedComment #7
nod_We can hide patches from the issue summary so that the testbot ignores them if they don't match the issue version.
Comment #8
smustgrave CreditAttribution: smustgrave at Mobomo commentedThank you for reporting.
Can we get a test case showing the issue please
Comment #9
WalkingDexter CreditAttribution: WalkingDexter as a volunteer and at Initlab commentedPatch with tests.
Comment #10
smustgrave CreditAttribution: smustgrave at Mobomo commentedThanks for adding those! For next time super helpful to add a test-only patch with the full patch in that order. So we can see the red/green quickly. But not a big deal!
Ran the tests locally without the fix
testValidEntityAutocompleteElement:
Failed asserting that null matches expected '3'.
Expected :3
Actual :null
testEntityReferenceAutocompletion:
Undefined array key 0
/var/www/html/vendor/symfony/phpunit-bridge/DeprecationErrorHandler.php:104
/var/www/html/web/core/tests/Drupal/KernelTests/Core/Entity/EntityAutocompleteTest.php:137
/var/www/html/web/vendor/phpunit/phpunit/src/Framework/TestResult.php:728
So believe the tests are good.
Issue summary is clearly filled out so I think this is good for RTBC bucket.
Comment #12
smustgrave CreditAttribution: smustgrave at Mobomo commentedSeems unrelated, retesting
Comment #13
xjmOK, this bug is hilarious. Great find!
I'd be surprised if there hasn't already been an issue filed for this, but on the other hand I wasn't able to find one myself in a few minutes of searching. (It's harder because
0
is less than three characters and therefore ignored by d.o's issue search.)My first thought when opening this patch: What about other empty values besides
0
and''
? Let's think through them:NULL
is handled by theisset()
.FALSE
is not an expected value by default. However, the element (like all form data structures) is passed around by reference and alterable at every level by every module under the sun, so theoretically someone could haveFALSE
here for$weird_custom_code_reasons
, in which case this would cause this code path to execute when it did not previously.[]
(which is also a totally conceivable thing for contrib to alter in since entity references can very logically be multivalue.0
,0.0
), but it is a behavior change to start executing this code path for them when we didn't previously.Therefore, I think this should be changed to something along the lines of:
or perhaps:
It should also have an inline comment, because it's non-obvious why we're doing this either way. Or, maybe we could add a method? Something like
isNotEmpty()
or whatever.As above, this should probably be:
or:
Or use the method if we add that.
Based on the above, we should probably also add test coverage for other empty value types.
Thanks!
Comment #14
WalkingDexter CreditAttribution: WalkingDexter as a volunteer and at Initlab commentedGood points! I updated the patch with minor changes -
empty()
is not necessary when the variable is defined.Comment #15
marcoliverThe updated patch in #14 works nicely!
As far as expanding the test coverage goes, would adding this to EntityAutocompleteTest.php suffice?
Comment #16
smustgrave CreditAttribution: smustgrave at Mobomo commented@WalkingDexter fyi please include an interdiff to help see the changes
@marcoliver think that would be good!
Comment #17
WalkingDexter CreditAttribution: WalkingDexter as a volunteer and at Initlab commented@smustgrave Here it is.
Comment #18
xjmComment #19
marcoliver@WalkingDexter Would you mind adding the lines I proposed in #15 (or something similar you like) to your patch / diff? Then we’d also have the expanded test coverage for all the other empty values @xjm suggested in #13.
I’d do it myself, but I don’t have access to a workable setup at this time.
Comment #20
xjmThanks @marcoliver. #15 is a decent suggestion. Usually I'd suggest using a data provider since that is cleaner, but since
core/tests/Drupal/KernelTests/Core/Entity/EntityAutocompleteTest.php
is already a kernel test set up to test many API values with a single test setup, it is more performant to just add code along the lines of what you suggest.Saving issue credits.
Comment #21
allisonherodevs CreditAttribution: allisonherodevs at HeroDevs commentedI added the suggested additional tests per comment #15 to the EntityAutocompleteTest.php file.
Comment #22
allisonherodevs CreditAttribution: allisonherodevs at HeroDevs commentedAdded the tests to a new method instead of an existing method as I should've -- will update with new patch and interdiff shortly.
Comment #23
allisonherodevs CreditAttribution: allisonherodevs at HeroDevs commentedUpdated the wrong method will post updated interdiff and patch shortly.
Comment #24
allisonherodevs CreditAttribution: allisonherodevs at HeroDevs commentedUpdating existing method with test
Comment #25
allisonherodevs CreditAttribution: allisonherodevs at HeroDevs commentedComment #26
smustgrave CreditAttribution: smustgrave at Mobomo commentedCC failure.
Comment #27
WalkingDexter CreditAttribution: WalkingDexter as a volunteer and at Initlab commentedImprovements for tests.
I removed
[]
from the list of empty values because it causes an error:Comment #28
ashley_herodev CreditAttribution: ashley_herodev at HeroDevs commentedThanks at @WalkingDexter, I have added a test-only patch which should fail to prove the test coverage for #27
Comment #30
xjmThanks @allisonherodevs and @ashley_herodev! The test-only patch fails in the expected manner. 👍
I forgot to tell Ashley to re-upload the passing patch after the failing one so that it gets retested instead of that. So doing that here. Not my work, just a little housekeeping. :)
Comment #31
smustgrave CreditAttribution: smustgrave at Mobomo commentedConfirmed additional test in #15 has been added.
Comment #32
lauriiiIt seems that
is_string
withstrlen
or checking explicitly for empty string is how we would check emptiness of strings.I think
!empty($element['#value']) || (is_string($element['#value']) && strlen($element['#value']))
might be more consistent with that.Same here, I don't think we need to hardcode '0' here. We could do either
is_string($input) && $input !== ''
oris_string($input) && strlen($input)
.Comment #33
smustgrave CreditAttribution: smustgrave at Mobomo commentedThink this would be a good task for a novice user
Comment #34
roshni27 CreditAttribution: roshni27 at Valuebound for Drupal Association commentedBased on the comments and suggestions #32, here's the updated code with more explicit checks for empty strings.
Comment #35
smustgrave CreditAttribution: smustgrave at Mobomo commented@roshni27 same post as the other issue thank you for working on it. Looking at your post history believe you can work on non-novice issue now. Novice issues are meant to be reserved for new users. Thanks!
Comment #36
roshni27 CreditAttribution: roshni27 at Valuebound for Drupal Association commentedThank you for your feedback! I appreciate your guidance on the issue categorization. I'll make sure to focus on non-novice issues going forward.
Comment #37
needs-review-queue-bot CreditAttribution: needs-review-queue-bot as a volunteer commentedThe Needs Review Queue Bot tested this issue.
While you are making the above changes, we recommend that you convert this patch to a merge request. Merge requests are preferred over patches. Be sure to hide the old patch files as well. (Converting an issue to a merge request without other contributions to the issue will not receive credit.)
Comment #38
smustgrave CreditAttribution: smustgrave at Mobomo commentedHiding the other patches but I think this one was small enough that patches should still be fine.
Comment #39
xjmThanks @lauriii; that's cleaner.
Checking
isset()
is redundant with!empty()
because!empty()
will always be false ifisset()
is false. So we can remove theisset()
check and simplify the first condition.Comment #40
pradhumanjain2311 CreditAttribution: pradhumanjain2311 at OpenSense Labs for DrupalFit commentedMade changes as per #39
Comment #41
smustgrave CreditAttribution: smustgrave at Mobomo commentedPlease include any patches with an interdiff,
Also encouraged patches be converted to MRs.
Comment #44
ankithashettyRaised an MR as requested.
Also attaching an interdiff of the patches in #34 and #40.
Thanks!
Comment #45
smustgrave CreditAttribution: smustgrave at Mobomo commentedFeedback appears to be have been addressed
Comment #46
xjmAlso remember to queue tests when using patches. Merge requests will queue tests automatically and be much faster.
I queued the tests now, but we have to wait for them to finish running.
Comment #47
xjmAh, I see there is now an MR. Please remember to hide patch files from the IS when opening an MR. Thanks!
Comment #48
xjmChasing my own tail here, re-rebasing after I make other commits. Unfortunately the test-only job only works properly if the MR is rebased against the branch tip. This is a good reason for contributors to run the test-only job before RTBCing.
Comment #49
xjmFinally have the test-only results:
I wonder why
core/tests/Drupal/KernelTests/Core/Entity/EntityAutocompleteTest.php
shows no failures? I would have expected these two assertions to fail:Can someone try it locally?
Comment #50
smustgrave CreditAttribution: smustgrave at Mobomo commentedRan EntityAutocompleteTest ::testEntityReferenceAutocompletion and got
Undefined array key 0
Comment #51
xjmOK, so it seems like a bug in the test-only job then. Thanks @smustgrave!
Comment #52
smustgrave CreditAttribution: smustgrave at Mobomo commentedHaven't review but saw this in the queue #3395977: Test-only changes reverts changes to test modules could be completely unrelated though
Comment #53
xjmThere are no changes to a test module or other such fixture in the MR though.
Comment #54
xjmSaving credits.
Comment #58
xjmI did one more full review of the whole merge request. It looks pretty great!
Committed to 11.x, 10.2.x, and 10.1.x as a patch-safe bugfix. (We were careful to eliminate disruptions by not changing the behavior of empty values other than string-zero.) Thanks everyone for your work on this!
Comment #63
xjmSorry, I realized this morning why the test failure probably wasn't being surfaced correctly. (Let's call it a working illustration of why doing code reviews for 11 hours straight decreases your effectiveness.) The failure in #50 is a notice. We should make the fail more explicit so that an assertion fails -- the test is not working as intended currently.
Reverted to fix that. Thanks!
Comment #65
WalkingDexter CreditAttribution: WalkingDexter as a volunteer commentedComment #66
smustgrave CreditAttribution: smustgrave at Mobomo commentedSeems to have a unit test failure now.
Comment #67
WalkingDexter CreditAttribution: WalkingDexter as a volunteer commentedRebased the source branch, now all tests are passed. The test-only results now show the failure for
core/tests/Drupal/KernelTests/Core/Entity/EntityAutocompleteTest.php
.Comment #68
smustgrave CreditAttribution: smustgrave at Mobomo commentedLGTM
Comment #69
larowlanLeft a question on the MR, feel free to self-RTBC after answering
Comment #70
WalkingDexter CreditAttribution: WalkingDexter as a volunteer commentedComment #72
quietone CreditAttribution: quietone at PreviousNext commentedI'm triaging RTBC issues.
I gather from #58 that this was reverted because the test-only tests did not fail for EntityAutocompleteTest ::testEntityReferenceAutocompletion. When I run the test-only version locally I get that same result as in #59,
That makes sense because it is testing an empty array. Changing the assertion to test against NULL doesn't make sense to me because that is not the real result from
getAutocompleteResult
. A simple assertion that the return value is an array would probably work. But before that I want to revert the last change and rebase.Comment #73
quietone CreditAttribution: quietone at PreviousNext commentedAfter running test-only changes I see the two expected errors, https://git.drupalcode.org/project/drupal/-/jobs/552187. So, that is working now.
Do we think there is a need to assert that getAutocompleteResult() returned an array with two elements?
Comment #74
smustgrave CreditAttribution: smustgrave at Mobomo commentedBelieve thats what is being tested here. Unless I'm misunderstanding.
Comment #77
larowlanCommitted to 11.x and backported to 10.2.x
Thanks all
Comment #79
WalkingDexter CreditAttribution: WalkingDexter as a volunteer commentedShould the status be "Fixed" instead of "Postponed"?
Comment #80
smustgrave CreditAttribution: smustgrave at Mobomo commentedBelieve so as it appears to have been committed to both 11.c and 10.2.x