I have a site with a news content type with a 'published' date field. There's an autocomplete entity reference field on a bean that refers to nodes of this content type, sorted by that field. The attached screenshot might make this a little more clear.

When logged in as an administrator, I'll see multiple nodes when I start typing in the autocomplete field, but when logged in as a user with enough access to create the bean, I'll only see a single node in the autocomplete list, even when I know other nodes should be there.

A little digging seems to implicate EntityReference_SelectionHandler_Generic::ensureBaseTable() in EntityReference_SelectionHandler_Generic.class.php.

That method is called from EntityReference_SelectionHandler_Generic_node::entityFieldQueryAlter() when there is no node_grants implementation and the current user does not have 'bypass node access' permission. This line is the culprit, and it is run in my tests when I'm logged in as the non-admin user:

$base_table = $this->ensureBaseTable($query);

As far as I can tell (EntityFieldQueries are hard to debug), the ensureBaseTable() method accidentally adds a second join to the node table, and the result set is a cartesian product of some kind.

This is the autocomplete list query generated as the admin user:

SELECT field_data_field_published_date0.entity_type AS entity_type, field_data_field_published_date0.entity_id AS entity_id, field_data_field_published_date0.revision_id AS revision_id, field_data_field_published_date0.bundle AS bundle
FROM 
field_data_field_published_date field_data_field_published_date0
INNER JOIN node node ON node.nid = field_data_field_published_date0.entity_id
WHERE  (field_data_field_published_date0.deleted = '0') AND (node.title LIKE '%research%' ESCAPE '\\') AND (field_data_field_published_date0.entity_type = 'node') AND (field_data_field_published_date0.bundle IN  ('cals_news')) 
ORDER BY field_data_field_published_date0.field_published_date_value DESC
LIMIT 10 OFFSET 0

When I run the above query, I get 6 rows back.

And this is the query generated by the user without 'bypass node access'. It has been run through ensureBaseTable() and a second join on the node table is present.

SELECT field_data_field_published_date0.entity_type AS entity_type, field_data_field_published_date0.entity_id AS entity_id, field_data_field_published_date0.revision_id AS revision_id, field_data_field_published_date0.bundle AS bundle
FROM 
field_data_field_published_date field_data_field_published_date0
INNER JOIN node node ON node.nid = field_data_field_published_date0.entity_id
INNER JOIN node node_2 ON node.nid = field_data_field_published_date0.entity_id
WHERE  (field_data_field_published_date0.deleted = '0') AND (node.title LIKE '%research%' ESCAPE '\\') AND (field_data_field_published_date0.entity_type = 'node') AND (field_data_field_published_date0.bundle IN  ('cals_news')) AND (node_2.status = '1') 
ORDER BY field_data_field_published_date0.field_published_date_value DESC
LIMIT 10 OFFSET 0

When I run this query without the LIMIT, I get back over 600 rows. Since the top ten all refer to the same node, my non-admin users end up seeing only that one node.

So my guess is that ensureBaseTable() isn't working right. I haven't dug any deeper than that, and I suspect others may know better than I how to properly detect the base table.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Damien Tournoud’s picture

INNER JOIN node node ON node.nid = field_data_field_published_date0.entity_id
INNER JOIN node node_2 ON node.nid = field_data_field_published_date0.entity_id

The problem is in the condition of the second query. It should be node_2.nid = field_data_field_published_date0.entity_id. As a consequence, the second join matches all the rows of the node table.

Damien Tournoud’s picture

Status: Active » Needs review
Issue tags: +Needs tests
FileSize
754 bytes

Does this help? Obviously we are missing tests on this.

Damien Tournoud’s picture

Priority: Normal » Major
jeffam’s picture

Status: Needs review » Reviewed & tested by the community

That nice, simple patch fixes the issue for me. Thanks!

Damien Tournoud’s picture

Status: Reviewed & tested by the community » Fixed

Merged into 7.x-1.x.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.