Last Updated: February 25, 2016
·
2.665K
· timfernihough

Cannot set a fieldCondition for a Domain Access provided field when using EntityFieldQuery

Context:
We have Domain Access installed on a Drupal 7 website and have 8 different subdomains that all have different themes and slightly different business logic. We rely heavily on domain access to determine which nodes are allowed to show on which subdomain.

Specifically for our implementation, we benefit from the following Domain Access features that become available when authoring/editing a node:

  1. Publish to - checkboxes to select which domains have access to the particular node.
  2. Source Domain - either set as "Use Active Domain" or as a specific subdomain. Let's you decide if viewing on a node on one subdomain should redirect to a different one, or if you can just view it on the currently accessed subdomain.

Picture

Problem & Solution:
It looks like when we imported a bunch of nodes of a particular type (~1000), the data wasn't perfect and the "source domain" for some of those nodes was set to a specific subdomain when it was supposed to be set to "Use Active Domain" for all of them.

We of course have no idea how many nodes are set incorrectly until we can write an intelligent query to find out or we check it manually (but no one does that). If the number is high (which it ended up being 103 of 1013), we don't want to manually have to point, click and save to change all of these settings for each node. Instead, we'd want to write an update hook to query for all nodes of this type that have the wrong value set for source domain and update it to the desired one.

Given this is Drupal 7, and I like to be as elegant as possible, I decided to use EntityFieldQuery (an awesome Drupal class you can use to ultimately write mySQL but without actually having to write it). From here on out, I"ll refer to it as EFQ for succinctness.

I was going to use EFQ to grab all nodes of a particular type where the domain_source field is NOT set to -5 (the integer value representing the "use active domain" value) and then set that value to -5.

Tim Cosgrove from the Treehouse Agency wrote a very helpful article on the building blocks of EFQ, which was one of my resources in learning how to do it. I figured the following would work as per the Drupal API:

$query->entityCondition('entity_type', 'node')->entityCondition('bundle', 'my_node_type_name')->fieldCondition('domain_source', 'domain_id', '-5', '=')->execute();

It threw some fatal errors that weren't really helpful in determining the cause and my debugger/stack trace didn't really provide much useful intel either.

Unfortunately, after much painful research and conferring with my colleagues, it seems like EFQ can only interact with "standard" Drupal fields and because Domain Access adds a table in the database called "domainsource" rather than the standard way that other fields are implemented in the database (like **fieldname**), EFQ cannot find it.

I ended up performing my query in a slightly less elegant way using the standard SelectQuery class, but it still works just fine:

$query = db_select('node', 'n');
$query->innerJoin('domain_source', 'd', 'n.nid = d.nid');
$query->addField('n', 'nid');
$query->addField('n', 'type');
$query->addField('d', 'domain_id');
$query->condition('n.type', 'my_node_type_name', '=');
$query->condition('d.domain_id', '-5', '!=');
$result = $query->execute();

Next Steps:
I'm going to review the Domain Access issue queue and see if there are any outstanding issues surrounding this, or perhaps I'm just doing it wrong and its entirely possible to already.

If anyone knows how to do this using EFQ, please let me know. Otherwise, I may consider finding out if a patch can be rolled for Domain Access or for core that can solve this.

1 Response
Add your response

Thanks for this article. Below my code :

$query2 = db_select('node', 'n');

// Gestion du multi-site
if (module_exists('domain')) {
  $domain    = domain_get_domain();
  $domain_id = $domain['domain_id'];
  $query2->innerJoin('domain_access', 'd', 'n.nid = d.nid');
  $query2->condition('d.gid', $domain_id, '=');
}

$query2->addField('n', 'nid');
$query2->condition('n.type', $ws_push_node_type, 'IN');
$query2->orderBy('n.created', 'DESC');
$query2->range(0, 50);
$query2->condition('n.status', 1);

$nids_data = $query2->execute()->fetchAll();
over 1 year ago ·