The Views selection handler for entity reference autocomplete is not properly doing exact matches with typed in input.
Step to reproduce
1. Create 2 articles with title "dog" and "dog cat"
2. Create an entity reference field on some entity, and configure it to use a views selection handler, with a view showing all articles
3. Edit the entity, and type "dog" into the ER autocomplete field. Do NOT pick either "dog" or "dog cat" from the autocomplete dropdown.
4. Save the entity.
5. See the error "Multiple entities match this reference"
This should not happen - exact matches should be accepted when typed in, as they are when using the "Default" selection handler.
Cause
views\src\Plugin\views\display\EntityReference.php -> query() is failing to properly handle the '=' match operator that the autocomplete widget passes when executing a view to evaluate typed in values for matches with existing entities.
$value = db_like($options['match']) . '%';
if ($options['match_operator'] != 'STARTS_WITH') {
$value = '%' . $value;
}
Even when $match_operator is '=', this code results in "LIKE $value%", which does not return only exact matches. And therefore the view contains not just "dog" but "dog cat" also, and the autocomplete widget throws the "Multiple entities match" warning.
Comment | File | Size | Author |
---|---|---|---|
#22 | interdiff-2809555-16-22.txt | 3.28 KB | jonathanshaw |
#22 | 2809555-22.patch | 3.72 KB | jonathanshaw |
Comments
Comment #2
jonathanshawTest and fix.
Comment #3
jonathanshawComment #4
jonathanshawComment #7
jonathanshawSlightly simplified, and rebased.
Comment #8
jonathanshawComment #11
jonathanshawComment #12
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedThe patch looks good but I wonder how can you get in this situation since the widgets provided by core only gives you two options: STARTS_WITH and CONTAINS.
Comment #13
jonathanshawThanks for the review!
drupal/core/lib/Drupal/Core/Entity/Element/EntityAutocomplete.php contains
and then drupal/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php has
So while the sitebuilder can only choose 'Starts with' or 'Contains' to affect what is displayed in the dropdown, the API (correctly) uses '=' to evaluate input typed in by authors who ignore the dropdown.
The steps to reproduce from the IS work on simplytest.me.
Comment #14
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedRight, that makes sense. Thanks for the explanation :)
Comment #15
alexpottThis is a behaviour change for things that pass something other than STARTS_WITH, CONTAINS or =. I think the behaviour should be completely different for =. And we shouldn't change the behaviour for things only than what is used by core - just in case something in contrib is doing something weird.
Comment #16
alexpottSomething like this.
Comment #17
jonathanshawAgreed, thanks for that.
Comment #19
jonathanshawTest fail looks unrelated.
Comment #20
catchWhile this stops inexact matches being made, it also makes the search case sensitive. Shouldn't the operator still be LIKE but with no wildcard after the string?
The test coverage only includes a lower case string, so wouldn't catch this.
Comment #21
LendudeBriefly discussed with @jonathanjfshaw on IRC.
Also see #2784739: Fix PostgreSQL operator in views and #2664530: Views Combined fields filter with "Contains any word" or "Contains all words" operator results in an incorrect SQL query and a fatal error
Replace db_like() with Database::getConnection()->escapeLike($string)
Also change the LIKE statements to use Connection::mapConditionOperator.
Since this is also not currently done, this might be something to do in a followup, but if we want to address the case sensitivity this might be needed here anyway.
Comment #22
jonathanshawI've switched the '=' to 'LIKE' and modified the tests to check for case insensitivity.
I haven't done these here as seems not needed here, and they are already in scope for #2784739: Fix PostgreSQL operator in views .
Comment #23
Lendude@jonathanjfshaw I agree, the db_like can be removed in #2784739: Fix PostgreSQL operator in views.
tiny nitpick, indent too big.
Comment #25
catchCommitted/pushed to 8.3.x and cherry-picked to 8.2.x. Thanks!