I am using hook_node_access() to deny users access to some nodes based on a custom criteria. However, I do not want this content to show up in a view that lists it if the user does not pass the criteria. Is there any way to have views respect hook_node_access() implementations?
3 Answers
hook_node_access() only is invoked when trying to view the full node. What you need to do is implement hook_node_access_records() and hook_node_grants().
Views uses SQL determine the nodes to display. Sadly, for performance reasons it simply would not be feasible for Drupal to perform a node_load on all potential candidates and then call hook_node_access on each one of those of all of them. Imagine a view which shows thousands of nodes (especially when using a pager). If the logic isn't done in SQL then the pagers would have very unusual functionalty thus Drupal forces you do it as rik mentioned using access records in your database.
Making access_records is a fair amount more work but will make it work with SQL. Thus I recommend using an existing node_access module to solve your functionality wherever possible because it will probably be implemented using access records and thus will work with views.
By the way the access records are stored in the table node_access table as seen below:
Through the comments for each column you can get an understanding of their purpose. Think of the realm as the system used for node access and the gid as the group within a realm. That group can have view, update, and delete permissions. In general each node_access module defines one or more realms (sometimes multiple node_access modules can also work in parallel). A user has one or more gids in each of the realms.
In Drupal all queries that have the "node_access" tag will automatically have some special logic added. See the documentation to learn more about tagging. This special logic joins the "node_access" table for each realm and adds the condition that where the "gid" is equal to one of the gids applied to a user, the user has the appropriate permission.
This whole system allows all queries to properly handle node_access, even count queries, etc. It is very powerful but has a higher learning curve that just the simple hook_node_access. Whenever possible, using an existing node_access module can save you this whole headache.
hook_node_access()implementations are not respected. As it is "by design," reporting a work-around is fine.