Not long ago I've found this gorgeous tool in Drupal, called EntityFieldQuery. This handy facet class creates you queries on entities using various filters and conditions. It's an ultimate entity crawler, not more, not less.
The mechanism is very straightforward, however makes a bit of a headache the first time, so let me explain you the basics. You need to instantiate the class first:
$query = new EntityFieldQuery();
Now you can use the wide range of conditions - first let's see what we've got regarding the entity:
$query->entityCondition($name, $value[, $operator]);
Entity attributes are the 'bundle', 'entity_type' or 'entity_id', etc.:
Next category is the properties of an entity by using:
$query->propertyCondition($column, $value[, $operator]);
To know the properties you either check the entity definition of the certain type or you already know the famous ones (for node, user, term ...), such as node title or node author.
Next one is almost the what makes it so great - the field conditions, where you can define certain filters to field values:
$query->fieldCondition($field, [$column, $value, $operator, $delta_group, $language_group]);
To make it really query like you have some well known helpers, such as the range definition, ordering or counting:
$query->range(0, 10); $query->propertyOrderBy($column[, $direction]); $query->count();
Yeah, *pheh* so easy. But now comes Gandalf. You had the SQL rewrite mechanism in the DB api and you want it here too. Here it's called addMetaData and addTag:
$query->addMetaData($key, $object); $query->addTag($tag);
Let me quote the hilarious specs of the addMetaData function:
Adds additional metadata to the query.
Sometimes a query may need to provide additional contextual data for the alter hook. The alter hook implementations may then use that information to decide if and how to take action.
You definitely need a little bit of research to map the possibilities of the function. But it worth. First it could add user authority to the query. It works most of the time. The rest you need a little extra - that's where addTag comes handy. To get the options you can check the hook_query_TAG_alter. Here you can see there is a core implementation for node_access.
So to summarize my finding today - the way you build up a nice node query that checks if the user has view access to the node comes this way:
global $user; $query = new EntityFieldQuery(); $query->entityCondition('entity_type', 'node') ->entityCondition('bundle', 'article') ->propertyCondition('status', NODE_PUBLISHED) ->range(0, 10) ->addTag('node_access') ->addMetaData('account', $user);
In a nutshell I think EntityFieldQuery is beautiful and incredibly useful.
You can find much better helps and tutorials about it on drupal.org and Treehouse Agency.
Any mysterious extra for the API you know and I missed?